Refactored - Top Rated Cloud Training

View Original

IaaS and PaaS Deployments with Terraform on Azure

In this article, I want to introduce you to Terraform, an Infrastructure as Code solution, helping in optimizing your Azure Resources deployments.  

This article will be part of a 3-article-series:  
 
a) Getting started with Terraform,  
b) Guiding you through an Azure Linux Virtual Machine deployment,  
c) Closing with a more complex deployment of a mixed IaaS and PaaS scenario on Azure.  

The following topics will be discussed in this third article: 

  • Terraform template of Azure WebApps for Containers 

  • Terraform authentication options 

  • Terraform as part of your CI/CD Pipeline DevOps deployments 

Terraform Template to deploy Azure WebApps (for Containers) 

If you read through the first and second article in this series on Terraform on Azure, you should be familiar with the syntax, the flow and validation of your deployments, all driven from the Terraform executable. 

In the previous article, you learned about the template syntax to deploy Azure Virtual Machine infrastructure, deploying the Virtual Network and subnet, the Virtual Disk and Virtual Machine itself. To show you that it is not only possible to deploy “infrastructure” out of infrastructure as code, I will walk you through another example, deploying an Azure WebApp App Service instance. And at the same time, introduction you to Azure WebApp for Containers, where – instead of publishing application source code, you run a Docker container. 

The sample Terraform template can be picked up here:
https://github.com/pdtit/TerraformTemplates/blob/main/webapp4containers/webapp4containers.tf

You could save this into its own subfolder “TFwebapp” or similar on your local machine.  

Let me again describe some of the template syntax: 
Lines 1-6

This is where you define the Terraform Azure Provider, and what specific provider version you want to use. (In most cases, these will always be the first lines in your Terraform template).

Line 7-12

This contains the section where you define the settings for the new Resource Group creation. You call out the azurerm_resource_group resource type from the AzureRM Terraform Provider, and define the required parameters name and location.

Line 13-31

Here, you declare all the settings for the creation of an Azure App Service Plan, in our scenario for an underlying Linux-based infrastructure.  

Notice how the name, location and Resource Group name are referring to Terraform variables, picking up the information from the Resource Group defined earlier in the template. 

Line 32-39

This section contains the details for the actual Azure App Service itself, by calling out the azurerm_app_service resource type. And we are again reusing the variables from before.

Lines 53-61

In this last section, we provide the Docker container information; the Microsoft/aci-helloworld is a sample container, showing a basic HTML web page, with the Azure Container Instance logo. (if you want to see a more business-ready web application in action, you can use one of my sample containers pdetender/simplcommerce, which is an open source webshop application. Where line 55 should look like this instead:

linux_fx_version = "DOCKER|pdetender/simplcommerce:latest"

Notice I skipped lines 43-51; these are the reference placeholder lines if you would use your own Azure Container Registry as a Docker container repository. Since we are using the public Docker Hub repository (in line 55), we don’t need that information. But feel free to try if you should have an ACR available. 

 From here, open your command prompt to the subfolder where you saved the Terraform template file, and kick off the deployment, using the sequence described in the previous article: 

  • Terraform init

  • Terraform plan

  •  Terraform apply -auto-approve  

And checking from the Azure Portal, you can see there is a Resource Group “pdtsamplecontwebapp” deployed, having the following resources:

Open the “pdtsamplecontwebapp” App Service, and notice the URL:

Click the URL, which will open the web page in your browser:

Another successful Terraform template deployment, having created a resource group, Azure Web App for Containers instance, and picked up the container from the public Docker Hub.

Terraform Authentication 

Up till now, you have used Terraform from a “pre-authenticated” command prompt, or maybe you ran the deployments directly from the Azure Cloud Shell (see article 1 for details). 

Out of a broader Infrastructure as Code and DevOps perspective, using a pre-authenticated session doesn’t feel automation friendly, so I want to guide you through other ways to get your Terraform authenticating to Azure, and still run successful deployments. 

In short, one can authenticate in 3 different ways to Azure: 

  • Interactive logon (what you used earlier) 

  • App Registration or Service Principal 

  • Managed Identity 

https://www.terraform.io/docs/providers/azurerm/guides/service_principal_client_secret.html

Option a) is what you are probably most familiar with, connecting to the Azure Portal and providing your credentials, or running “az login” from Azure CLI or running “az-connectaccount” from PowerShell. 

