This article explores the process of utilizing Infrastructure as Code with Terraform to provision Azure Resources for creating storage and managing Terraform Remote State based on the environment.
Terraform State
Terraform state refers to the information and metadata that Terraform uses to manage your infrastructure. It includes details about the resources created, their configurations, dependencies, and relationships.
Remote state storage enhances security by preventing sensitive information from being stored locally and allows for controlled access to the state. It enables state locking and preventing conflicts. It simplifies recovery and auditing by acting as a single source of truth and maintaining a historical record of changes.
Azure Storage
Azure Storage is a highly scalable and durable solution for storing various types of data. To store Terraform state in Azure Storage, we will be utilizing the Azure Blob Storage backend. Azure Blob Storage is a component of Azure Storage that provides a scalable and cost-effective solution for storing large amounts of unstructured data, such as documents, images, videos, and log files.
Note: This article assumes you have Linux and Terraform experience.
Prerequisites
- Terraform Installed
- Azure Account
- Azure CLI
Code
You can find the GitHub Repo here.
Brief Overview of the Directory Structure
/terraform-aks/
├── modules
│ ├── 0-remotestate
│
└── tf
└── dev
|
├── global
│ └── 0-remotestate
- /terraform-aks: This is the top-level directory.
- /modules: Within this directory, we store the child modules that will be invoked by the root modules located in /tf/.
- /0-remotestate: This sub-directory, found within the /modules/ directory, contains the necessary resources for creating storage used to store our remote state.
- /tf: The configurations for all root modules are located in this directory.
- /dev: Representing the environment, this directory contains configurations specific to the dev environment.
- /global: This subdirectory houses configurations that are shared across different regions.
- /0-remotestate: Located within the /global/ directory, this subdirectory represents the root module responsible for calling the child module located in /modules/0-remotestate/ in order to create our storage.
Usage
To use the module, modify the main.tf at the root level and child module at main.tf based on your criteria.
Let’s take a look at the resources needed to create our storage for our remote state within our child module located in terraform-aks/modules/0-remotestate/main.tf
We are creating the following:
Resource Group: A resource group is a logical container for grouping and managing related Azure resources.
Storage Account: Storage accounts are used to store and manage large amounts of unstructured data.
Storage Container: A storage container is a logical entity within a storage account that acts as a top-level directory for organizing and managing blobs. It provides a way to organize related data within a storage account.
We use the Terraform Azure provider (azurerm
) to define a resource group (azurerm_resource_group
) in Azure. It creates a resource group with a dynamically generated name, using a combination of <youruniquename
> and the value of the var.environment
variable. The resource group is assigned a location specified by the var.location
variable, and tags specified by the var.tags
variable.
The Azure storage account (azurerm_storage_account
) block is use to create a storage account. The name attribute is set using a combination of <var.name
>, a placeholder that should be replaced with your own name, and the value of the var.environment
variable.
An Azure storage container (azurerm_storage_container
) is defined. The name
attribute specifies the name of the container using <youruniquename
> placeholder, which should be replaced with your desired name.
Next, let’s take a look at the variables inside terraform-aks/modules/0-remotestate/variables.tf
These variables provide flexibility and configurability to the 0-remotestate
module, allowing you to customize various aspects of the resource provisioning process, such as names, locations, access types, and more, based on your specific requirements and preferences.
Next, lets take a look at the outputs located in terraform-aks/modules/0-remotestate/outputs.tf
By defining these outputs, the outputs.tf
file allows you to capture and expose specific information about the created resource group, storage account, and container from the 0-remotestate
module.
Let’s Navigate to our Root module located at terraform-aks/tf/dev/global/0-remotestate /main.tf
This code begins by defining the azurerm
provider, which enables Terraform to interact with Azure resources. The features {}
block is empty, indicating that no specific provider features are being enabled or configured in this case.
The locals
block is used to define local variables. In this case, it defines the following variables:
cwd
: This variable extracts the current working directory path, splits it by slashes (“/”), and then reverses the resulting list. This is done to extract specific values from the path.environment
: This variable captures the third element from thecwd
list, representing the environment.location
: This variable is set to the value"westus2"
, specifying the Azure region where resources will be deployed.name
: This variable is set to the value"aksdemo"
, representing the name of the project or deployment.tags
: This variable is a map that defines various tags for categorizing and organizing resources. The values within the map can be customized based on your specific needs.
This code block declares a module named remote_state
and configures it to use the module located at ../../../../modules/0-remotestate
. The source parameter specifies the relative path to the module. The remaining parameters (name, location, environment,
and tags
) are passed to the module as input variables, using values from the local variables defined earlier.
This code also, includes a data block to fetch the current Azure client configuration. This data is useful for authentication and obtaining access credentials when interacting with Azure resources.
The commented out terraform
block represents a backend configuration for storing Terraform state remotely. This block is typically uncommented after the necessary Azure resources (resource group, storage account, container, and key) are created. It allows you to configure remote state storage in Azure Blob Storage for better state management.
Now that we have set up the root module in the terraform-aks/tf/dev/global/0-remotestate/
directory, it’s time to provision the necessary resources using the child module located at terraform-aks/modules/0-remotestate
. The root module acts as the orchestrator, leveraging the functionalities and configurations defined within the child module to create the required infrastructure resources.
- From the directory: terraform-aks/dev/global/0-remotestate, with the backend commented out, run:
- Terraform init
- Terraform Plan
- Terraform apply
After executing terraform apply and successfully creating your storage resources, you can proceed to uncomment the backend block in the main.tf file. This block contains the configuration for storing your Terraform state remotely. Once uncommented, run another terraform init command to initialize the backend and store your state in the newly created storage account. This ensures secure and centralized management of your Terraform state, enabling collaborative development and simplified infrastructure updates.
Enter a value of yes when prompted.
Matt Mendez is a dedicated and passionate IT professional with a strong desire to help people as a consultant. With expertise in AWS, Linux, Terraform, and Google Cloud. He has acquired valuable certifications in these areas. Having hands-on experience in working with leading cloud platforms such as AWS, Azure, and Google Cloud, as well as proficient in managing infrastructure using Terraform and Kubernetes.
Follow Matt on LinkedIn