При роботі з інфраструктурою у хмарних середовищах, особливо в AWS, використання інструменту автоматизації Terraform є надзвичайно корисним. Однак, іноді виникають ситуації, коли потрібно дещо складніше конфігурувати інфраструктуру, ніж це можливо зробити за допомогою звичайних директив Terraform. У цій статті ми розглянемо один з таких випадків – як перенаправити значення “Output” до оператора “for_each”.
Спробуймо розібратися з цим на конкретному прикладі. Нехай у нас є код Terraform для створення інфраструктури AWS, яка містить такі елементи:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
# Створення ресурсу EC2 resource "aws_instance" "terra_prj1_ec2" { ami = "ami-0014ce3e52359afbd" instance_type = "t3.micro" availability_zone = "eu-north-1a" count = 2 key_name = "main-key" iam_instance_profile = aws_iam_instance_profile.terra_prj1_instance_profile.name user_data = file("userdata.sh") network_interface { device_index = 0 network_interface_id = aws_network_interface.terra_prj1_sec_network_interface.id } } # Дані про EC2 output "ec2_target_group_arn" { value = join("", aws_instance.terra_prj1_ec2.*.id) } # Створення групи безпеки для балансувальника навантаження resource "aws_security_group" "terra_prj1_alb_sec_grp" { name = "allow_terra_web_traffic" description = "Allow web inbound traffic" vpc_id = aws_vpc.terra_prj1.id ingress { description = "HTTP" from_port = 80 to_port = 80 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] ipv6_cidr_blocks = ["::/0"] } egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] ipv6_cidr_blocks = ["::/0"] } } # Створення правила групи безпеки для EC2 resource "aws_security_group_rule" "terra_prj1_alb_sec_grp_rule" { type = "ingress" from_port = 8080 to_port = 8080 protocol = "tcp" security_group_id = aws_security_group.terra_prj1_sec_grp.id source_security_group_id = aws_security_group.terra_prj1_alb_sec_grp.id } # Створення цільової групи для балансувальника навантаження resource "aws_lb_target_group" "terra_prj1_alb_target_grp" { name = "terra-prj1-alb-target-grp" port = 8080 protocol = "HTTP" vpc_id = aws_vpc.terra_prj1.id load_balancing_algorithm_type = "round_robin" health_check { enabled = true port = 8081 interval = 30 protocol = "HTTP" path = "/health" matcher = 200 healthy_threshold = 3 unhealthy_threshold = 3 } } # Прикріплення цільової групи resource "aws_lb_target_group_attachment" "terra_prj1_alb_target_grp_attachment" { for_each = output.ec2_target_group_arn[*] target_group_arn = aws_lb_target_group.terra_prj1_alb_target_grp.arn target_id = aws_instance.terra_prj1_ec2[each.key].id depends_on = [aws_lb_target_group.terra_prj1_alb_target_grp] port = 8080 } # Створення балансувальника навантаження resource "aws_lb" "terra_prj1_alb" { name = "terra-prj1-alb" internal = false load_balancer_type = "application" security_groups = [aws_security_group.terra_prj1_alb_sec_grp.id] subnets = [aws_subnet.terra_prj1_subnet.id] } # Створення слухача для балансувальника навантаження resource "aws_lb_listener" "terra_prj1_alb_listener" { load_balancer_arn = aws_lb.terra_prj1_alb.arn port = 80 protocol = "HTTP" default_action { type = "forward" target_group_arn = aws_lb_target_group.terra_prj1_alb_target_grp.arn } } |
При спробі виконання коду ми зіткнулися з помилкою, яка вказує на те, що ресурс “output” не був оголошений в кореневому модулі. Це відбувається через спробу використання значення “Output” у визначенні оператора “for_each” для ресурсу “aws_lb_target_group_attachment”. Ця ситуація може виникнути внаслідок невір