Terraform: как использовать несколько локальных переменных и переменных внутри "for_each" - PullRequest
1 голос
/ 24 января 2020

У меня есть шаблон terraform, который создает несколько экземпляров EC2. Затем я создал несколько сетевых интерфейсов Elasti c в консоли AWS и добавил их как локальные в шаблон terraform. Теперь я хочу отобразить соответствующий ENI для экземпляра, поэтому я добавил локальные и переменные, как показано ниже.

locals {
  instance_ami = {
    A  = "ami-11111"
    B = "ami-22222"
    C  = "ami-33333"
    D   = "ami-4444"
  }
}

variable "instance_eni" {
  description = "Pre created Network Interfaces"
  default = [
    {
      name = "A"
      id   = "eni-0a15890a6f567f487"
    },
    {
      name = "B"
      id   = "eni-089a68a526af5775b"
    },
    {
      name = "C"
      id   = "eni-09ec8ad891c8e9d91"
    },
    {
      name = "D"
      id   = "eni-0fd5ca23d3af654a9"
    }
  ]
}


resource "aws_instance" "instance" {
  for_each = local.instance_ami

  ami           = each.value
  instance_type = var.instance_type
  key_name      = var.keypair

  root_block_device {
    delete_on_termination = true
    volume_size           = 80
    volume_type           = "gp2"
  }


  dynamic "network_interface" {
    for_each = [for eni in var.instance_eni : {
      eni_id = eni.id
    }]

    content {
      device_index          = 0
      network_interface_id  = network_interface.value.eni_id
      delete_on_termination = false
    }
  }
}

Я получаю сообщение об ошибке ниже:

Ошибка: Ошибка запуска экземпляра источника: InvalidParameterValue: для каждого сетевого интерфейса требуется уникальный индекс устройства. код состояния: 400, идентификатор запроса: 4a482753- bddc -4fc3-90f4-2f1c5e2472c7

Я думаю, что terraform пытается подключить все 4 ENI только к одному экземпляру. Что нужно сделать, чтобы прикрепить ENI к отдельному экземпляру?

1 Ответ

0 голосов
/ 24 января 2020

Конфигурация, которой вы поделились в своем вопросе, просит Terraform управлять четырьмя экземплярами, каждый из которых имеет четыре сетевых интерфейса, связанных с ним. Это проблематично c двумя различными способами:

  • Все для сетевых интерфейсов в каждом экземпляре настроены с одинаковым device_index, что недопустимо и является тем, о чем здесь сообщается в сообщении об ошибке.
  • Даже если вы исправите это, он попытается подключить одни и те же четыре сетевых интерфейса к четырем различным экземплярам EC2, что недопустимо: каждый сетевой интерфейс может быть подключен только к одному экземпляру одновременно.

Чтобы решить эту проблему и получить желаемое поведение, вам нужен только один network_interface блок, содержимое которого отличается для каждого из экземпляров:

locals {
  instance_ami = {
    A = "ami-11111"
    B = "ami-22222"
    C = "ami-33333"
    D = "ami-4444"
  }
}

variable "instance_eni" {
  description = "Pre created Network Interfaces"
  default = [
    {
      name = "A"
      id   = "eni-0a15890a6f567f487"
    },
    {
      name = "B"
      id   = "eni-089a68a526af5775b"
    },
    {
      name = "C"
      id   = "eni-09ec8ad891c8e9d91"
    },
    {
      name = "D"
      id   = "eni-0fd5ca23d3af654a9"
    }
  ]
}

locals {
  # This expression is transforming the instance_eni
  # value into a more convenient shape: a map from
  # instance key to network interface id. You could
  # also choose to just change directly the
  # definition of variable "instance_eni" to already
  # be such a map, but I did it this way to preserve
  # your module interface as given.
  instance_network_interfaces = {
    for ni in var.instance_eni : ni.name => ni.id
  }
}

resource "aws_instance" "instance" {
  for_each = local.instance_ami

  ami           = each.value
  instance_type = var.instance_type
  key_name      = var.keypair

  root_block_device {
    delete_on_termination = true
    volume_size           = 80
    volume_type           = "gp2"
  }

  network_interface {
    device_index          = 0
    network_interface_id  = local.instance_network_interfaces[each.key]
    delete_on_termination = false
  }
}

Теперь каждый экземпляр имеет только один сетевой интерфейс, каждый из которых подключается к соответствующему ENI ID, указанному в вашей входной переменной. Обращаясь к each.key и each.value, мы можем создать различия между каждым из объявленных экземпляров при использовании ресурса for_each; нам не нужны никакие другие конструкции повторения внутри, если мы не хотим создавать вложенные повторения, например, наличие динамического c количества сетевых интерфейсов для каждого экземпляра.

...