Azure resource groups are the organizational backbone of most Azure deployments. A resource group is a container that holds related resources for a solution. Resource groups define the scope for access control, policy, and cost management. Some resource types can exist at subscription, management group, or tenant scope, but you cannot create a virtual machine, database, or storage account without first placing it in a resource group. This makes resource groups the first thing you create in any Azure Terraform project. Getting the structure right early saves you from painful reorganizations later.
Terraform enables the definition, preview, and deployment of cloud infrastructure. Using Terraform, you create configuration files using HCL syntax. The HCL syntax allows you to specify the cloud provider - such as Azure - and the elements that make up your cloud infrastructure. After you create your configuration files, you create an execution plan that allows you to preview your infrastructure changes before they're deployed. With Terraform, you can then discover and manage drift between your desired state and the current state of the infrastructure.
Resource groups are containers that hold related resources for a solution - they define the scope for access control, policy, and cost management. Group-level dashboards make it easy to see the status of all resources belonging to a particular application or team, and alert on issues before they affect users. Resource groups are the organizational backbone of most Azure deployments. Getting the naming, tagging, and access control right at this level pays dividends as your infrastructure grows. Use Terraform's for_each to create consistent groups across environments, apply delete locks to production groups, and set budgets to avoid cost surprises. Most application resources you build in Azure depend on this foundation being solid.
Provider Configuration and Prerequisites
Terraform projects that target Azure require explicit provider declarations and authentication. The provider configuration establishes the connection between Terraform and Azure and determines the version compatibility of the Azure provider used.
Prerequisites for creating resource groups with Terraform include:
- Terraform 1.0 or later
- Azure CLI installed and authenticated (
az login
) - An Azure subscription
- Basic familiarity with Terraform HCL
The required providers block defines the azurerm and azuread providers with version constraints. The azurerm provider source is hashicorp/azurerm. The version constraint used in reference material is ~> 4.0. The azuread provider source is hashicorp/azuread with version constraint ~> 3.0.
Provider configuration example:
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 4.0"
}
azuread = {
source = "hashicorp/azuread"
version = "~> 3.0"
}
}
}
provider "azurerm" {
features {}
}
provider "azuread" {}
Check the compatibility matrix in the Terraform documentation to find compatible versions of Terraform and the Azure provider. Configuration structure and style matters for scalability. Good configuration hygiene makes the difference between a codebase that scales and one that becomes a maintenance burden.
Creating a Basic Resource Group
The first infrastructure object created in most Azure Terraform projects is a resource group. The azurermresourcegroup resource block is used to create resource groups inside of Azure.
A simple resource group definition includes name, location, and tags.
resource "azurerm_resource_group" "main" {
name = "rg-myapp-prod-eastus"
location = "East US"
tags = {
Environment = "production"
Project = "myapp"
ManagedBy = "terraform"
}
}
The name and location are required attributes for azurermresourcegroup. Tags are optional but recommended for governance.
Another example configuration:
resource "azurerm_resource_group" "example_group" {
name = "my-resource-group"
location = "uksouth"
tags = {
environment = "dev"
}
}
The creation workflow follows Terraform lifecycle steps.
In your terminal window, navigate to your Terraform project directory.
Run the command
terraform init
to initialize Terraform.
Run the command
terraform plan
to see the changes Terraform will make. This will show you the creation of the resource group. If the plan looks good, run
terraform apply
to create the resource group in your Azure subscription.
The sample code for this article is located in the Azure Terraform GitHub repo. This article shows how to create an Azure resource group using Terraform. In this article, you learn how to create an Azure resource group using Terraform.
Resource Group Attributes and Naming Conventions
Resource group attributes determine how the group is identified and governed.
| Attribute | Requirement | Example Value |
|---|---|---|
| name | required | my-resource-group |
| location | required | uksouth / East US |
| tags | optional | environment = dev |
Naming conventions impact cost management and access control. Consistent naming enables group-level dashboards to show the status of all resources belonging to a particular application or team, and alert on issues before they affect users.
Tags applied at the resource group level propagate governance signals. Common tags used in examples include Environment, Project, ManagedBy, and environment.
A modular design breaks infrastructure into reusable modules for common components like networking, compute, and storage. Use a modular design. Break your infrastructure into reusable modules for common components like networking, compute, and storage.
Use Terraform's foreach to create consistent groups across environments. The foreach meta-argument allows creation of the number of resources of the type we want.
resource "azurerm_resource_group" "this" {
for_each = var.resource_groups
name = each.key
location = each.value.location
}
Variables are declared using map(object) types. The link between resources is created by referencing attributes of the resource group.
Linking Resources to Resource Groups
Most Azure resources depend on a resource group existing first. Dependency is expressed through attribute references in Terraform.
Example: Kubernetes deployment with Terraform on Azure.
The code can be found here.
We will be using two resources:
azurermresourcegroup – used to create resource groups inside of Azure
azurermkubernetescluster – used to create the Kubernetes cluster inside of Azure
In this example, cluster management will always be free; you pay only for the cluster’s underlying nodes.
resource "azurerm_kubernetes_cluster" "this" {
for_each = var.kube_params
name = each.key
location = azurerm_resource_group.this[each.value.rg_name].location
resource_group_name = azurerm_resource_group.this[each.value.rg_name].name
...
}
The link between the resources above is created on the Kubernetes one, specifically at the location and resourcegroupname parameters. This allows us to ensure the resource group is created first, and we access its location and name attributed inside the Kubernetes Cluster. The cluster and the resource group in which it will be created will reside in the same location.
We declare the variables using map(object) types.
Verification and Cleanup Operations
After applying Terraform configuration, verification confirms the resource group exists with the specified name and location in Azure.
Verify the results:
Log into the Azure portal and navigate to the Resource Groups section to see your newly created resource group with the specified name and location.
Cleanup removes the resource group when it is no longer needed.
If you no longer need the resource group, you can remove it using Terraform by running
terraform destroy
.
Terraform enables the definition, preview, and deployment of cloud infrastructure. Using Terraform, you create configuration files using HCL syntax. The HCL syntax allows you to specify the cloud provider - such as Azure - and the elements that make up your cloud infrastructure. After you create your configuration files, you create an execution plan that allows you to preview your infrastructure changes before they're deployed.
Best Practices for Using Terraform with Azure
Following best practices from the start of your project can save you from painful restructuring and security headaches down the line. Here is what we recommend.
Configuration structure and style
Good configuration hygiene makes the difference between a codebase that scales and one that becomes a maintenance burden.
- Use a modular design. Break your infrastructure into reusable modules for common components like networking, compute, and storage
Additional recommendations derived from reference material:
- Use Terraform's for_each to create consistent groups across environments
- Apply delete locks to production groups
- Set budgets to avoid cost surprises
- Apply tags for Environment, Project, ManagedBy
- Use group-level dashboards to see the status of all resources belonging to a particular application or team, and alert on issues before they affect users
Resource groups are the organizational backbone of most Azure deployments. Getting the naming, tagging, and access control right at this level pays dividends as your infrastructure grows.
Disadvantages and State Management Complexity
While Terraform gives most advantages for managing Azure Resource Groups, there are also some disadvantages to keep in mind:
- Learning Curve: It require domain-specific language (HCL) and configuration syntax which is unique and at times challenging for new learning especially when the new things are being introduced(IaC).
- State Management Complexity: The terraform resource management is dependent on a state file used for monitoring changes. The management of the state file can be complex, notwithstanding the fact that it tends to get complicated in larger environments, or more engagements that involve more teams which are working on the same infrastructure.
- Vendor Lock-in: Even if it is cross-cloud compatible, Terraform has a possibility of vendor lock-in while hosting your instance. Moving from Terraform for Azure infrastructure provisioning, which apparently involved a great deal of configuration, may become a nightmare. You may not be able to quickly migrate even to another IaC tool or cloud provider as a result of this.
- Drift Management: Terraform is able to spot the differences occurring between the desired and the real states for resources, but it may not always be able to rebuild the infrastructure with the same commands that created it initially
The terraform resource management is dependent on a state file used for monitoring changes. The management of the state file can be complex, notwithstanding the fact that it tends to get complicated in larger environments, or more engagements that involve more teams which are working on the same infrastructure.
Conclusion
Azure resource groups provisioned with Terraform form the foundational layer for access control, policy, and cost management in Azure. The azurermresourcegroup resource block with required name and location attributes, and optional tags, establishes the container in which virtual machines, databases, and storage accounts must live. Provider configuration with azurerm ~> 4.0 and azuread ~> 3.0, along with Terraform 1.0 or later and Azure CLI authentication, provides the execution context.
Creation follows init, plan, apply, verification in the Azure portal, and eventual destroy. The foreach meta-argument enables consistent multi-environment resource group creation via map(object) variables. Linking downstream resources such as azurermkubernetescluster to azurermresourcegroup via location and resourcegroup_name references enforces correct dependency ordering and co-location.
Best practices emphasize modular design, naming consistency, tagging, delete locks, budgets, and group-level dashboards. These practices reduce reorganization pain, improve cost visibility, and support access control at scale. The disadvantages of Terraform for Azure resource groups include HCL learning curve, state file management complexity in larger teams, potential vendor lock-in, and imperfect drift remediation.
Getting the structure right early saves you from painful reorganizations later. Resource groups are the first thing you create in any Azure Terraform project. Getting the structure right early saves you from painful reorganizations later.