Как исправить ошибку Terraform for_each

Как исправить ошибку Terraform for_each

Содержание
  1. Что такое ошибка for_each?
  2. Цели:
  3. Предварительные условия:
  4. Используемые ресурсы:
  5. Шаги для внедрения в этот проект:
    1. 1. Войдите в консоль управления AWS
    2. 2. Создайте инфраструктуру для блока ресурсов
    3. 3. В директории ресурсов terraform_files создадим 4 файла - main.tf, variables.tf, outputs.tf и terrafprm.tfvars.
    4. 4. Инициализация рабочей директории
    5. 5. Исправление ошибки for_each
    6. 6. Развертывание ресурсов
  6. Очистка
  7. Что мы сделали на данный момент

Что такое ошибка for_each?

”Атрибут for_each в Terraform позволяет создать набор похожих ресурсов на основе заданных вами критериев.”

”Когда вам нужно создать набор похожих экземпляров, каждый из которых назначен отдельной группе безопасности. Terraform не может разобрать awssecurity_group..id в этом атрибуте, поскольку выражение splat (_) интерполирует только типы списков, а атрибут for_each предназначен для типов map.

  • Локальное значение может возвращать тип map.
  • Определите локальное значение в файле main.tf. Это преобразует список групп безопасности в карту.

Пожалуйста, посетите мой GitHub-репозиторий статей по Terraform по различным темам, которые постоянно обновляются.

Давайте начнем!

Цели:

1. Войдите в AWS Management Console

2. Создайте инфраструктуру для блока ресурсов

3. В каталоге ресурсов terraform_files создайте 4 файла - main.tf, variables.tf, outputs.tf и terrafprm.tfvars.

4. Инициализация рабочего каталога

5. Исправьте ошибку for_each

6. Разверните ваши ресурсы

Предварительные условия:

  • Учетная запись пользователя AWS с правами администратора, но не root.
  • Cloud9 IDE с AWS CLI.

Используемые ресурсы:

Документация Terraform. Документация Terraform для AMI.. Troubleshoot Terraform - Correct a for_each error. learn-terraform-troubleshooting.

Шаги для внедрения в этот проект:

1. Войдите в консоль управления AWS

  • Убедитесь, что вы находитесь в регионе N. Virginia (us-east-1).

2. Создайте инфраструктуру для блока ресурсов

  • Создадим следующую организационную структуру, как показано ниже.

Описание изображения

3. В директории ресурсов terraform_files создадим 4 файла - main.tf, variables.tf, outputs.tf и terrafprm.tfvars.

  • 1. main.tf
  • замените vpc_id на свой собственный VPC
терраформа {

  required_providers {
    aws = {
      источник = "hashicorp/aws"
      версия = "~> 4.23"
    }
  }

  required_version = ">= 0.14.9"
}

провайдер "aws" {
  регион = var.region
}

данные "aws_ami" "linux" {
   most_recent = true
   owners = ["amazon"]

  фильтр {
    name = "name"
    values = ["amzn2-ami-hvm-*-x86_64-gp2"]
  }

  фильтр {
    name = "тип виртуализации"
    значения = ["hvm"]
  }
}

ресурс "aws_instance" "web_app" {
  for_each = aws_security_group.*.id
  ami = data.aws_ami.linux.id
  availability_zone = var.az_1a
  instance_type = var.instance_type
  vpc_security_group_ids = [each.id]
  user_data = <<-EOF
              #!/bin/bash
              echo "Hello, World" > index.html
              nohup busybox httpd -f -p 8080 &
              EOF
  теги = {
    Name = "${var.name}-mywebapp"
  }
}
 ресурс "aws_security_group" "sg_ping" {
   name = "Allow Ping"
   vpc_id = "<DUMMY VALUE>"
}

ресурс "aws_security_group" "sg_8080" {
   имя = "Разрешить 8080"
   vpc_id = "<DUMMY VALUE>"
}

 ресурс "aws_security_group_rule" "sg_ping" {
   тип = "ingress"
   from_port = -1
   to_port = -1
   протокол = "icmp"
   security_group_id = aws_security_group.sg_ping.id
   source_security_group_id = aws_security_group.sg_8080.id
}

 ресурс "aws_security_group_rule" "sg_8080" {
   типe = "ingress"
   from_port = 8080
   to_port = 8080
   протокол = "tcp"
   security_group_id = aws_security_group.sg_8080.id
   source_security_group_id = aws_security_group.sg_ping.id
}
  • 2. переменные.tf
переменная "регион" {
  описание = "регион"
}

переменная "name" {
  description = "Значение тега Name для экземпляра EC2"
}

переменная "az_1a" {
  описание = "зона доступности 1"
  тип = строка
  по умолчанию = "us-east-1a"
}

переменная "instance_type" {
  description = "Значение тега Name для типа экземпляра EC2"
  тип = строка
  default = "t2.micro"
}
  • 3. outputs.tf
output "instance_id" {
  description = "ID экземпляра EC2"
  value = [for instance in aws_instance.web_app: instance.id]
}

output "instance_public_ip" {
  description = "Публичный IP-адрес экземпляра EC2"
  value = [for instance in aws_instance.web_app: instance.public_ip]
}

