Learn Terraform - Deploy an App Service instead of a scale set

As mentioned in my post before, it is no so easy as a beginner to get everything realized in Terraform. The challenge was, deploy to a web site in Azure which is able to scale out behind a load balancer. After demonstrating the way be using virtual machine scale sets, I would like to show the way I found with Azure App Services as the service to go to.

If you take a look at the simple sample in the documentation, you see that it is very easy to deploy a simple website in azure. Out of this, my idea was, it could not be so complicated in Terraform to achieve the same.

So let’s get started with our script and define the provider and resource group:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
## Lets start with an app service in Azure
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"
}
}

That’s pretty much the same, as in the other posts. The only thing I changed was the version of the provider. You can always check the latest version in the GitHub repo releases section for the provider.

For an App Service, we need an “App Service Plan“.

1
2
3
4
5
6
7
8
9
10
11
### 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"
}
}

Which SKU to choose depends on the features needed. You can check the possible options in the DOCs. As soon as we have an App Service Plan, we can define our App Service:

1
2
3
4
5
6
7
## The 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
}

Until this point, it was pretty much straight forward. My plan was now, to point to a simple web site that is provided by one of my GitHub repos. So use GitHub as the deployment source for my Web App. In the Azure portal it is very simple to configure:

Reading the documentation of the resource “azurerm_app_service”, I found out that there is the section of the site_config to configure the scm_type. But I did not find an option to define the “repo_url” and “branch”. It seems to be possible to read these attributes from an existing App Service, but I did not find a way to define it. After a little bit of research, I found out that this seems to be work in progress and not finished til now.

So I found another way to implement the connection to my GitHub hosted website code. There is an option to deploy an ARM template in a Terraform script. And that’s the way how I made my challenge.

Starting with the following ARM template to define the source code for my App Service deployment:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
{
"$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": "The name of you Web Site."
}
},
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]",
"metadata": {
"description": "Location for all resources."
}
},
"repoURL": {
"type": "string",
"defaultValue": "https://github.com/nielsophey/simplewebsite",
"metadata": {
"description": "The URL for the GitHub repository that contains the project to deploy."
}
},
"branch": {
"type": "string",
"defaultValue": "master",
"metadata": {
"description": "The branch of the GitHub repository to use."
}
}
},
"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": {}
}

I saved the template in the same folder as my Terraform script under appservice.json and added the following code to my Terraform script:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
## Deploy the Deployment option by ARM Template
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 the appservice.json is the definition of the GitHub repo and the needed branch. I set the two parameters as default so that I only need to define the App Service name and location for the ARM template to work probably.

So finally I got my web site up and running:

I totally agree that the chosen way is not the best way to deploy a simple App Services like this, but it was a great learning curve for me. I understand to check the issues, pull requests and release notes in GitHub for the Terraform Azure provider. As well as I learned how to read the documentation of the Terraform resources.

Also I hope, that the resource “azurerm_app_service_source_control” or something equal to that, will be available soon so that we do not need the way via ARM template anymore.

The two scripts can be found on my GitHub Repo for all these samples.