Проблемы с перебиранием списка или набора элементов в Terraform - PullRequest
1 голос
/ 30 мая 2019

Я пытаюсь запустить экземпляры AWS в разных подсетях, созданных в AZ, используя переменную count по списку идентификаторов подсетей, это приводит к ошибкам с сообщениями об ошибках с разными подходами.

Я пытался использовать element () и [count.index], я использую TF v12.

Ниже приведен фрагмент кода, пожалуйста, игнорируйте строки с # (закомментировано).

resource "aws_instance" "workers" {
#count         =   length(data.terraform_remote_state.network.outputs.public_subnet_list)
count         = length(data.aws_subnet_ids.subnet_list.ids)
instance_type = var.worker_instance_type
ami           = var.k8_ami
key_name      = aws_key_pair.ssh_key.key_name
#subnet_id     = "${data.terraform_remote_state.network.outputs.public_subnet_list[count.index]}"
subnet_id = "${element(data.aws_subnet_ids.subnet_list.ids, count.index)}"
vpc_security_group_ids = [
aws_security_group.kubernetes.id
]
}

Ниже приведены два фрагмента ошибки.

Error: Invalid index

on k8-cluster.tf line 85, in resource "aws_instance" "workers":
85:   subnet_id = "${data.aws_subnet_ids.subnet_list.ids[count.index]}"
|----------------
| count.index is 2
| data.aws_subnet_ids.subnet_list.ids is set of string with 4 elements

This value does not have any indices.

Еще одна ошибка с элементом ():

Error: Error in function call

on k8-cluster.tf line 85, in resource "aws_instance" "workers":
85:   subnet_id = "${element(data.aws_subnet_ids.subnet_list.ids, count.index)}"
|----------------
| count.index is 3
| data.aws_subnet_ids.subnet_list.ids is set of string with 4 elements

Call to function "element" failed: cannot read elements from set of string.

Ответы [ 2 ]

1 голос
/ 03 июня 2019

Основная проблема здесь в том, что data.aws_subnet_ids.subnet_list.ids является установленным значением, а не списком значением, и поэтому его элементы не находятся в определенном порядке и поэтому недоступныпо числовому индексу в список.

Чтобы использовать его в качестве списка, необходимо решить, как упорядочить элементы.В этом случае кажется, что порядок не очень важен, потому что цель состоит в том, чтобы просто создать один экземпляр для каждой подсети, поэтому передачи набора в функцию sort должно быть достаточно для их лексической сортировки:

resource "aws_instance" "workers" {
  count         = length(data.terraform_remote_state.network.outputs.public_subnet_list)
  instance_type = var.worker_instance_type
  ami           = var.k8_ami
  key_name      = aws_key_pair.ssh_key.key_name
  subnet_id     = sort(data.terraform_remote_state.network.outputs.public_subnet_list)[count.index]
  vpc_security_group_ids = [
    aws_security_group.kubernetes.id
  ]
}

В будущей версии Terraform (недоступной на момент написания в v0.12.0) планируется новая функция for_each, которая сделает это более простым:

resource "aws_instance" "workers" {
  # Planned for a future Terraform release; not in v0.12.0
  for_each = data.terraform_remote_state.network.outputs.public_subnet_list

  instance_type = var.worker_instance_type
  ami           = var.k8_ami
  key_name      = aws_key_pair.ssh_key.key_name
  subnet_id     = each.value
  vpc_security_group_ids = [
    aws_security_group.kubernetes.id
  ]
}

Преимуществоиспользование for_each после его реализации (помимо краткости) заключается в том, что он также скажет Terraform идентифицировать отдельные экземпляры этого ресурса по строке идентификатора подсети, а не по позиции в списке.Это означает, что добавление новых подсетей в будущем не приведет к тому, что последующие экземпляры будут «смещены» и без необходимости воссозданы, как было бы верно для моего исходного примера выше.

0 голосов
/ 30 мая 2019

Вам просто нужно изменить счет следующим образом:

count = "${length(data.aws_subnet_ids.subnet_list.ids)}"

И когда вы цитируете переменные, я предлагаю вам сделать это так:

"${var.var_name}" 

Таким образом, весь код будет выглядеть так:

resource "aws_instance" "workers" {
    #count         =   "${length(data.terraform_remote_state.network.outputs.public_subnet_list)}"
    count         = "${length(data.aws_subnet_ids.subnet_list.ids)}"
    instance_type = "${var.worker_instance_type}"
    ami           = "${var.k8_ami}"
    key_name      = "${aws_key_pair.ssh_key.key_name}"
    #subnet_id     = "${data.terraform_remote_state.network.outputs.public_subnet_list[count.index]}"
    subnet_id = "${element(data.aws_subnet_ids.subnet_list.ids, count.index)}"
    vpc_security_group_ids = [
    "${aws_security_group.kubernetes.id}"
    ]
}

Вы можете увидеть пример в Terraform .

...