Getting started with Terraform Azure – Provision & Manage any Infrastructure
Each organisation is different, some has dedicated teams to manage and provision resources. But if you were to manage them your self as a developer, either you login to Azure Portal and create necessary resources yourself or you CI/CD (Infrastructure as a code) do it as part of the release. You will anyway have to build pipelines for deployments, why not include “Infrastructure as a code” as part of a release. Also, you will have source control for the “Infrastructure as a code”
In the past, I have been using Azure ARM templates, but it has been a bit confusing building JSON file, especially when you have many resources and configurations, you will easily get lost on your own JSON.
This is where Terraform comes handy; it makes not only readable code, but also minimal lines of code.
Let’s see how you can build the code on your PC before you add it to the pipeline. You can run the same code over and over to get it right and test it before you actually create resources in Azure.
Install terraform CLI
https://learn.hashicorp.com/tutorials/terraform/install-cli?in=terraform/azure-get-started
Install Azure CLI
Login to your Azure subscription – using PowerShell
- login to your Azure subscription
az login
Once the login is completed on the browser you will see something like below
{ "cloudName": "AzureCloud", "homeTenantId": "xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxx", "id": "ssssxxx-dddd-eee-ddd-eeeeeee", "isDefault": true, "managedByTenants": [], "name": "Azure PAID Subscription", "state": "Enabled", "tenantId": "xxxx-xxx-4b29-xxx-ccccc", "user": { "name": "yor@mail.com", "type": "user" } },
Copy the subscription id (make sure you don’t share any of these Ids)
- Set your default subscription id (if you have a single subscription you don’t have to do this)
az account set --subscription="XXXXX-XXXX-XXXX-XXXX-XXXXXXXX"
You will need to create 2 files main.tf and variables.tf
# Configure the Azure provider terraform { required_providers { azurerm = { source = "hashicorp/azurerm" version = ">= 2.26" } } } provider "azurerm" { features {} } resource "azurerm_resource_group" "rg" { name = "ml_${var.environment}_rg_${var.appname}" location = var.location tags = var.tags } resource "azurerm_storage_account" "rg" { name = "st${var.appname}${var.environment}" resource_group_name = azurerm_resource_group.rg.name location = azurerm_resource_group.rg.location account_tier = "Standard" account_replication_type = "LRS" tags = var.tags } resource "azurerm_application_insights" "rg" { name = "appi-${var.appname}-${var.environment}" location = azurerm_resource_group.rg.location resource_group_name = azurerm_resource_group.rg.name application_type = "web" } resource "azurerm_sql_server" "rg" { name = "sql-${var.appname}-${var.environment}" resource_group_name = azurerm_resource_group.rg.name location = azurerm_resource_group.rg.location version = "12.0" administrator_login = "sql-${var.appname}-admin-${var.environment}" administrator_login_password = var.administrator_login_password tags = var.tags } resource "azurerm_sql_database" "rg" { name = "sqldb-${var.appname}-${var.environment}" resource_group_name = azurerm_resource_group.rg.name location = azurerm_resource_group.rg.location server_name = azurerm_sql_server.rg.name tags = var.tags } resource "azurerm_app_service_plan" "rg" { name = "azapp-${var.appname}-${var.environment}" location = azurerm_resource_group.rg.location resource_group_name = azurerm_resource_group.rg.name sku { tier = "ElasticPremium" size = "EP1" } tags = var.tags } resource "azurerm_function_app" "rg" { name = "func-${var.appname}-${var.environment}" location = azurerm_resource_group.rg.location resource_group_name = azurerm_resource_group.rg.name app_service_plan_id = azurerm_app_service_plan.rg.id storage_account_name = azurerm_storage_account.rg.name storage_account_access_key = azurerm_storage_account.rg.primary_access_key tags = var.tags } output "instrumentation_key" { value = azurerm_application_insights.rg.instrumentation_key } output "app_id" { value = azurerm_application_insights.rg.app_id }
you can configure your variables in variables.tf, they can be either constants or parameters that get passed in by CI/CD
Below is the variables.tf file, please note that I have not set a default value to “administrator_login_password”, therefore it will ask for value. later I will set it up as a secure variable in Azure DevOps (alternatively in Key Vault)
variable "appname" { type = string default = "profile" } variable "location" { type = string default = "australiasoutheast" } variable "environment" { type = string default = "dev" } variable "administrator_login_password" { type = string } variable "tags" { type = map default = { Application = "AppSuperman" Department = "Superman Unit" Environment = "dev" } }
In a Powershell window, if you are running the script for the first time
terraform init
terraform plan -var "environment=tst" -var "administrator_login_password=8891c2ce-399c-11eb-adc1-0242ac120002"
Once everything is working as expected you can run the below script to create your resources in Azure
terraform apply -var "environment=tst" -var "administrator_login_password=8891c2ce-399c-11eb-adc1-0242ac120002" -auto-approve
Deleting your resources – DO NOT include this in CI/CD, and be careful with your local as you can’t revert
terraform destroy -var "environment=tst" -var "administrator_login_password=XXXX"