This post is the second part of a multi-part blog post and video on Terraform with Azure. The previous video located here went over configuring an environment for Terraform and Azure. This post reviews the basic Terraform workflow. In the process, we create our first deployment to Azure with Terraform.
The basic workflow for Terraform is to write, plan and deploy. So let’s get started with the first step, writing the Terraform configuration.
Write
Terraform uses a directory as a workspace. All Terraform files in a directory are treated as one file. We can split a configuration into multiple files to make the configuration easier to read and understand, but from Terraform’s perspective, they are all part of the same project.
Directory structures are important to creating and organizing Infrastructure as Code (IaC). For this example, we’ll start with a folder called TerraformProjects in the documents directory, then add the first project Folder named ResourceGroup.
Next, we create our first Terraform configuration file. Terraform uses the extension .tf for configuration files. There is also a .tf.json option for JSON based configurations, but we’ll use .tf for this example. A common Terraform file is called main.tf. This file is the main configuration file for a project. As stated earlier, Terraform configuration files in a directory are treated as a single file by Terraform. We use multiple configuration files to make the code easier to read.
Open VSCode and then go to file>open folder. Next, select the ResourceGroup folder created in the previous step.
Once the file is created, we can add the provider information. The provider information can be added manually, but it’s easier to get the most up-to-date information from the Terraform Registry. Go to https://registry.terraform.io/ and select Azure.
From there, you can get the code required to use AzureRM Provider from the ‘Use Provider’ dropdown.
Copy the code into the main.tf file. To set the AzureRM provider. With this setting, the specified version of the AzureRM provider is used whenever the code is deployed to new environments. Version control is important, if we always used the most recent version of Terraform, it’s possible that changes to an updated version could break the configuration. By specifying a version, we can update and test new versions of Terraform with the code in a controlled manner.
Next, we need to add the resource block. A resource block is the infrastructure to be deployed to Azure. Multiple blocks are used to create complete infrastructure sets in Azure. For this example, we will deploy a single resource, a Resource Group.
The easiest way to add a resource is to go back to the Resource Provider in the Registry at https://registry.terraform.io/ and change the view on the top right of the page to Documentation.
From here, we can search for the type of resource to deploy. Search for ‘Resource Group’ and open Base>Resources>azurerm_resource_group.
The azurerm_resource_group page provides information to create a resource group, including an example and a list of required and optional arguments to deploy the resource.
Copy the example and paste it to the bottom of the main.tf file in VSCode. Once done, the main.tf file will look similar to below.
A resource block starts with the word Resource. Next is the resource type, azurerm_resource_group, for this example. After that is the local name, example in the image above.
Terraform uses the word ‘example’ frequently in the examples. The image above shows example for the local name and the resource name. These two items do not need to be named the same, and they are not related other than being in the same resource block. Change the first instance of example, the local name, to ‘resoucegroup’.
A local name is for internal terraform use only. We can reference the resource in other sections of code with the local name.
The next instance of example is the name that the resource will have in Azure. For this example, change that to ‘TerraformRG’.
Save the file. Terraform uses files in the directory, and if they are not saved, changes won’t apply.
Now that we have the main.tf updated with a resource, we can initialize the directory. Do this by opening a terminal window by going to Terminal, New Terminal.
Next, run the command:
terraform init
## If you get a message that Terraform can’t be found, be sure you downloaded and extracted the terraform.exe and updated the system path to include the location.
As stated previously, terraform works at the directory. Running the terraform init command initializes the directory for Terraform. It creates a new folder called .terraform and adds the specified version of the resource provider to the directory. It also makes a terraform.lock.hcl file. This is a dependency lock file used to track provider dependencies. Both the .terraform directory and terraform.lock.hcl file are maintained by Terraform.
We have successfully written our first Terraform configuration file. One important note, any time configuration files are updated in the directory, the changes need to be saved then re-initialized by running the terraform init command.
Log in to Azure
Logging into Azure is not a designated step in the Terraform Workflow, but it is required before we can deploy resources. Below is a list of commands to log in and update Azure CLI with the Account extension. Also included are steps to verify we are on the correct subscription and if not, change the subscription.
Please note, you may need to type these commands in as this was edited in Word, and sometimes a dash isn’t a dash??
First, log in with the az login command.
az login
Next, add the account extension for the Azure CLI with the command below. This is required for the az account commands.
az extension add –upgrade -n account
If you have more then one subscription, verify you are on the correct one with the az account show command.
az account show
If you need to switch subscriptions, use the command below to list all subscriptions.
az account subscription list
To change the subscription, use the command below with the name of the subscription you want to use.
az account set –subscription “<Subscription Name>”
Verify the subscription was switched by running the az account show command again.
Plan
Now that the directory is initialized and we are logged into Azure, we can plan a deployment. A Terraform plan reads the current state of remote objects and makes sure it’s up to date. It also compares the current configuration with the prior state and notes any differences. Terraform plan uses this information to create a plan of changes that will take place.
At the command prompt, type terraform plan to run the plan.
The output will show one addition, the Resource Group, for this example.
Terraform Plan runs a “what if” analysis of the current environment against the proposed changes. If the output looks as expected, we can move onto applying the configuration.
Apply
We have our configuration file written and we agree to the plan; now it’s time to apply the changes with the terraform apply command. This will run a terraform plan and then prompt you to confirm the changes. Once confirmed, the changes are written to Azure.
Run terraform apply to apply the configuration.
Once the change is confirmed, the configuration is applied. In the end, you will see a notice that the apply completed.
You can verify the change by viewing the new resource group in the Azure portal or by running the command below. Update the Resource Group name if yours is different.
az group list –query “[?name==’TerraformRG’]”
Once applied, you will notice a new terraform.state file in the directory. The Terraform state file tracks the status of resources Terraform manages. It maps real world resources to the configuration.
Destroy
It may be necessary at times to remove a configuration. We can do this with the destroy command. This will remove all items deployed with the Terraform plan. The command to remove the deployment is:
terraform destroy
Run the destroy command and use the az grop list command to verify that resource group was removed.
Conclusion
This post covered a lot of information. The example in this post was a simple deployment, but the workflow will be similar for larger deployments. The Terraform AzureRM reference documentation will be important as we build more complex environments. The examples and arguments are valuable references for future projects.
You can find the next post on input variables here