skip to Main Content

I’m new to Terraform and trying to figure out how to use it to create multiple VMs in different Azure regions. I’m expecting it to do the entire deployment, including creating VNETs, subnets, NICs, and everything related to the VM. I’ve gotten pretty far, but am stuck on how to get the subnet ID that gets created and use it in the NIC creation. I have tried a few different things and can’t get it to work how I need it to. If there is a more efficient way to achieve this I’d love to hear it!

Here’s my code:


variable "regions" {
    type = map(object({
        name = string
        region = string
        address_space = string
        }))
        default = {
            "us-east-2" = {
                name = "us-east-2"
                region = "East US 2"
                address_space = "10.1.0.0/16"
            },
            "uk-south" = {
                name = "uk-south"
                region = "UK South"
                address_space = "10.2.0.0/16"
            },
            "aus-east" = {
                name = "aus-east"
                region = "Australia East"
                address_space = "10.3.0.0/16"
            }
        }
}

variable "resource-group" {
    default = "rg-vm"
}


resource "azurerm_virtual_network" "vnet" {
    for_each = var.regions 

    name = "vnet-${each.value.name}"
    location = each.value.region
    resource_group_name = var.resource-group
    address_space = ["${each.value.address_space}"]
}

resource "azurerm_subnet" "subnet-lan" {
    for_each = var.regions

    name = "vnet-${each.value.name}-LAN"
    resource_group_name = var.resource-group
    virtual_network_name = "vnet-${each.value.name}"
    address_prefixes = ["${cidrsubnet(each.value.address_space, 8, 1)}"]
}

output "subnet_ids" {
    value = {
        for k, v in azurerm_subnet.subnet-lan : k => v.id
    }

    depends_on = [azurerm_subnet.subnet-lan]
}

resource "azurerm_network_interface" "nic" {
    for_each = var.regions

    name = "nic-${each.value.name}-ub-vm01"
    location = each.value.region 
    resource_group_name = var.resource-group

    ip_configuration {
      name = "ipconfig1"
      subnet_id = each.value.id
      private_ip_address_allocation = "Dynamic"
    }

}

I have tried using an output clause among other things and I keep getting errors when trying to reference the subnets that get created.

2

Answers


  1. Using output from one terraform resource for_each in another resource

    Issue seems to with the way you refer the each.value.id for azurerm_network_interface this refers won’t add the actual ID which may results in the blocker.

    Try refer as mentioned below make necessay changes as in the way you refering subnet in NIC as mentioned below

    Demo configuration:

    variable "regions" {
        type = map(object({
            name          = string
            region        = string
            address_space = string
        }))
        default = {
            "us-east-2" = {
                name          = "usvk-east-2"
                region        = "East US 2"
                address_space = "10.1.0.0/16"
            },
            "uk-south" = {
                name          = "ukvk-south"
                region        = "UK South"
                address_space = "10.2.0.0/16"
            },
            "aus-east" = {
                name          = "ausvk-east"
                region        = "Australia East"
                address_space = "10.3.0.0/16"
            }
        }
    }
    
    variable "resource_group_name" {
        default = "rgvk-vm"
    }
    
    resource "azurerm_resource_group" "rg" {
        name     = var.resource_group_name
        location = "East US"
    }
    
    resource "azurerm_virtual_network" "vnet" {
        for_each = var.regions
    
        name                = "vnet-${each.value.name}"
        location            = each.value.region
        resource_group_name = azurerm_resource_group.rg.name
        address_space       = [each.value.address_space]
    }
    
    resource "azurerm_subnet" "subnet" {
        for_each = var.regions
    
        name                 = "subnet-${each.value.name}"
        resource_group_name  = azurerm_resource_group.rg.name
        virtual_network_name = azurerm_virtual_network.vnet[each.key].name
        address_prefixes     = ["${cidrsubnet(each.value.address_space, 8, 1)}"]
    }
    
    resource "azurerm_network_interface" "nic" {
        for_each = var.regions
    
        name                = "nic-${each.value.name}-ub-vm01"
        location            = each.value.region
        resource_group_name = azurerm_resource_group.rg.name
    
        ip_configuration {
            name                          = "ipconfig1"
            subnet_id                     = azurerm_subnet.subnet[each.key].id
            private_ip_address_allocation = "Dynamic"
        }
    }
    

    deployment:

    enter image description here

    enter image description here

    Refer:

    https://build5nines.com/terraform-ip-functions-for-managing-ip-addresses-cidr-blocks-and-subnets/

    https://discuss.hashicorp.com/t/multiple-for-each/51076

    https://dev.azure.com/v-scheedella/MT%20Stack%20Overflow/_workitems/edit/42784

    Login or Signup to reply.
  2. To correctly reference the subnet ID created in a azurerm_subnet resource when creating an azurerm_network_interface, ensure that you use the same for_each key to access the subnet ID. This allows you to dynamically reference the subnet ID for each region using expression.

    variable "regions" {
        type = map(object({
            name           = string
            region         = string
            address_space  = string
        }))
        default = {
            "us-east-2" = {
                name          = "us-east-2"
                region        = "East US 2"
                address_space = "10.1.0.0/16"
            },
            "uk-south" = {
                name          = "uk-south"
                region        = "UK South"
                address_space = "10.2.0.0/16"
            },
            "aus-east" = {
                name          = "aus-east"
                region        = "Australia East"
                address_space = "10.3.0.0/16"
            }
        }
    }
    
    variable "resource-group" {
        default = "rg-vm"
    }
    
    resource "azurerm_virtual_network" "vnet" {
        for_each = var.regions
    
        name                = "vnet-${each.value.name}"
        location            = each.value.region
        resource_group_name = var.resource-group
        address_space       = [each.value.address_space]
    }
    
    resource "azurerm_subnet" "subnet_lan" {
        for_each = var.regions
    
        name                 = "subnet-${each.value.name}-LAN"
        resource_group_name  = var.resource-group
        virtual_network_name = azurerm_virtual_network.vnet[each.key].name
        address_prefixes     = [cidrsubnet(each.value.address_space, 8, 1)]
    }
    
    output "subnet_ids" {
        value = {
            for k, v in azurerm_subnet.subnet_lan : k => v.id
        }
    }
    
    resource "azurerm_network_interface" "nic" {
        for_each = var.regions
    
        name                = "nic-${each.value.name}-ub-vm01"
        location            = each.value.region
        resource_group_name = var.resource-group
    
        ip_configuration {
            name                          = "ipconfig1"
            subnet_id                     = azurerm_subnet.subnet_lan[each.key].id
            private_ip_address_allocation = "Dynamic"
        }
    }
    
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search