выход "instance_name" {
  description = "Теги экземпляра EC2"
  value = [for instance in aws_instance.web_app: instance.tags.Name]
}
  • 4. terrafprm.tfvars
имя = "rev"
регион = "us-east-1"

4. Инициализация рабочей директории

cd terraform_files
  • Формат терраформы
terraform fmt

Описание изображения

  • Создайте рабочий каталог
terraform init

Описание изображения

  • Проверка конфигурации
terraform validate
  • получить ряд ошибок в конфигурационном файле

Описание изображения

5. Исправление ошибки for_each

Ошибки

  • в main.tf - Просмотреть детали всех сообщений об ошибках
    • 1. Исправьте ошибку интерполяции переменных - В строке 33 имеется недопустимая ссылка на атрибут for_each для группы aws_security.
    • Ошибка возникает потому, что выражение * в значении aws_security_group.*.id не поддерживается атрибутом for_each.
Ошибка: Недопустимая ссылка

│ на main.tf строка 33, в ресурсе "aws_instance" "web_app":
│ 33: for_each = aws_security_group.*.id

│ За ссылкой на тип ресурса должно следовать как минимум одно обращение к атрибуту, указывающее на имя ресурса.
  • в main.tf - Просмотр деталей сообщения об ошибке Invalid “each” attribute
    • 2. В строке 37 недопустимый объект “each”, в котором отсутствует атрибут vpc_security_group_ids.
    • Ошибка возникает потому, что значение [each.id] зависит от атрибута for_each
Ошибка: Неверный атрибут "each"

│ на main.tf строка 37, в ресурсе "aws_instance" "web_app":
│ 37: vpc_security_group_ids = [each.id]

1. Исправление ошибок

  • в нижней части файла main.tf объявите локальные переменные для групп безопасности, создаваемых в конфигурационном файле:
локальные переменные {
  security_groups = {
    sg_ping = aws_security_group.sg_ping.id,
    sg_8080 = aws_security_group.sg_8080.id,
  }
}

2. Исправление ошибок

  • В строке 33 замените значение aws_security_group.*.id на local.security.groups
  • заменить
for_each     = aws_security_group.*.id
  • с
for_each = local.security_groups;

3. Исправление ошибок

  • В строке 37 замените значение [each.id] на [each.value]
  • заменить
vpc_security_group_ids = [each.id];
  • с
vpc_security_group_ids = [each.value];

4. Исправление ошибок

  • В строке 44 для атрибута Name тега
  • замените значение
${var.name}-mywebapp
  • с
${var.name}-mywebapp-${each.key}
  • main.tf выглядит следующим образом
терраформа {

  required_providers {
    aws = {
      источник = "hashicorp/aws"
      версия = "~> 4.23"
    }
  }

  required_version = ">= 0.14.9"
}

провайдер "aws" {
  регион = var.region
}

данные "aws_ami" "linux" {
  most_recent = true
  owners = ["amazon"]

  фильтр {
    name = "name"
    values = ["amzn2-ami-hvm-*-x86_64-gp2"]
  }

  фильтр {
    name = "тип виртуализации"
    значения = ["hvm"]
  }
}

ресурс "aws_instance" "web_app" {
  for_each = local.security_groups
  ami = data.aws_ami.linux.id
  availability_zone = var.az_1a
  instance_type = var.instance_type
  vpc_security_group_ids = [each.value]
  user_data = <<-EOF
              #!/bin/bash
              echo "Hello, World" > index.html
              nohup busybox httpd -f -p 8080 &
              EOF
  теги = {
    Name = "${var.name}-mywebapp-${each.key}"
  }
}
ресурс "aws_security_group" "sg_ping" {
  name = "Allow Ping"
  vpc_id = "vpc-0da931f5deb73c9e2"
}

ресурс "aws_security_group" "sg_8080" {
  имя = "Разрешить 8080"
  vpc_id = "vpc-0da931f5deb73c9e2"
}

ресурс "aws_security_group_rule" "sg_ping" {
  тип = "ingress"
  from_port = -1
  to_port = -1
  протокол = "icmp"
  security_group_id = aws_security_group.sg_ping.id
  source_security_group_id = aws_security_group.sg_8080.id
}

ресурс "aws_security_group_rule" "sg_8080" {
  тип = "ingress"
  from_port = 8080
  to_port = 8080
  протокол = "tcp"
  security_group_id = aws_security_group.sg_8080.id
  source_security_group_id = aws_security_group.sg_ping.id
}

локали {
  security_groups = {
    sg_ping = aws_security_group.sg_ping.id,
    sg_8080 = aws_security_group.sg_8080.id,
  }
}
  • Проверьте конфигурацию:
проверить конфигурацию
  • Вы должны получить сообщение об успешном завершении конфигурации.

Описание изображения

6. Развертывание ресурсов

  • Создайте план Terraform
план terraform

Вход в полноэкранный режим

Описание изображения

Описание изображения

  • Создайте ресурсы
применить терраформу
  • введите yes для подтверждения развертывания

Описание изображения

Описание изображения

  • Инстансы EC2 - rev-mywebapp-sg_8080 и rev-mywebapp-sg_ping

Описание изображения

Очистка

разрушение терраформы

Описание изображения

Что мы сделали на данный момент

Мы успешно исправили ошибку for_each и развернули наши ресурсы.