Terraform is an open-source software developed by HashiCorp that allows the management of IT infrastructure through the concept of “Infrastructure as Code”. Using a declarative language, users can define, create and manage resources such as servers, databases, networks, and more, both in cloud environments (such as AWS, Azure, Google Cloud) and in local infrastructures. Terraform allows you to automate infrastructure provisioning and management, offering the ability to maintain code versions, roll back, and collaborate effectively on complex projects. In this article, we'll then dive into what Terraform is, how it works, and how it integrates with Azure.
One of the technologies that emerged thanks to the DevOps movement, which promotes greater communication and cooperation between development and operational teams, is Infrastructure as Code. These are technologies that DevOps engineers and Site Reliability Engineers (SRE) have adopted to implement the latest infrastructure automation techniques in the cloud.
Microsoft Azure natively supports ARM templates to implement the IaC, but this is an Azure-specific technology.
With the help of HashiCorp Terraform, we now have an open source Infrastructure as Code tool that is independent of the cloud, an infrastructure automation tool that works with any provider, including Microsoft Azure and can operate simultaneously on multiple cloud platforms in a single infrastructure distribution.
When automating resource distributions on Microsoft Azure, Terraform offers some differences compared to the native tools of Microsoft's ARM templates and, in this article, we'll take a closer look at what Terraform is, how to use it and what the use of the latter for provisioning infrastructure and resources on Microsoft Azure looks like.
Before going to discuss Terraform and its integration into Azure, let's first take a minute for a brief review, for the benefit of those who may have missed a few steps. What is Infrastructure as Code?
Infrastructure as Code (IaC) is an approach to managing and configuring IT infrastructures through the definition and automation through code, rather than through manual intervention on servers or network devices.
With IaC, the infrastructure (servers, databases, networks, etc.) is described in readable and repeatable configuration files, usually in formats such as JSON, YAML or specific languages such as HCL (HashiCorp Configuration Language).
These files can be versioned, revised, and managed like any other source code, making the provisioning and management process more efficient and less prone to errors.
The IaC offers numerous advantages, including greater consistency, repeatability, and scalability of infrastructure deployments, as well as faster and more reliable provisioning. It also allows the use of version control and documentation of infrastructure configurations, making it easier to track changes and rollbacks.
It aligns perfectly with the core principles of DevOps, such as automation, collaboration, and continuous integration and delivery (CI/CD).
HashiCorp Terraform is an Infrastructure as Code tool that helps to more reliably deploy and manage infrastructure deployments on one or more clouds, or even on-premise.
Like all IaC tools, Terraform allows you to write code that is used to create, modify and version the distributions of your digital infrastructure in a reliable and efficient way.
There are two types of Infrastructure as Code: declarative and imperative.
Terraform belongs to the declarative type of IaC, in which you write a template file or, in the case of Terraform, one or more files with a .tf extension in the Terraform Configuration Language.
These files state what the final result of deploying the infrastructure should be; therefore, when you deploy with the Terraform tool, it will make the necessary changes or updates to the infrastructure to meet the desired definition that has been declared.
In comparison, an imperative approach to the IaC would use traditional command-line scripts (CLI) that perform all the necessary steps in the order in which they are written.
The declarative IaC is more efficient and reliable, since it is not necessary to know the current state of the infrastructure when writing the IaC code, and the tool will determine what changes or updates to make at the time of deployment.
The code written in Terraform can be used to declare (or define) all the infrastructure components necessary for a given workload. This workload could be a single application or even a large scale system comprised of multiple microservices, databases, virtual machines, and other resources.
The infrastructure components of the workload may include low-level infrastructure resources such as network, storage, and computing resources, and also high-level infrastructure such as Platform as a Service (PaaS) computing and database services or other components.
While tools such as Azure Bicep and ARM Templates are developed by Microsoft to natively support the management of Microsoft Azure resources, these tools allow you to manage only Azure resources.
Using HashiCorp Terraform, on the other hand, you can use the same tools and languages to manage Microsoft Azure resources, in addition to any other resource within your environments from a single Terraform project.
In addition, with Terraform, SREs or DevOps engineers will use the same skills and understanding of the HCL language to manage all resources, while also ensuring efficiency benefits.
There are several advantages to using Terraform to manage your resources:
When you start using Terraform, there are some important terms to know to better navigate your way through files, documentation, and other resources while working on your Terraform projects.
Here are some useful terms that are important for all DevOps engineers or site reliability engineers (SRE) to understand:
There are other specific terms, however these are the main ones you should know when you start using Terraform automation and form the basis for understanding how it works.
We have created the Infrastructure & Security team, focused on the Azure cloud, to better respond to the needs of our customers who involve us in technical and strategic decisions. In addition to configuring and managing the tenant, we also take care of:
With Dev4Side, you have a reliable partner that supports you across the entire Microsoft application ecosystem.
As a platform-independent set of tools, Terraform adopts a “plugin” style model to add providers that manage communication with the various infrastructure APIs.
This allows the Terraform code to integrate the specific providers you need to work with your infrastructure distributions and enhance the tool with the ability to manage different technological resources such as, in our case, Microsoft Azure resources, Microsoft Azure AD resources or even non-Microsoft technological resources.
To work with the Microsoft Azure infrastructure through Terraform, you use the azurerm provider to code against the Microsoft Azure Resource Manager (ARM) REST APIs.
The azurerm provider allows the management of Microsoft Azure resources such as virtual machines, storage accounts and network interfaces, but it is not the only one dedicated to Microsoft's cloud platform.
In fact, there are several Terraform providers specific to the various types of Azure resources:
As an Infrastructure as Code tool, the infrastructure managed by Terraform is configured in HCL (HashiCorp Configuration Language) code and is usually inserted into version control (such as Git) and integrated with CI/CD distribution pipelines for distribution automation.
Terraform modules are a way to create blocks of Terraform HCL (HashiCorp Configuration Language) code that can be reused within a single Terraform project or even across multiple Terraform projects.
An analogy for programmers, thinking about Terraform modules, is to compare them to a function or a code method.
For those not used to the programming language, let's imagine instead having a set of instructions for building something, like a house. If you want to build several similar houses, instead of rewriting all the instructions each time, you can create a form with instructions for a part of the house, such as the kitchen, and reuse it whenever you need it.
In the beginning, when you start writing a Terraform project, you create one or more Terraform code files (.tf) inside a single folder. This is similar to writing all the code for a program in a single source code file of more than 1,000 lines.
With modules, you can break that code down into blocks that are used throughout the program. This allows you to create reuse of the code and to adhere to the DRY (Don't Repeat Yourself) best practice in programming, also making the code easier to read and maintain over time.
Terraform modules offer advantages for different use cases:
At a basic level, a Terraform form is a collection of Terraform code (.tf) files in the same folder. This is similar to a regular Terraform project, but with a Terraform module, you can use the form from another module or project to achieve code reuse for infrastructure.
When thinking about reusing code compared to other development technologies, it's useful to consider a Terraform module as a code library that is referenced and called from another library or code application.
In 2024, Microsoft announced Azure Verified Modules (AVM), an initiative to standardize Infrastructure-as-Code (IaC) modules for Azure. The goal is to provide a unified set of Terraform (and Bicep) modules that adhere to industry best practices and specific standards.
Key features of AVM:
To start using AVMs for Terraform, you can explore the modules currently available on AVM official page.
Now that we're a little more clear about what Terraform is and the basics of how it works, let's take a look at an example of Terraform code using the Azure Resource Manager (azurerm) provider to create an Azure resource group and then an Azure storage account within that resource group.
All infrastructure deployments in Microsoft Azure will use resource groups, and most will also use Azure storage accounts.
The following examples will provide a better understanding of how to use Terraform to manage Microsoft Azure resources. So, let's move on.
Here's a simple Terraform code example that uses the Azure RM azurerm_resource_group resource type to specify the IAC for deploying an Azure resource group.
# Create a resource group
resource “azurerm_resource_group” “d4s” {name = “d4s-rg” location = “West Europe”}
When you run a Terraform deployment using this code, the Azure resource group will be created.
Note that within the Terraform code for the azurerm_resource_group resource, the Terraform code sets the name of the 'Terraform resource' to d4s.
This name can be used to refer to the next Terraform code resource (such as creating the Azure storage account below) to access the properties/values of the resource and configure other resources to be distributed.
For example, in other Terraform code, you can refer to this resource group using the following format:
# Format
[Terraform Resource Type]. [Terraform Resource Name]
# Specify the resource type of the AzureRM Resource Group
azurerm_resource_group. [Terraform Resource Name]
# Specify the particular Resource Group named “d4s”
azurerm_resource_group.d4s
Note that to refer to the resource group named d4s, you must assign this name to the resource type of the resource group (azurerm_resource_group). When declaring Terraform resources, the first value in quotes (“) is the Terraform resource type, and the second value in quotes (“) is the name of the resource.
Here's an example to clarify:
# Format
resource “[Terraform Resource Type]” “[Terraform Resource Name]” {...}
# Specify the resource type of the AzureRM Resource Group
resource “azurerm_resource_group” “[Terraform Resource Name]” {...}
# Specify the Resource Group resource type to be named “d4s”
resource “azurerm_resource_group” “d4s” {...}
All resources defined within the Terraform configuration files must have a unique name within the Terraform configuration files (.tf). This uniqueness must be respected in all .tf files in your distribution, whether you use a single .tf file or multiple files. In addition, the name is unique to the type of Terraform resource that is being deployed.
This Terraform Resource Type + Resource Name scheme is used to define each unique resource that the Terraform configuration will manage and deploy. It can also be used to set dependencies between Terraform resources, allowing you to refer to one resource when configuring another; as illustrated below.
Here's a Terraform code example for creating an Azure storage account using the azurerm_storage_account resource type.
In this case, the Terraform resource name for the storage account is set to d4sstorage, and the resource_group_name for organizing the resource within Azure refers to the Azure resource group created in the previous example.
# Create an Azure Storage Account resource
“azurerm_storage_account” “d4sstorage” {name = “d4sstorage”
# Place in the same resource group
resource_group_name = azurerm_resource_group.d4s.name
# Use the same location as the resource group
location = azurerm_resource_group.d4s.location account_tier = “Standard” account_replication_type = “GRS” tags = {environment = “dev”}}
When running a Terraform deployment using this code, the Azure storage account will be created with the specified configurations, such as placing it within the previously created Azure resource group in the same distribution.
By setting the azurerm_storage_account.resource_group_name property to the value of azurerm_resource_group.d4s.name, the previously created Azure resource group is referred to, using the .name to indicate to the azurerm provider which resource group to insert the Azure storage account.
Microsoft's well-established commitment to open source has been bearing great fruit for many years and the integration of a whole series of tools and tools into its proprietary services is leading to a significant increase in the quality of the offer for all those companies that need more efficient digital infrastructures.
The combination of Terraform and Azure is yet another good example of how this openness has paid off tremendously. In the hands of developers, engineers and SREs, it proves to be a powerful and versatile tool for managing cloud infrastructure, with its ability to automate the provisioning and configuration of resources, thus allowing organizations to reduce development times and improve consistency in distributions.
Finally, we cannot fail to mention an extremely active community that contributes modules and providers to continue to improve them and integrate Terraform functionality even more closely with Azure services.
Terraform is an open-source tool developed by HashiCorp that allows you to define and manage infrastructure as code, according to a declarative approach. When used in combination with Microsoft Azure, it allows DevOps developers and engineers to automate the provisioning and configuration of Azure resources, while maintaining a high level of consistency, repeatability, and versioned control. Its operation is based on files .tf
written in HCL, which declare the desired state of the infrastructure.
Using Terraform on Azure means having a tool independent of the cloud provider, capable of orchestrating Azure resources together with resources from other platforms within the same project. The ability to inspect changes before application thanks to the command Plan
, the ease of use offered by the declarative language and the absence of breaks even in repeated executions make Terraform particularly suitable for managing complex and dynamic environments.
To work with Azure, Terraform provides several specific providers. The main one is Azurerm
, which interacts with the Azure Resource Manager REST APIs and allows you to manage resources such as virtual machines, storage accounts and networks. Other providers include Azuread
for managing users and groups in Azure Active Directory, Azuredevops
to interact with Azure DevOps, Azapi
to access ARM functionality in preview and Azurestack
to manage distributed environments through Azure Stack.
A Terraform module is a collection of files that encapsulate reusable blocks of code, making it easier to manage and maintain infrastructure. Thanks to the forms, it is possible to avoid duplication, increase the readability of the project and apply changes in a centralized way. Azure Verified Modules, known as AVM, are a series of official modules developed and supported by Microsoft to ensure that distributions follow best practices in terms of security, efficiency and reliability.
With Terraform, you can create any type of Azure-supported resource, including network, storage, computational, and PaaS. A common example is creating a resource group followed by a storage account, defining the desired properties in the code .tf
and letting Terraform generate and maintain the corresponding infrastructure state.
The declarative approach, such as that adopted by Terraform, is based on describing the desired state of the infrastructure. It is up to the tool to calculate and apply only the changes necessary to achieve that state. On the contrary, the imperative approach requires that each step be explicitly written and followed in order, making management less flexible and more prone to errors. Terraform, with its declarative model, does not need to know the current state of the infrastructure at the time of writing, improving reliability and scalability.
It is important to familiarize yourself with concepts such as files .tf
, which contain the infrastructure code, and with terms such as resource, provider, variable, module and input variable. Each resource is defined by a type and a name that must be unique within the project. Providers allow Terraform to interact with cloud APIs, while variables make code more dynamic and reusable. Finally, the modules allow you to organize the code in logical and reusable blocks for greater efficiency.
The Infra & Security team focuses on the management and evolution of our customers' Microsoft Azure tenants. Besides configuring and managing these tenants, the team is responsible for creating application deployments through DevOps pipelines. It also monitors and manages all security aspects of the tenants and supports Security Operations Centers (SOC).