Ошибка удаления целевой группы: ResourceInUse при изменении целевых портов в AWS через Terraform
В настоящее время я работаю над бета-версией "Terraform Up & Running, 2nd Edition". В главе 2 я создал группу автоматического масштабирования и балансировщик нагрузки в AWS.
Теперь я сделал свои порты HTTP внутреннего сервера настраиваемыми. По умолчанию они прослушивают порт 8080.
variable "server_port" {
…
default = 8080
}
resource "aws_launch_configuration" "example" {
…
user_data = <<-EOF
#!/bin/bash
echo "Hello, World" > index.html
nohup busybox httpd -f -p ${var.server_port} &
EOF
…
}
resource "aws_security_group" "instance" {
…
ingress {
from_port = var.server_port
to_port = var.server_port
…
}
}
Этот же порт также необходимо настроить в целевой группе балансировщика нагрузки приложения.
resource "aws_lb_target_group" "asg" {
…
port = var.server_port
…
}
Когда моя инфраструктура уже развернута, например, с настройкой порта 8080, а затем я изменяю переменную на 80, выполнив terraform apply --var server_port=80
появляется следующая ошибка:
> Error: Error deleting Target Group: ResourceInUse: Target group
> 'arn:aws:elasticloadbalancing:eu-central-1:…:targetgroup/terraform-asg-example/…'
> is currently in use by a listener or a rule status code: 400,
Как я могу уточнить определение инфраструктуры Terraform, чтобы сделать это изменение возможным? Я полагаю, это может быть связано с lifecycle
вариант где-то, но мне пока не удалось разобраться.
Для справки я прилагаю все мое определение инфраструктуры ниже:
provider "aws" {
region = "eu-central-1"
}
output "alb_location" {
value = "http://${aws_lb.example.dns_name}"
description = "The location of the load balancer"
}
variable "server_port" {
description = "The port the server will use for HTTP requests"
type = number
default = 8080
}
resource "aws_lb_listener_rule" "asg" {
listener_arn = aws_lb_listener.http.arn
priority = 100
condition {
field = "path-pattern"
values = ["*"]
}
action {
type = "forward"
target_group_arn = aws_lb_target_group.asg.arn
}
}
resource "aws_lb_target_group" "asg" {
name = "terraform-asg-example"
port = var.server_port
protocol = "HTTP"
vpc_id = data.aws_vpc.default.id
health_check {
path = "/"
protocol = "HTTP"
matcher = "200"
interval = 15
timeout = 3
healthy_threshold = 2
unhealthy_threshold = 2
}
}
resource "aws_lb_listener" "http" {
load_balancer_arn = aws_lb.example.arn
port = 80
protocol = "HTTP"
default_action {
type = "fixed-response"
fixed_response {
content_type = "text/plain"
message_body = "404: page not found"
status_code = 404
}
}
}
resource "aws_lb" "example" {
name = "terraform-asg-example"
load_balancer_type = "application"
subnets = data.aws_subnet_ids.default.ids
security_groups = [aws_security_group.alb.id]
}
resource "aws_security_group" "alb" {
name = "terraform-example-alb"
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
resource "aws_autoscaling_group" "example" {
launch_configuration = aws_launch_configuration.example.name
vpc_zone_identifier = data.aws_subnet_ids.default.ids
target_group_arns = [aws_lb_target_group.asg.arn]
health_check_type = "ELB"
min_size = 2
max_size = 10
tag {
key = "Name"
value = "terraform-asg-example"
propagate_at_launch = true
}
}
resource "aws_launch_configuration" "example" {
image_id = "ami-0085d4f8878cddc81"
instance_type = "t2.micro"
security_groups = [aws_security_group.instance.id]
user_data = <<-EOF
#!/bin/bash
echo "Hello, World" > index.html
nohup busybox httpd -f -p ${var.server_port} &
EOF
lifecycle {
create_before_destroy = true
}
}
resource "aws_security_group" "instance" {
name = "terraform-example-instance"
ingress {
from_port = var.server_port
to_port = var.server_port
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
data "aws_subnet_ids" "default" {
vpc_id = data.aws_vpc.default.id
}
data "aws_vpc" "default" {
default = true
}
3 ответа
Из ссылки на проблему в комментарии к вопросу (https://github.com/terraform-providers/terraform-provider-aws/issues/1315):
Добавьте правило жизненного цикла к своей целевой группе, чтобы она стала:
resource "aws_lb_target_group" "asg" {
name = "terraform-asg-example"
port = var.server_port
protocol = "HTTP"
vpc_id = data.aws_vpc.default.id
lifecycle {
create_before_destroy = true
}
health_check {
path = "/"
protocol = "HTTP"
matcher = "200"
interval = 15
timeout = 3
healthy_threshold = 2
unhealthy_threshold = 2
}
}
Однако вам также нужно будет выбрать способ изменения названия вашей целевой группы. Дальнейшее обсуждение и предложения о том, как это сделать, можно найти здесь: https://github.com/terraform-providers/terraform-provider-aws/issues/636
Но одно из возможных решений - просто использовать случайное целое число, но игнорировать изменения имени:
resource "aws_lb_target_group" "asg" {
name = "terraform-asg-example${substr(uuid(),0, 3)}"
port = var.server_port
protocol = "HTTP"
vpc_id = data.aws_vpc.default.id
lifecycle {
create_before_destroy = true
ignore_changes = [name]
}
health_check {
path = "/"
protocol = "HTTP"
matcher = "200"
interval = 15
timeout = 3
healthy_threshold = 2
unhealthy_threshold = 2
}
}
Немного проще, чем решение @FGreg, добавить политику жизненного цикла и переключиться с
name
к
name_prefix
что предотвратит конфликты имен.
resource "aws_lb_target_group" "asg" {
name_prefix = "terraform-asg-example"
port = var.server_port
protocol = "HTTP"
vpc_id = data.aws_vpc.default.id
lifecycle {
create_before_destroy = true
}
health_check {
path = "/"
protocol = "HTTP"
matcher = "200"
interval = 15
timeout = 3
healthy_threshold = 2
unhealthy_threshold = 2
}
}
Нет необходимости в
uuid
или
ignore_changes
настройки.
изменить имя = "terraform-asg-example"
к
name_prefix = "asg-"