Option b) and c) are about similar on concept, but slightly different in use case. In these scenarios, an Azure Active Directory identity object gets created. Which later on, can be reused to perform authenticated tasks (like running a Terraform deployment 😊).  

A Service Principal is like a service account you create yourself, where a Managed Identity is always linked to an Azure Resource. For example, you can have an Azure Virtual Machine, an Azure Web App, an Azure Storage Account,… and “turn that into” an identity object.  

I’ll guide you through the creation of an Azure Service Principal, and show you how it integrates with Terraform: 

  • From Azure Cloud Shell, run the following command:

az ad sp create-for-rbac --name “terraformsp”

Now, reusing the outcome of this Azure AD Identity resource, within your Terraform template, is possible in 2 different ways: 

  1. Integrating the credential information directly into each Terraform.TF file 

  2. Store the credentials in a Terraform.TFVars file and share it across different deployments 

Here is a snippet of an existing Terraform template, having the Service Principal information in there: 

The Terraform Azure Provider will recognize the variables subscription_id, client_id, client_secret and tenant_id, and reuse those for this individual template deployment.

Integrating Terraform in your CI/CD Pipelines

In this last section, I want to introduce you to an end-to-end DevOps scenario, by integrating the Terraform sequence for deployments, into your CI/CD Pipelines.  

I’ll be using Azure DevOps (https://dev.azure.com) in this example, but the concept is the same for other DevOps tools like Jenkins, TeamCity, GitLab,… 

Any of these tools, wraps a CI/CD Pipeline around a sequence of tasks, with – depending on the tool – some additional intelligence. Important here is the sequence of tasksbecause that’s exactly what Terraform does, looping through init -> plan -> apply. So it already uses this “devops flow” out of the box. 

Here is an example how to make this happen in Azure DevOps: 

  • Assumptions:  

  • You have an Azure DevOps environment up and running and have necessary access permissions  

  • You have an Azure subscription, allowing you to deploy Azure resources 

  • You have an Azure DevOps project defined 

  • You have your application and Terraform template source code in Azure Repos (or any other Git compatible repository) 

1. From Azure DevOps / Pipelines / Select Release; specify your “Azure Repos” as Artifacts (where it recognizes your app source files and/or Template files, depending what you want to deploy) 

2.  Select Stage, which is where you define your task list

3. Which could look similar to the above example in my environment:  

  • Read out some information about Azure using Azure CLI 

  • Read out some information about Azure storage using Azure PowerShell 

  • Store the outcome of a) and b) into Terraform variables 

  • Install Terraform 

  • Run Terraform init + plan + apply (with auto-approve) 

  • This will deploy the Azure Resources, e.g. the webapp from our earlier example 

  • The last step here is where I am publishing a webdeploy.zip (artifacts) into my Azure WebApp, which got deployed through Terraform. 

Summary

This is the end of our 3-series article on enabling Terraform for Azure, where we started with describing the benefits of Terraform compared to ARM templates, guided you through the Terraform syntax (article 1) and authoring template for a Linux VM (article 2) as well as a WebApp with Containers (article 3), and how to optimize authentication and integrate Terraform in (Azure) DevOps Pipelines. 

I hope you enjoyed the series, learned from it. If you need some additional guidance, have a look at our Terraform courses:

Terraform for Azure an Introduction
Terraform for Azure
Coming Soon - Terraform on Azure with Nick Colyer and Peter De Tender