Как создать несколько сетевых адаптеров виртуальной машины в цикле, используя terraform с назначенным статическим IP-адресом

#terraform-provider-azure

#terraform-provider-azure

Вопрос:

Я пытаюсь создать 2 виртуальные машины в Azure с использованием Terraform, и для каждой виртуальной машины требуется 4 сетевых адаптера, по одному в каждой подсети виртуальной сети, и эти сетевые адаптеры должны быть настроены со статическими IP-адресами. Есть ли какой-либо способ добиться этого, используя циклы в идеале с for_each?

Я могу сделать это с помощью «динамического» назначения IP-адреса для блока ip_configuration без проблем, но мне нужно, чтобы он работал со «статическим» назначением IP и не знаю, как передать ip-адрес внутри блока ip_configuration блока ресурсов сетевого интерфейса.

Я не знаю, подходит ли динамический блок для этой модели, но я попытался использовать вложенный цикл с динамическим блоком ip_configuration без особой удачи 🙁

Вот что у меня есть на данный момент (фрагмент для сетевых адаптеров для подсети 1), и я хотел бы получить некоторую помощь;

 variable "subnet1IpAddresses" {
  type        = map(string)
  description = "The subnet1 IP address to assign to vm nodes."
  default = {
    "1" = "10.10.1.4"  
    "2" = "10.10.1.5"
  }
}

locals {
  vmName = [format("%s%s%s%s%s", var.envPrefix, "-", var.dptPrefix, var.vmPrefix, "01"), format("%s%s%s%s%s", var.envPrefix, "-", var.dptPrefix, var.vmPrefix, "02")]
  subnet1Ip = [var.subnet1IpAddresses[1], var.subnet1IpAddresses[2]] 
}

#create NIC for each NVA and Assign Static IP addresses.
    resource "azurerm_network_interface" "subnet1Nics" {
      for_each                      = toset(local.vmName)
      name                          = "${each.value}subnet1-nic"
      resource_group_name           = azurerm_resource_group.rg.name
      location                      = azurerm_resource_group.rg.location
      enable_ip_forwarding          = "true"
      enable_accelerated_networking = "true"
    
      dynamic ip_configuration {
        for_each = local.subnet1Ip
        content {
          name                          = "ipconfig1"
          subnet_id                     = azurerm_subnet.snet1.id
          private_ip_address            = ip_configuration.value
          private_ip_address_allocation = "static"
          primary                       = "true"
        }
      }
    }
 

Проблема с приведенным выше кодом «как есть» заключается в том, что он пытается создать две конфигурации ip_configurations для одной и той же виртуальной машины, поэтому VM1 будет иметь nic1 с двумя конфигурациями IP, т.Е. (10.10.1.4 и 10.10.1.5), но это не то, что мне нужно.

Проще говоря, ниже приведен результат, который я желаю для этого конкретного примера и надеюсь, что кто-нибудь сможет помочь с этим.

 VM1's nic1 with IP (10.10.1.4)
VM2's nic1 with IP (10.10.1.5)
 

Спасибо.

Комментарии:

1. Вы хотите, чтобы каждый сетевой адаптер находился в каждой подсети? затем вам нужно создать 8 сетевых адаптеров. Вы пытались использовать цикл for.

2. Правильно, 2 сетевых адаптера в каждой подсети, и пример кода, который я вставил выше, предназначен для одной подсети, остальные будут следовать той же логике. Если у вас есть какой-либо другой способ добиться этого, пожалуйста, не могли бы вы поделиться примером кода?

3. Есть какие-либо обновления по этому вопросу? Решает ли это вашу проблему?

4. @CharlesXu Спасибо за продолжение. В итоге я немного изменился и использовал cidrhost для вычисления IP-адреса с подсчетом для каждой сетевой карты подсети. Я попробую ваше предложение и принял ваш ответ.

Ответ №1:

Вот пример для ваших целей: 2 виртуальные машины, каждая виртуальная машина имеет 4 сетевых адаптера, 4 подсети во виртуальной сети, каждая сетевая карта виртуальной машины в подсети.

main.tf:

 provider "azurerm" {
  features {}
}

variable "nics" {}

variable "vnet_prefix" {}

variable "subnet_prefixes" {}

resource "azurerm_resource_group" "group" {
  name              = "charlesVM"
  location          = "East Asia" 
}

resource "azurerm_virtual_network" "vnet" {
  name              = "charles-vnet"
  resource_group_name = azurerm_resource_group.group.name
  location          = azurerm_resource_group.group.location
  address_space     = var.vnet_prefix
}

resource "azurerm_subnet" "subnets" {
  count             = length(var.subnet_prefixes)
  name              = "subnet-${count.index}"
  resource_group_name = azurerm_resource_group.group.name
  virtual_network_name = azurerm_virtual_network.vnet.name
  address_prefix    = element(var.subnet_prefixes, count.index)
}

resource "azurerm_network_interface" "nics" {
  count             = length(var.nics)
  name              = "nic-${count.index}"
  location          = azurerm_resource_group.group.location
  resource_group_name = azurerm_resource_group.group.name

  ip_configuration {
    name            = "config-${count.index}"
    subnet_id       = element(azurerm_subnet.subnets[*].id, count.index % 4)
    private_ip_address_allocation = "Static"
    private_ip_address = element(var.nics, count.index)
  }
}

locals {
  vm_nics = chunklist(azurerm_network_interface.nics[*].id, 4)
}

resource "azurerm_linux_virtual_machine" "vm" {
  count             = 2
  name              = "azurevm-${count.index}"
  resource_group_name = azurerm_resource_group.group.name
  location          = azurerm_resource_group.group.location
  size              = "Standard_DS3_v2"
  admin_username    = "adminuser"
  network_interface_ids = element(local.vm_nics, count.index)

  admin_ssh_key {
    username   = "adminuser"
    public_key = file("~/.ssh/id_rsa.pub")
  }

  os_disk {
    caching              = "ReadWrite"
    storage_account_type = "Standard_LRS"
  }

  source_image_reference {
    publisher = "Canonical"
    offer     = "UbuntuServer"
    sku       = "16.04-LTS"
    version   = "latest"
  }
}
 

терраформирование.tfvar:

 nics = [
    "10.0.0.4",
    "10.0.1.4",
    "10.0.2.4",
    "10.0.3.4",
    "10.0.0.5",
    "10.0.1.5",
    "10.0.2.5",
    "10.0.3.5"
]
vnet_prefix = ["10.0.0.0/16"]
subnet_prefixes = [
    "10.0.0.0/24",
    "10.0.1.0/24",
    "10.0.2.0/24",
    "10.0.3.0/24"
]
 

Обратите внимание, что вы хотите использовать статический IP-адрес, тогда вам нужно вычислить их вручную, чтобы избежать конфликта, и убедиться, что каждый IP-адрес сетевой карты находится прямо в подсети. И вам также необходимо выбрать правильный размер виртуальной машины, который может поддерживать 4 сетевых адаптера для одной виртуальной машины.

Комментарии:

1. Хорошо, только незначительные ошибки: network_interface_ids и address_prefix должны быть списком [].