J'essaie de lancer des instances AWS dans différents sous-réseaux créés dans des zones de disponibilité en utilisant la variable count sur une liste d'ID de sous-réseau, cela échoue avec des messages d'erreur avec des approches différentes.
J'ai essayé d'utiliser element () et d'utiliser [count .index], j'utilise TF v12.
Voici un extrait du code, veuillez ignorer les lignes avec # (commenté).
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.
Ci-dessous sont deux extraits d'erreur.
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.
Une autre erreur avec element ():
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 ] }
3 Réponses :
Il vous suffit de changer le décompte comme ceci:
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}" ] }
Et lorsque vous citez les variables, je vous suggère de le faire comme ceci:
"${var.var_name}"
Merci, mais cela donne toujours l'erreur Erreur: Erreur dans l'appel de la fonction ... L'appel de la fonction "élément" a échoué: impossible de lire les éléments du jeu de chaînes. '
EDIT: juste pour ajouter, c'est activé TF v12, pas v11. Cela pourrait être un bug?
@ mzs_47 Vous pouvez peut-être afficher les subnet_ids pour vérifier s'il obtient vraiment les ID de sous-réseau.
Oui, il contient quatre éléments, si vous avez remarqué les extraits d'erreur ci-dessus, le nombre varie et il mentionne `` est un ensemble de chaînes avec 4 éléments '', par souci de concision, je viens d'en coller un pour chaque méthode que j'ai essayée.
@ mzs_47 Je n'ai aucune expérience avec AWS. Mais d'après l'erreur que vous montrez, il semble que le count.index 1 soit OK et les après pas. Si c'est OK si vous utilisez la v11?
Malheureusement, je ne peux pas passer à la v11 atm,: (Je vais devoir prendre le temps de citer les expressions pour que cela fonctionne. Je vais essayer cela plus tard. Merci!
Le problème racine ici est que data.aws_subnet_ids.subnet_list.ids
est une valeur set , plutôt qu'une valeur list , et donc ses éléments ne sont pas dans un ordre particulier et ne sont donc pas accessibles par index numérique dans une liste.
Pour l'utiliser comme une liste, il faut décider comment ordonner les éléments. Dans ce cas, il semble que l'ordre n'est pas vraiment important car le but est simplement de créer une instance par sous-réseau, donc passer l'ensemble à la fonction sort
devrait être suffisant pour les trier lexicalement: p>
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 ] }
Dans une future version de Terraform (non disponible au moment de la rédaction de la v0.12.0), une nouvelle fonctionnalité for_each
est prévue pour rendre cela plus simple:
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 ] }
Un avantage d'utiliser for_each
une fois qu'il est implémenté (mis à part la brièveté) est qu'il indiquera également à Terraform d'identifier instances individuelles de cette ressource par la chaîne d'identifiant de sous-réseau, plutôt que par position dans la liste. Cela signifie que l'ajout de nouveaux sous-réseaux à l'avenir n'entraînera pas de "décalage" des instances ultérieures et de recréation inutile, comme ce serait le cas avec mon exemple original ci-dessus.
Merci pour ça!
Ce problème se produit car les données renvoyées sont sous la forme d'un "SET", tandis que l'élément attend l'entrée sous la forme d'une "LISTE".
Pour résoudre le problème, vous devez le convertir en liste.
subnet_id = "$ {element (tolist (data.aws_subnet_ids.subnet_list.ids), count.index)}"