Содержание
Что такое ошибка 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 и развернули наши ресурсы.










