Wie in meinem vorherigen Beitrag erwähnt, ist es als Anfänger nicht so einfach, alles in Terraform umzusetzen. Die Herausforderung war, eine Website in Azure bereitzustellen, die hinter einem Load Balancer skalieren kann. Nach der Demonstration mit Virtual Machine Scale Sets möchte ich den Weg zeigen, den ich mit Azure App Services gefunden habe.

Wenn man sich das einfache Beispiel in der Dokumentation ansieht, erkennt man, dass es sehr einfach ist, eine Website in Azure bereitzustellen. Daraus entstand meine Idee: Es kann doch nicht so kompliziert in Terraform sein.

Also starten wir mit unserem Skript und definieren Provider und Resource Group:

## App Service in Azure bereitstellen
provider "azurerm" {
    version = "~>2.3.0"
    features {}
}

### Resource Group
resource "azurerm_resource_group" "rg" {
  name     = "rg-appservice-test"
  location = "West Europe"
  tags = {
      App = "appservice"
      Source = "Terraform"
  }
}

Das ist im Wesentlichen das Gleiche wie in den anderen Beiträgen. Das Einzige, was ich geändert habe, ist die Version des Providers. Die neueste Version kann man immer im GitHub-Repo-Releases-Bereich des Providers prüfen.

Für einen App Service brauchen wir einen “App Service Plan”:

### App Service Plan
resource "azurerm_app_service_plan" "appservice" {
  name                = "azapp-plan-eastus-001"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name

  sku {
    tier = "Standard"
    size = "S1"
  }
}

Welche SKU man wählt, hängt von den benötigten Features ab. Die Optionen findet man in den Docs. Sobald wir einen App Service Plan haben, können wir unseren App Service definieren:

## Der App Service 
resource "azurerm_app_service" "appservice" {
  name                = "azapp-appservice-test-001"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  app_service_plan_id = azurerm_app_service_plan.appservice.id
 }

Bis hierhin war alles recht geradlinig. Mein Plan war, auf eine einfache Website aus einem meiner GitHub-Repos zu verweisen – also GitHub als Deployment-Quelle für meine Web App zu nutzen. Im Azure-Portal ist das sehr einfach zu konfigurieren:

Git-Deploy App Service

Beim Lesen der Dokumentation der Ressource “azurerm_app_service” fand ich heraus, dass es im Abschnitt site_config die Möglichkeit gibt, den scm_type zu konfigurieren. Allerdings fand ich keine Option zur Definition von “repo_url” und “branch”. Es scheint möglich zu sein, diese Attribute von einem bestehenden App Service zu lesen, aber ich fand keinen Weg, sie zu definieren. Nach etwas Recherche stellte ich fest, dass dies in Arbeit ist.

Also fand ich einen anderen Weg: Man kann ein ARM-Template in einem Terraform-Skript bereitstellen. Und genau so habe ich meine Herausforderung gelöst.

Das folgende ARM-Template definiert den Quellcode für die App-Service-Bereitstellung:

{
    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "siteName": {
           "type": "string",
           "defaultValue": "[concat('WebApp-', uniqueString(resourceGroup().id))]",
            "metadata": {
                "description": "Der Name der Web-App."
            }
        },
        "location": {
            "type": "string",
            "defaultValue": "[resourceGroup().location]",
            "metadata": {
                "description": "Standort für alle Ressourcen."
            }
        },
        "repoURL": {
            "type": "string",
            "defaultValue": "https://github.com/nielsophey/simplewebsite",
            "metadata": {
                "description": "Die URL des GitHub-Repositories mit dem zu deployenden Projekt."
            }
        },
        "branch": {
            "type": "string",
            "defaultValue": "master",
            "metadata": {
                "description": "Der Branch des GitHub-Repositories."
            }
        }
    },
    "variables": {},
    "resources": [
            {
                "type": "Microsoft.Web/sites",
                "apiVersion": "2018-02-01",
                "name": "[parameters('siteName')]",
                "location": "[parameters('location')]",
                "properties": {},
                "resources": [
                    {
                        "type": "sourcecontrols",
                        "apiVersion": "2018-02-01",
                        "name": "web",
                        "location": "[parameters('location')]",
                        "dependsOn": [
                            "[resourceId('Microsoft.Web/sites', parameters('siteName'))]"
                        ],
                        "properties": {
                            "repoUrl": "[parameters('repoURL')]",
                            "branch": "[parameters('branch')]",
                            "isManualIntegration": true
                        }
                    }
                ]
            }
       ],
    "outputs": {}
}

Ich speicherte das Template im gleichen Ordner wie das Terraform-Skript unter appservice.json und fügte folgenden Code hinzu:

## Deployment-Option per ARM-Template bereitstellen
resource "azurerm_template_deployment" "appservice" {
    name                    = "arm-appservice-template"
    resource_group_name     = azurerm_resource_group.rg.name

    template_body = file("appservice.json")

    parameters = {
        "siteName" = azurerm_app_service.appservice.name
        "location" = azurerm_resource_group.rg.location
    }

    deployment_mode = "Incremental"
}

In der appservice.json sind das GitHub-Repo und der benötigte Branch definiert. Ich habe die beiden Parameter als Standard gesetzt, sodass nur der App-Service-Name und der Standort für das ARM-Template definiert werden müssen.

Und am Ende lief meine Website:

Hello World Website

Ich stimme zu, dass der gewählte Weg nicht der beste ist, um einen einfachen App Service bereitzustellen, aber es war eine großartige Lernkurve. Ich habe gelernt, die Issues, Pull Requests und Release Notes auf GitHub für den Terraform Azure Provider zu prüfen. Außerdem habe ich gelernt, die Dokumentation der Terraform-Ressourcen richtig zu lesen.

Ich hoffe auch, dass die Ressource “azurerm_app_service_source_control” bald verfügbar sein wird, damit wir den Umweg über ARM-Templates nicht mehr benötigen.

Die beiden Skripte findet ihr in meinem GitHub-Repo für alle diese Beispiele.