> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Multiple Resources

> Explains how to define and manage multiple Azure resources with Terraform using provider declaration, resource blocks, inter-resource references, and plan apply workflow.

So far we've been working with single resources to learn Terraform syntax. Real-world infrastructure rarely consists of only one resource — applications typically require networking, storage, databases, compute, and supporting services working together.

This lesson shows how to define multiple resources in one Terraform configuration so they are managed together predictably and repeatably.

Concept overview

* A provider (for example, the AzureRM provider) is the communication layer between Terraform and a cloud platform such as Azure.
* Providers implement many resource types (virtual networks, storage accounts, SQL databases, Kubernetes clusters, etc.).
* Each resource type documents its available arguments (some required, some optional) in the Terraform provider docs: [https://registry.terraform.io/](https://registry.terraform.io/).

<Frame>
  <img src="https://mintcdn.com/kodekloud-c4ac6d9a/9l60TCpe5-axPZIp/images/Terraform-On-Azure/HashiCorp-Configuration-Language/Multiple-Resources/azurerm-provider-resource-management-diagram.jpg?fit=max&auto=format&n=9l60TCpe5-axPZIp&q=85&s=94b10edf6e9ade203da00ab853e8122d" alt="The image illustrates the concept of managing multiple resources using the &#x22;azurerm provider,&#x22; featuring icons for SQL and other services with associated arguments. There's also a section on the right outlining an argument reference guide for configuring these resources." width="1920" height="1080" data-path="images/Terraform-On-Azure/HashiCorp-Configuration-Language/Multiple-Resources/azurerm-provider-resource-management-diagram.jpg" />
</Frame>

Key concept: Terraform is declarative — you describe the desired state and Terraform determines the actions required to reach that state. When multiple resource blocks are present in the same configuration, Terraform analyzes references between them to determine ordering and dependencies.

Example: resource group, virtual network, storage account
Below is a concise, real-world example showing multiple resources in a single configuration. Note how resources reference one another (so values are not duplicated) and how blocks are structured.

```hcl theme={null}
provider "azurerm" {
  features {}
}

# Create a Resource Group
resource "azurerm_resource_group" "rg" {
  name     = "kodekloud-tf-rg"
  location = "eastus"
}

# Create a Virtual Network (references the resource group by name)
resource "azurerm_virtual_network" "vnet" {
  name                = "kodekloud-tf-vnet"
  resource_group_name = azurerm_resource_group.rg.name
  location            = azurerm_resource_group.rg.location
  address_space       = ["10.0.0.0/16"]
}

# Create a Storage Account (references the resource group and uses the SKU block)
resource "azurerm_storage_account" "sa" {
  name                     = "stkodekloudtfsa45778" # Storage account names must be globally unique and lowercase
  resource_group_name      = azurerm_resource_group.rg.name
  location                 = azurerm_resource_group.rg.location
  kind                     = "StorageV2"

  sku {
    name = "Standard_LRS"
  }
}
```

Why references matter

* Each resource block is syntactically independent, but Terraform reads them together and constructs a plan.
* By referencing `azurerm_resource_group.rg.name` and `azurerm_resource_group.rg.location` you avoid duplicating literal values and let Terraform infer implicit dependencies (e.g., the resource group is created before resources that reference it).

If you prefer a more explicit (but duplicative) style while learning, you can hard-code `resource_group_name` and `location` in each resource. This works functionally but increases maintenance overhead:

```hcl theme={null}
provider "azurerm" {
  features {}
}

resource "azurerm_resource_group" "rg" {
  name     = "kodekloud-tf-rg"
  location = "eastus"
}

resource "azurerm_virtual_network" "vnet" {
  name                = "kodekloud-tf-vnet"
  resource_group_name = "kodekloud-tf-rg"
  location            = "eastus"
  address_space       = ["10.0.0.0/16"]
}

resource "azurerm_storage_account" "sa" {
  name                = "stkodekloudtfsa45778"
  resource_group_name = "kodekloud-tf-rg"
  location            = "eastus"
  kind                = "StorageV2"

  sku {
    name = "Standard_LRS"
  }
}
```

<Callout icon="lightbulb" color="#1CB2FE">
  Storage account names and other cloud resource names must follow provider-specific rules (for example, storage account names in Azure must be 3–24 characters, lowercase letters and numbers, and globally unique). These are Azure rules, not Terraform rules.
</Callout>

terraform plan and apply — what to expect

* `terraform plan` compares the declared desired state with the current state, showing what will be added, changed, or destroyed.
* `terraform apply` executes the plan and streams provisioning progress.

Example trimmed `terraform plan` output:

```plaintext theme={null}
Plan: 2 to add, 1 to change, 0 to destroy.

Note: You didn't use the --out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now.
```

Example trimmed `terraform apply --auto-approve` output:

```plaintext theme={null}
azurerm_resource_group.rg: Creating...
azurerm_virtual_network.vnet: Creating...
azurerm_storage_account.sa: Creating...
azurerm_resource_group.rg: Creation complete after 2s [id=/subscriptions/.../resourceGroups/kodekloud-tf-rg]
azurerm_virtual_network.vnet: Creation complete after 5s [id=/subscriptions/.../resourceGroups/kodekloud-tf-rg/providers/Microsoft.Network/virtualNetworks/kodekloud-tf-vnet]
azurerm_storage_account.sa: Creation complete after 41s [id=/subscriptions/.../resourceGroups/kodekloud-tf-rg/providers/Microsoft.Storage/storageAccounts/stkodekloudtfsa45778]

Apply complete! Resources: 2 added, 1 changed, 0 destroyed.
```

Verify in the Azure Portal
After apply completes you can confirm the created resources in the Azure Portal.

<Frame>
  <img src="https://mintcdn.com/kodekloud-c4ac6d9a/9l60TCpe5-axPZIp/images/Terraform-On-Azure/HashiCorp-Configuration-Language/Multiple-Resources/azure-portal-resource-groups-kodekloud.jpg?fit=max&auto=format&n=9l60TCpe5-axPZIp&q=85&s=ea304a999d3e5fc289341b63347f233d" alt="The image shows a Microsoft Azure portal interface displaying resource groups and resources within a selected group named &#x22;kodekloud-tf-rg,&#x22; which includes a virtual network and a storage account located in East US." width="1920" height="1080" data-path="images/Terraform-On-Azure/HashiCorp-Configuration-Language/Multiple-Resources/azure-portal-resource-groups-kodekloud.jpg" />
</Frame>

Quick reference table

| Resource Type   | Purpose                         | Example reference              |
| --------------- | ------------------------------- | ------------------------------ |
| Resource Group  | Container for resources         | `azurerm_resource_group.rg`    |
| Virtual Network | Networking (subnets, IP ranges) | `azurerm_virtual_network.vnet` |
| Storage Account | Blob/file/table storage         | `azurerm_storage_account.sa`   |

Further reading and references

* Terraform Provider documentation: [https://registry.terraform.io/](https://registry.terraform.io/)
* Azure Portal: [https://portal.azure.com/](https://portal.azure.com/)

Advanced topics such as outputs, explicit dependencies, interpolation functions, and lifecycle customizations are beyond this lesson. For now, focus on the core structure: provider declaration + multiple resource blocks, using references to avoid duplication and let Terraform build an accurate execution plan.

<CardGroup>
  <Card title="Watch Video" icon="video" cta="Learn more" href="https://learn.kodekloud.com/user/courses/terraform-on-azure/module/2dc00bf7-fa00-41df-a4e0-bce9fb23c19d/lesson/ffd22529-0143-407a-85de-e494843e38d7" />
</CardGroup>
