これは Terraform terraform-providers/terraform-provider-awsで質問されましたが、プロバイダーの問題はあまり注目されていないようです (terraform チームは非常に小さなチームであるため、特にプロバイダーに関するすべての問題を処理することはできませんでした)。 - しかし、これは実際には AWS プロバイダーのブロックの問題であり、再現するのは非常に簡単です。
以下はテスト構成です
variable "domain_name" {
default = "mytest.com"
}
variable "ssl_policy" {
default = "ELBSecurityPolicy-2016-08"
}
data "aws_acm_certificate" "mytest_certificate" {
domain = "*.${var.domain_name}"
}
resource "aws_alb" "alb" {
name = "khiem-test-alb"
internal = false
security_groups = ["sg-35482152"]
subnets = ["subnet-04c29a60", "subnet-d05915a6"]
lifecycle {
create_before_destroy = true
}
}
resource "aws_alb_target_group" "author_target_group" {
name = "khiem-author-target-group"
port = 8080
protocol = "HTTP"
vpc_id = "vpc-32c75856"
health_check = {
protocol = "HTTP"
path = "/.healthcheck/"
port = 8080
healthy_threshold = 5
unhealthy_threshold = 2
timeout = 5
interval = 30
matcher = "200"
}
lifecycle {
create_before_destroy = true
}
}
resource "aws_alb_target_group_attachment" "author_target_group_att" {
target_group_arn = "${aws_alb_target_group.author_target_group.arn}"
target_id = "i-0b305d179d6aacf57"
port = 8080
lifecycle {
create_before_destroy = true
}
}
resource "aws_alb_target_group" "public_target_group" {
name = "khiem-public-target-group"
port = 8080
protocol = "HTTP"
vpc_id = "vpc-32c75856"
health_check = {
protocol = "HTTP"
path = "/.healthcheck/"
port = 8080
healthy_threshold = 5
unhealthy_threshold = 2
timeout = 5
interval = 30
matcher = "200"
}
lifecycle {
create_before_destroy = true
}
}
resource "aws_alb_target_group_attachment" "public_target_group_att" {
target_group_arn = "${aws_alb_target_group.public_target_group.arn}"
target_id = "i-0b305d179d6aacf57"
port = 8080
lifecycle {
create_before_destroy = true
}
}
# http listener
resource "aws_alb_listener" "alb_http_listener" {
load_balancer_arn = "${aws_alb.alb.arn}"
port = "80"
protocol = "HTTP"
default_action {
target_group_arn = "${aws_alb_target_group.public_target_group.arn}"
type = "forward"
}
lifecycle {
create_before_destroy = true
}
}
# http listener rules
resource "aws_alb_listener_rule" "alb_http_public_rule" {
listener_arn = "${aws_alb_listener.alb_http_listener.arn}"
priority = 100
action {
type = "forward"
target_group_arn = "${aws_alb_target_group.public_target_group.arn}"
}
condition {
field = "host-header"
values = ["public-khiem.${var.domain_name}"]
}
lifecycle {
create_before_destroy = true
}
}
resource "aws_alb_listener_rule" "alb_http_author_rule" {
listener_arn = "${aws_alb_listener.alb_http_listener.arn}"
priority = 99
action {
type = "forward"
target_group_arn = "${aws_alb_target_group.author_target_group.arn}"
}
condition {
field = "host-header"
values = ["author-khiem.${var.domain_name}"]
}
lifecycle {
create_before_destroy = true
}
}
# https listener
resource "aws_alb_listener" "alb_https_listener" {
load_balancer_arn = "${aws_alb.alb.arn}"
port = "443"
protocol = "HTTPS"
ssl_policy = "${var.ssl_policy}"
certificate_arn = "${data.aws_acm_certificate.mytest_certificate.arn}"
default_action {
target_group_arn = "${aws_alb_target_group.public_target_group.arn}"
type = "forward"
}
lifecycle {
create_before_destroy = true
}
}
# https listener rules
resource "aws_alb_listener_rule" "alb_https_public_rule" {
listener_arn = "${aws_alb_listener.alb_https_listener.arn}"
priority = 100
action {
type = "forward"
target_group_arn = "${aws_alb_target_group.public_target_group.arn}"
}
condition {
field = "host-header"
values = ["public-khiem.${var.domain_name}"]
}
lifecycle {
create_before_destroy = true
}
}
resource "aws_alb_listener_rule" "alb_https_author_rule" {
listener_arn = "${aws_alb_listener.alb_https_listener.arn}"
priority = 99
action {
type = "forward"
target_group_arn = "${aws_alb_target_group.author_target_group.arn}"
}
condition {
field = "host-header"
values = ["author-khiem.${var.domain_name}"]
}
lifecycle {
create_before_destroy = true
}
}
基本的に、構成は Application Load Balancer、2 つのターゲット グループ、およびドメインに基づいて各ターゲット グループにリクエストをルーティングするための http/https リスナーを作成するだけです。
この単純なセットアップは正しく機能するはずです (そして、過去には機能していました)。つい最近、作成/破棄の両方で不安定になり、HTTP または HTTPS リスナー リソースが Terraform 状態で適切に記録されず、他のリソースでエラーが発生することがわかりました。リソースはそれらに依存します ( aws_alb_listener_rule など)。以下は、作成時のエラーです。
Error applying plan:
2 error(s) occurred:
* aws_alb_listener_rule.alb_http_public_rule: Resource 'aws_alb_listener.alb_http_listener' does not have attribute 'arn' for variable 'aws_alb_listener.alb_http_listener.arn'
* aws_alb_listener_rule.alb_http_author_rule: Resource 'aws_alb_listener.alb_http_listener' does not have attribute 'arn' for variable 'aws_alb_listener.alb_http_listener.arn'
Terraform does not automatically rollback in the face of errors.
Instead, your Terraform state file has been partially updated with
any resources that successfully completed. Please address the error
above and apply again to incrementally change your infrastructure.
これは毎回発生するわけではありませんが、最近頻繁に発生するようになり、次のような一連のコマンドを実行することで簡単に再現できる可能性があります
terraform apply && terraform destroy -force && terraform apply && terraform destroy -force
Terraform 0.9.8 および 0.10.7 でテストしたところ、同じ不安定性のエラーが発生しました。同じコマンドを再度実行するとエラーが発生し、ほとんど問題なく動作しましたが、これは自動化プロセスのブロックです。