Infrastructure as Code in Microsoft Azure met Terraform
*Infrastructure as Code* is een manier om wijzigingen in je infrastrctuur te automatiseren, gebruikmakend van configuratie bestanden in je repository.
Deze blogpost introduceert de beginselen van Infrastructure as Code (IaC) in Microsoft Azure Services en ook de tool Terraform.
De post geeft een korte indruk van enkele zaken, allereerst een korte theoretische introductie van IaC. Daarna duiken we in de voordelen van IaC vergeleken met de "gebruikelijke" manier om infrastructure te beheren in Azure. Tot slot do ik een stap voor stap implementatie van IaC in de Microsoft Azure stack met de tool Terraform, via lab onderzoek (Bonestroo et al., 2018).
Kennis maken met IaC
Om te beginnen: Infrastructure as Code is het proces van het vervangen van handmatige stappen voor het maken en beheren van infrastructure met regels code (Workfall, 2021). Deze noemt met vaak configuratiebestanden of resources. Deze resources kunnen elk stuk infrastructure in a bepaalde omgeving maken, bijvoorbeeld een virtuele machine, een database, of — in de context van Azure — een logic app of service bus.
Infrastructure as code workflow (DigitalOcean, 2021)
Gebruik en voordelen van IaC
Er zijn een aantal voordelen van het gebruik van IaC, waarvan de voornaamste is dat het een efficiente en consistente manier is om infrastructuur te definieren en beheren.
Versiebeheer
Het definieren van infrastructuur resources maakt het mogelijk om wijzigingen te en toevoegingen aan de infrastructuur bij te houden in versiebeheer. Het gevolg is een historie van wijzigingen in je infrastructuur, waarnaar je makkelijk een rollback kunt doen in geval van een fout of niet werkend systeem.
Ook is het mogelijk om de wijzigingen in je infrastructuur te inspecteren en controleren voordat je daadwerkelijke oplevert.
Documentatie
Deze bestanden kunnen ook dienen als documentatie, aangezien de bestanden een specificatie zijn van de state (toestand) en opmaak van de services op een leesbare manier.
Snelheid
Ook is het op deze manier specificeren van je infrastructuur een stuk sneller. Vooral als je te maken hebt met een zeer uitgebreide infrastructuur, is het simpelweg niet mogelijk om alles te behren via een grafische user interface. Niet DevOps teams hebben het nog zwaarder te verduren, aangezien developers moeten wachten op een apart ops team om de benodigde infrastructure in de lucht te brengen (SDxCentral, 2021).
Je kunt makkelijk delen van IaC bestanden hergebruiken om specifieke services op te schalen.
Automatisering
Bovendien kunnen tools zoals Terraformje in staat stellen jr process te automatiseren. Je kan een IaC configuratie wijzigen of toevoegen. Daarna kun je de deployment van de wijzingen integreren in je CI/CD pipeline om deze naar een cloud provider naar keuze op te leveren.
Best practices with IaC
Voordat je IaC toepast is het goed om te een paar best practices te kennen om je aan te houden. Ik heb enkele van deze practices hieronder opgesoms, welke ik het meest waardevol vindt.
Documenting
When using infrastructure as code your configuration files will essentially be your documentation (Chan, 2021). This doesn't mean you shouldn't write any documentation at all!
In complexe landschappen kunnen diagrammen heel waardevol zijn. In sommige gevallen is een snelle blik op een overzicht / diagram meer waard dan de gehele structuur van de configuratie file te bestuderen.
Keep it simple, keep it modular
Het is een best practice om de configuratiebestanden simpel te houden en makkelijk te lezen. Op die manier kunnen andere developers makkelijk up to speed komen met de infrastructuur configuratie.
Dit kun je bijvoorbeeld doen door te modulatiseren. Als je de configuratie modulair houdt, dan kun je elementen hergebruiken, wat voor een consistente file structure zorgt (Xenonstack, 2021).
Mutable of immutable
Een mutable infrastructure betekent dat je wijzigingen kunt toepassen op je infrastructure terwijl deze al up and running is. Het hanteren van mutable infrastructure zorgt ervoor dat individuele wijzigingen aan je cluster kunnen zorgen voor configuration drift, waarbij een cluster stapsgewijs steeds meer afwijkt over de tijd, als gevolg vn de handmatige wijzigingen (Pelletier, 2020).
Sommigen argumenteren dat een betere manier om met wijzigingen om te gaan is met Immutable Infrastructure. Dit betekent de infrastructure die runt weggooien en deze volledig vervangen als je een wijziging deployed. Zo sta je toe om vorige configurations op te slaan als versies, en makkelijk opnieuw te deployen op basis van een versie van de infrastructuur (Vasiljevic, 2021).
Mutable vs immutable (Vasiljevic, 2021)
Implementing IaC
Er is een heel scale van tools die je kunt gebruiken voor IaC. In dit geval focussen we op Terraform. Aangezien je Terraform kunt integreren met een veelheid aan cloud service providers.
Overzicht van de workflow van Terraform (Hashicorp, 2021)
Implementing IaC with Terraform
Terraform gebruikt .tf
bestanden om je infrastructure configuraties in op te slaan. De syntax lijkt op Yaml and JSON. Als gewenst kun je ook een .tf.json
file extensie gebruiken, die je toestaat om JSON te schrijven.
Om te beginnen met het implementern van IaC, zal ik eerst een configuratie voor een lokale Docker container maken om bekent te raken met de syntax en verschillende onderdelen van Terraform.
Ik heb een .tf
configuratie bestand gemaakt met instructies om Nginx te runnen op een lokale Docker container:
terraform {
required_providers {
docker = {
source = "kreuzwerker/docker"
version = ">= 2.13.0"
}
}
}
provider "docker" {
host = "npipe:////.//pipe//docker_engine"
}
resource "docker_image" "nginx" {
name = "nginx:latest"
keep_locally = false
}
resource "docker_container" "nginx" {
image = docker_image.nginx.latest
name = "NginxUsingTerraform"
ports {
internal = 80
external = 8000
}
}
Dit bestand bestaat uit het volgende:
- Terraform blok met Terraform settings.
- Een lijst van vereiste providers binnen het Terraform blok. Dit lijkt op een dependency die is vereist om de infrastructuur te creeren.
- Een provider, die in dit geval ons doorverwijst naar onze Docker Engine die de infrastructure aanmaakt.
- Een lijst van resources. Dit zijn de resources om aan te maken. In dit geval is er een Nginx image, en een Nginx container waarop de image gedeployed zal worden.
Terraform commando's
Terraform ondersteunt de volgende basic commando's:
- Om Terraform te initialiseren en de vereiste dependencies te downloaden gebruik
terraform init
. - Om de configuratie te valideren gebruik je
terraform validate
. - To see a list of changes to be deployed use
terraform plan
. - To apply changes to your infrastructure use
terraform apply
. - To stop your running infrastructure use
terraform destroy
.
TODO: Rest vertalen Using the init and apply commands the infrastructure is deployed to a local Docker instance. A list of changes is shown and Terraform asks for confirmation before deploying.
After a short while you will see the specified Nginx container running in your local Docker instance.
Scaling up
Say you want to add another Nginx container to your infrastructure. Since the image and Docker provider are listed above for the first resource. Adding a second container is as easy as adding a second resource to the configuration file.
Adding the following resource to the file creates a second Docker container running Nginx in Docker.
resource "docker_container" "nginx_clone" {
image = docker_image.nginx.latest
name = "NginxUsingTerraformClone"
ports {
internal = 81
external = 8001
}
}
Both resources running in a Docker container
Implementing Terraform on Microsoft Azure
Terraform can communicate with a multitude of cloud services. I will use Azure for this example.
A prerequisite to working with Terraform in Azure is being logged in to your Azure account using the Azure cli.
To get started you can want to create a resource group and storage account. This resource group will contain all our resources.
I created the resource group and storage account using the following configuration:
resource "azurerm_resource_group" "rg" {
name = var.resource_group_name
location = var.location
}
resource "azurerm_storage_account" "storageaccount" {
name = "tbterraformstorageac"
resource_group_name = var.resource_group_name
location = var.location
account_tier = "Standard"
account_replication_type = "LRS"
}
You might notice var.[name]
items in this example, these are variables.
Variables
Terraform configuration files support variables as well. For example the name of the resource group I created will be re-used in future configuration files. To add variables you can create a new configuration file which can contain the following:
variable "resource_group" {
default = "TerraformResourceGroup"
}
variable "location" {
default = "westeurope"
}
Adding a resource to Azure
Next I will create a feature branch, on this branch I will make some changes to our infrastructure. I will be adding a MSSQL Database to azure.
To add cloud specific resources there are a multitude of templates available in the Terraform registry to get started. As there are way too many configuration options for each resource to remember!
I added the following file to create a database server and the MSSQL instance:
resource "azurerm_mssql_server" "tbdatabaseserver" {
name = "tbdatabaseserver"
resource_group_name = var.resource_group_name
location = var.location
version = "12.0"
administrator_login = "tb4dm1n!"
administrator_login_password = "SuperSecurePass123!"
}
resource "azurerm_mssql_database" "tbsqldatabase" {
name = "tbsqldatabase"
server_id = azurerm_mssql_server.tbdatabaseserver.id
collation = "SQL_Latin1_General_CP1_CI_AS"
license_type = "LicenseIncluded"
max_size_gb = 4
read_scale = true
sku_name = "BC_Gen5_2"
zone_redundant = true
extended_auditing_policy {
storage_endpoint = azurerm_storage_account.storageaccount.primary_blob_endpoint
storage_account_access_key = azurerm_storage_account.storageaccount.primary_access_key
storage_account_access_key_is_secondary = true
retention_in_days = 6
}
}
You can apply these changes directly from the command line using the apply command. But in most cases, you won't be working on your own. Terraform changes can be tracked by your version control system, and thus your changes can be monitored when making a pull request. There will be more info about this below.
Integrating Terraform into your pipeline
When your Terraform infrastructure is added to your version control system you are able to integrate it into your build pipeline. This allows you to see the changes Terraform is about to make to your infrastructure when creating pull requests.
Adding Terraform support is as easy as adding a Terraform extension to Azure DevOps.
You can then add the terraform init
, ... validate
, ... plan
, ... apply
commands to your pipeline stages. Allowing you to validate the changes you are going to make to your infrastructure. Show the changes using the output of plan, to eventually merge the changes kicking off an apply pipeline.
Unfortunately I am not able to demonstrate this due to missing privileges in Azure. If you do want to try this for yourself I would highly recommend reading the following blogposts:
-
Terraforming from zero to pipelines as code with Azure DevOps. Thomas Thornton, 2021, about creating an Azure pipeline with Terraform integration.
-
Azure DevOps #1 - Terraform Plan as a PR Comment – Kamil Wiecek, 2021 About a custom way to add Terraform comments to your PR's.
In summary
When starting a new project, or when currently working on a project. I would highly recommend to implement IaC as it simplifies creating and managing infrastructure for your project. It allows anyone to create infrastructure without having to navigate a user interface. They can easily get up to date on the infrastructure landscape since the configuration files are readable and serve as documentation.
Versioning of infrastructure is easily done because the infrastructure configuration is checked in to your version control system. Which also allows the ability to review changes before deploying.
Using a tool like Terraform you are able to easily apply your changes to a multitude of cloud services.
Sources
- Workfall. (2021, February 26). How to manage infrastructure as code (IaC) with Terraform on AWS? Medium. Opgehaald, october 2021 van https://medium.com/workfall/how-to-manage-infrastructure-as-code-iac-with-terraform-on-aws-1fa6cd6bccfe
- Hashicorp. (2021). Terraform overview. Retrieved October 2021, from https://www.terraform.io
- Bonestroo, W.J., Meesters, M., Niels, R., Schagen, J.D., Henneke, L., Turnhout, K. van (2018). ICT Research Methods. HBO-i, Amsterdam. ISBN/EAN: 9990002067426. Retrieved October 2021, from http://www.ictresearchmethods.nl
- Chan, M. (2021, January 26). Infrastructure as Code: 6 best practices to get the most out of IaC. Thorn Technologies. Retrieved October 2021, from https://www.thorntech.com/infrastructure-as-code-best-practices
- Pelletier, J. (2021, May 20). Configuration Drift in Kubernetes - What is it and Why it Matters. Fairwinds. Retrieved October 2021, from https://www.fairwinds.com/blog/configuration-drift-kubernetes
- Vasiljevic, R. (2021, June 4). IaC Benefits, Challenges & Best Practices. SuperAdmins. https://superadmins.com/infrastructure-as-code-demystified-iac-benefits-challenges-best-practices/#IaC_Best_Practices_According_to_SuperAdmins
- Terraform. (n.d.). Azurerm_mssql_database. Terraform.Io. Retrieved 6 October 2021, from https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/mssql_database
- Thornton, T. (2020, October 27). Validating Terraform Code During A Pull Request In Azure DevOps. Thomas Thornton. Retrieved October 2021, from https://thomasthornton.cloud/2020/07/29/validating-terraform-code-during-a-pull-request-in-azure-devops
- Kamil Wiecek (2021). Terraform plan as a PR comment. Azure DevOps #1. Retrieved October 2021, from https://www.kamilwiecek.com/blog/azure-dev-sec-platform-ops
- Thornton, T. (2020b, December 4). Terraforming from zero to pipelines as code with Azure DevOps. Thomas Thornton. Retrieved October 2021, from https://thomasthornton.cloud/2020/11/28/terraforming-from-zero-to-pipelines-as-code-with-azure-devops
- Xenonstack. (2021). Infrastructure as Code Tools and Best Practices. Retrieved October 2021, from https://www.xenonstack.com/blog/what-is-infrastructure-as-code
- SDxCentral. (2021, 19 maart). Server Resolution Error 1001. Retrieved October 2021, from https://www.sdxcentral.com/articles/sponsored/implementing-infrastructure-as-code-for-cloud-speed-and-agility/2021/06/