Terraform 模板在手动更改 EBS 卷后重新创建所有资源
Terraform template re-creating all resources after manually changing EBS vol
我有一个 terraform 模板,它为我们的 6 个后端应用程序创建一个 EC2 实例,并相应地添加安全组规则,以便它可以连接到所需的资源。它还创建了 6 个负载平衡器 (ALB),我们使用它们将后端暴露给外部。
上周我们的生产实例由于磁盘 space 达到 100% 而导致状态检查失败,这是由连续的错误日志引起的。在此事件中,我们必须使用恢复 EC2 实例来恢复我们的生产实例,并且我们必须在我们的生产实例 EBS 卷中执行手动容量增加。
然后我们尝试更新当前的 Terraform 模板以匹配新的 EBS 卷大小,但是它会破坏我们所有的生产资源并在此过程中重新创建它们。
我正在尝试找出一种方法,以某种方式避免模板再次重新创建所有资源,并使模板保持最新状态以匹配新的 EBS 卷容量。
下面是创建EC2实例的代码。
resource "aws_instance" "ec2" {
ami = "${var.ami_id}"
instance_type = "${var.instance_type}"
key_name = "${var.key_pair_name}"
subnet_id = "${var.private_subnet_id}"
iam_instance_profile = "${aws_iam_instance_profile.iam_instance_profile.name}"
/*
* CAUTION: changing value of below fields will cause the EC2 instance to be terminated and
* re-created. Think before running the "apply" command.
*/
associate_public_ip_address = false
tags = {
Environment = "${var.env}"
Project = "${var.project}"
Provisioner="different-box"
Name = "${local.name}"
}
root_block_device {
volume_type = "standard"
volume_size = 50
}
}
即使我更新 volume_size 以匹配新的大小 100,它仍然会重新创建所有资源。
计划产出
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
-/+ destroy and then create replacement
Terraform will perform the following actions:
# aws_instance.ec2 must be replaced
-/+ resource "aws_instance" "ec2" {
ami = "ami-09d1383e2a5ae8a93"
~ arn = "arn:aws:ec2:us-west-2:289914521333:instance/i-0ffa0d29b8fc91930" -> (known after apply)
associate_public_ip_address = false
~ availability_zone = "us-west-2a" -> (known after apply)
~ cpu_core_count = 1 -> (known after apply)
~ cpu_threads_per_core = 2 -> (known after apply)
- disable_api_termination = false -> null
- ebs_optimized = false -> null
get_password_data = false
- hibernation = false -> null
+ host_id = (known after apply)
iam_instance_profile = "iam_instance_profile_prod"
~ id = "i-0ffa0d29b8fc91930" -> (known after apply)
~ instance_state = "running" -> (known after apply)
instance_type = "t3.large"
~ ipv6_address_count = 0 -> (known after apply)
~ ipv6_addresses = [] -> (known after apply)
key_name = "dev_different"
- monitoring = false -> null
+ network_interface_id = (known after apply)
+ password_data = (known after apply)
+ placement_group = (known after apply)
~ primary_network_interface_id = "eni-061cb6a5ca9240438" -> (known after apply)
~ private_dns = "ip-172-31-72-30.us-west-2.compute.internal" -> (known after apply)
~ private_ip = "172.31.72.30" -> (known after apply)
+ public_dns = (known after apply)
+ public_ip = (known after apply)
~ security_groups = [
- "default",
- "different-box.prod-sg",
] -> (known after apply)
source_dest_check = true
subnet_id = "subnet-00beb1529c4ff05af"
tags = {
"Environment" = "prod"
"Name" = "different-box.prod"
"Project" = "different-box"
"Provisioner" = "different-box"
}
~ tenancy = "default" -> (known after apply)
~ volume_tags = {} -> (known after apply)
~ vpc_security_group_ids = [
- "sg-0844f9cd4fb14d5d9",
- "sg-97ef74ef",
] -> (known after apply)
- credit_specification {
- cpu_credits = "unlimited" -> null
}
+ ebs_block_device {
+ delete_on_termination = (known after apply)
+ device_name = (known after apply)
+ encrypted = (known after apply)
+ iops = (known after apply)
+ kms_key_id = (known after apply)
+ snapshot_id = (known after apply)
+ volume_id = (known after apply)
+ volume_size = (known after apply)
+ volume_type = (known after apply)
}
+ ephemeral_block_device {
+ device_name = (known after apply)
+ no_device = (known after apply)
+ virtual_name = (known after apply)
}
+ network_interface {
+ delete_on_termination = (known after apply)
+ device_index = (known after apply)
+ network_interface_id = (known after apply)
}
~ root_block_device {
~ delete_on_termination = false -> true # forces replacement
~ encrypted = false -> (known after apply)
~ iops = 0 -> (known after apply)
+ kms_key_id = (known after apply)
~ volume_id = "vol-01d0d03d564cf44d6" -> (known after apply)
volume_size = 100
volume_type = "standard"
}
}
# aws_network_interface_sg_attachment.sg_attachment must be replaced
-/+ resource "aws_network_interface_sg_attachment" "sg_attachment" {
~ id = "sg-0844f9cd4fb14d5d9_eni-061cb6a5ca9240438" -> (known after apply)
~ network_interface_id = "eni-061cb6a5ca9240438" -> (known after apply) # forces replacement
security_group_id = "sg-0844f9cd4fb14d5d9"
}
# module.alb_admin-mobile-api.aws_alb_target_group_attachment.alb_target_group_attachment must be replaced
-/+ resource "aws_alb_target_group_attachment" "alb_target_group_attachment" {
~ id = "arn:aws:elasticloadbalancing:us-west-2:289914521333:targetgroup/admin-mobile-api-prod-alb-tg/b6940620ef9217f6-20190610084318298800000003" -> (known after apply)
port = 1982
target_group_arn = "arn:aws:elasticloadbalancing:us-west-2:289914521333:targetgroup/admin-mobile-api-prod-alb-tg/b6940620ef9217f6"
~ target_id = "i-0ffa0d29b8fc91930" -> (known after apply) # forces replacement
}
# module.alb_admin-portal-backend.aws_alb_target_group_attachment.alb_target_group_attachment must be replaced
-/+ resource "aws_alb_target_group_attachment" "alb_target_group_attachment" {
~ id = "arn:aws:elasticloadbalancing:us-west-2:289914521333:targetgroup/admin-portal-backend-prod-alb-tg/09e967d1703d0c93-20190610084319310500000004" -> (known after apply)
port = 3001
target_group_arn = "arn:aws:elasticloadbalancing:us-west-2:289914521333:targetgroup/admin-portal-backend-prod-alb-tg/09e967d1703d0c93"
~ target_id = "i-0ffa0d29b8fc91930" -> (known after apply) # forces replacement
}
# module.alb_api.aws_alb_target_group_attachment.alb_target_group_attachment must be replaced
-/+ resource "aws_alb_target_group_attachment" "alb_target_group_attachment" {
~ id = "arn:aws:elasticloadbalancing:us-west-2:289914521333:targetgroup/api-prod-alb-tg/4cb4a656a520c34d-20190610084318237800000001" -> (known after apply)
port = 1984
target_group_arn = "arn:aws:elasticloadbalancing:us-west-2:289914521333:targetgroup/api-prod-alb-tg/4cb4a656a520c34d"
~ target_id = "i-0ffa0d29b8fc91930" -> (known after apply) # forces replacement
}
# module.alb_digitalreign.aws_alb_target_group_attachment.alb_target_group_attachment must be replaced
-/+ resource "aws_alb_target_group_attachment" "alb_target_group_attachment" {
~ id = "arn:aws:elasticloadbalancing:us-west-2:289914521333:targetgroup/digitalreign-prod-alb-tg/c8f0a479686bcaf0-20190610084318291300000002" -> (known after apply)
port = 2040
target_group_arn = "arn:aws:elasticloadbalancing:us-west-2:289914521333:targetgroup/digitalreign-prod-alb-tg/c8f0a479686bcaf0"
~ target_id = "i-0ffa0d29b8fc91930" -> (known after apply) # forces replacement
}
# module.alb_engine-ui.aws_alb_target_group_attachment.alb_target_group_attachment must be replaced
-/+ resource "aws_alb_target_group_attachment" "alb_target_group_attachment" {
~ id = "arn:aws:elasticloadbalancing:us-west-2:289914521333:targetgroup/engine-ui-prod-alb-tg/a2aedefc0c88b5e4-20190701134129654000000001" -> (known after apply)
port = 2016
target_group_arn = "arn:aws:elasticloadbalancing:us-west-2:289914521333:targetgroup/engine-ui-prod-alb-tg/a2aedefc0c88b5e4"
~ target_id = "i-0ffa0d29b8fc91930" -> (known after apply) # forces replacement
}
# module.alb_example-backend.aws_alb_target_group_attachment.alb_target_group_attachment must be replaced
-/+ resource "aws_alb_target_group_attachment" "alb_target_group_attachment" {
~ id = "arn:aws:elasticloadbalancing:us-west-2:289914521333:targetgroup/example-backend-prod-alb-tg/fa7eb3eb4ac1aa95-20190610084319317500000005" -> (known after apply)
port = 2010
target_group_arn = "arn:aws:elasticloadbalancing:us-west-2:289914521333:targetgroup/example-backend-prod-alb-tg/fa7eb3eb4ac1aa95"
~ target_id = "i-0ffa0d29b8fc91930" -> (known after apply) # forces replacement
}
# module.alb_tenant-mobile-api.aws_alb_target_group_attachment.alb_target_group_attachment must be replaced
-/+ resource "aws_alb_target_group_attachment" "alb_target_group_attachment" {
~ id = "arn:aws:elasticloadbalancing:us-west-2:289914521333:targetgroup/tenant-mobile-api-prod-alb-tg/76edfa9edba45f58-20190610084319318900000006" -> (known after apply)
port = 1983
target_group_arn = "arn:aws:elasticloadbalancing:us-west-2:289914521333:targetgroup/tenant-mobile-api-prod-alb-tg/76edfa9edba45f58"
~ target_id = "i-0ffa0d29b8fc91930" -> (known after apply) # forces replacement
}
Plan: 9 to add, 0 to change, 9 to destroy.
------------------------------------------------------------------------
根据计划输出,正在重新创建实例,因为 delete_on_termination
卷已更改。当它附加到恢复实例时,这可能会发生变化。
虽然aws_instance
可能不支持更新选项。但是according to the documentation应该是可以的。
有两种可能的解决方案:
- 如果您不关心在实例终止时删除卷,您可以简单地将
delete_on_termination = false
添加到您的 root_block_device
。由于您尚未设置它,因此使用默认值(即 true
according to the documentation)。
- 在 Terraform 外部将
DeleteOnTermination
参数更改为 true
using the CLI documentation。
我有一个 terraform 模板,它为我们的 6 个后端应用程序创建一个 EC2 实例,并相应地添加安全组规则,以便它可以连接到所需的资源。它还创建了 6 个负载平衡器 (ALB),我们使用它们将后端暴露给外部。
上周我们的生产实例由于磁盘 space 达到 100% 而导致状态检查失败,这是由连续的错误日志引起的。在此事件中,我们必须使用恢复 EC2 实例来恢复我们的生产实例,并且我们必须在我们的生产实例 EBS 卷中执行手动容量增加。
然后我们尝试更新当前的 Terraform 模板以匹配新的 EBS 卷大小,但是它会破坏我们所有的生产资源并在此过程中重新创建它们。
我正在尝试找出一种方法,以某种方式避免模板再次重新创建所有资源,并使模板保持最新状态以匹配新的 EBS 卷容量。
下面是创建EC2实例的代码。
resource "aws_instance" "ec2" {
ami = "${var.ami_id}"
instance_type = "${var.instance_type}"
key_name = "${var.key_pair_name}"
subnet_id = "${var.private_subnet_id}"
iam_instance_profile = "${aws_iam_instance_profile.iam_instance_profile.name}"
/*
* CAUTION: changing value of below fields will cause the EC2 instance to be terminated and
* re-created. Think before running the "apply" command.
*/
associate_public_ip_address = false
tags = {
Environment = "${var.env}"
Project = "${var.project}"
Provisioner="different-box"
Name = "${local.name}"
}
root_block_device {
volume_type = "standard"
volume_size = 50
}
}
即使我更新 volume_size 以匹配新的大小 100,它仍然会重新创建所有资源。
计划产出
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
-/+ destroy and then create replacement
Terraform will perform the following actions:
# aws_instance.ec2 must be replaced
-/+ resource "aws_instance" "ec2" {
ami = "ami-09d1383e2a5ae8a93"
~ arn = "arn:aws:ec2:us-west-2:289914521333:instance/i-0ffa0d29b8fc91930" -> (known after apply)
associate_public_ip_address = false
~ availability_zone = "us-west-2a" -> (known after apply)
~ cpu_core_count = 1 -> (known after apply)
~ cpu_threads_per_core = 2 -> (known after apply)
- disable_api_termination = false -> null
- ebs_optimized = false -> null
get_password_data = false
- hibernation = false -> null
+ host_id = (known after apply)
iam_instance_profile = "iam_instance_profile_prod"
~ id = "i-0ffa0d29b8fc91930" -> (known after apply)
~ instance_state = "running" -> (known after apply)
instance_type = "t3.large"
~ ipv6_address_count = 0 -> (known after apply)
~ ipv6_addresses = [] -> (known after apply)
key_name = "dev_different"
- monitoring = false -> null
+ network_interface_id = (known after apply)
+ password_data = (known after apply)
+ placement_group = (known after apply)
~ primary_network_interface_id = "eni-061cb6a5ca9240438" -> (known after apply)
~ private_dns = "ip-172-31-72-30.us-west-2.compute.internal" -> (known after apply)
~ private_ip = "172.31.72.30" -> (known after apply)
+ public_dns = (known after apply)
+ public_ip = (known after apply)
~ security_groups = [
- "default",
- "different-box.prod-sg",
] -> (known after apply)
source_dest_check = true
subnet_id = "subnet-00beb1529c4ff05af"
tags = {
"Environment" = "prod"
"Name" = "different-box.prod"
"Project" = "different-box"
"Provisioner" = "different-box"
}
~ tenancy = "default" -> (known after apply)
~ volume_tags = {} -> (known after apply)
~ vpc_security_group_ids = [
- "sg-0844f9cd4fb14d5d9",
- "sg-97ef74ef",
] -> (known after apply)
- credit_specification {
- cpu_credits = "unlimited" -> null
}
+ ebs_block_device {
+ delete_on_termination = (known after apply)
+ device_name = (known after apply)
+ encrypted = (known after apply)
+ iops = (known after apply)
+ kms_key_id = (known after apply)
+ snapshot_id = (known after apply)
+ volume_id = (known after apply)
+ volume_size = (known after apply)
+ volume_type = (known after apply)
}
+ ephemeral_block_device {
+ device_name = (known after apply)
+ no_device = (known after apply)
+ virtual_name = (known after apply)
}
+ network_interface {
+ delete_on_termination = (known after apply)
+ device_index = (known after apply)
+ network_interface_id = (known after apply)
}
~ root_block_device {
~ delete_on_termination = false -> true # forces replacement
~ encrypted = false -> (known after apply)
~ iops = 0 -> (known after apply)
+ kms_key_id = (known after apply)
~ volume_id = "vol-01d0d03d564cf44d6" -> (known after apply)
volume_size = 100
volume_type = "standard"
}
}
# aws_network_interface_sg_attachment.sg_attachment must be replaced
-/+ resource "aws_network_interface_sg_attachment" "sg_attachment" {
~ id = "sg-0844f9cd4fb14d5d9_eni-061cb6a5ca9240438" -> (known after apply)
~ network_interface_id = "eni-061cb6a5ca9240438" -> (known after apply) # forces replacement
security_group_id = "sg-0844f9cd4fb14d5d9"
}
# module.alb_admin-mobile-api.aws_alb_target_group_attachment.alb_target_group_attachment must be replaced
-/+ resource "aws_alb_target_group_attachment" "alb_target_group_attachment" {
~ id = "arn:aws:elasticloadbalancing:us-west-2:289914521333:targetgroup/admin-mobile-api-prod-alb-tg/b6940620ef9217f6-20190610084318298800000003" -> (known after apply)
port = 1982
target_group_arn = "arn:aws:elasticloadbalancing:us-west-2:289914521333:targetgroup/admin-mobile-api-prod-alb-tg/b6940620ef9217f6"
~ target_id = "i-0ffa0d29b8fc91930" -> (known after apply) # forces replacement
}
# module.alb_admin-portal-backend.aws_alb_target_group_attachment.alb_target_group_attachment must be replaced
-/+ resource "aws_alb_target_group_attachment" "alb_target_group_attachment" {
~ id = "arn:aws:elasticloadbalancing:us-west-2:289914521333:targetgroup/admin-portal-backend-prod-alb-tg/09e967d1703d0c93-20190610084319310500000004" -> (known after apply)
port = 3001
target_group_arn = "arn:aws:elasticloadbalancing:us-west-2:289914521333:targetgroup/admin-portal-backend-prod-alb-tg/09e967d1703d0c93"
~ target_id = "i-0ffa0d29b8fc91930" -> (known after apply) # forces replacement
}
# module.alb_api.aws_alb_target_group_attachment.alb_target_group_attachment must be replaced
-/+ resource "aws_alb_target_group_attachment" "alb_target_group_attachment" {
~ id = "arn:aws:elasticloadbalancing:us-west-2:289914521333:targetgroup/api-prod-alb-tg/4cb4a656a520c34d-20190610084318237800000001" -> (known after apply)
port = 1984
target_group_arn = "arn:aws:elasticloadbalancing:us-west-2:289914521333:targetgroup/api-prod-alb-tg/4cb4a656a520c34d"
~ target_id = "i-0ffa0d29b8fc91930" -> (known after apply) # forces replacement
}
# module.alb_digitalreign.aws_alb_target_group_attachment.alb_target_group_attachment must be replaced
-/+ resource "aws_alb_target_group_attachment" "alb_target_group_attachment" {
~ id = "arn:aws:elasticloadbalancing:us-west-2:289914521333:targetgroup/digitalreign-prod-alb-tg/c8f0a479686bcaf0-20190610084318291300000002" -> (known after apply)
port = 2040
target_group_arn = "arn:aws:elasticloadbalancing:us-west-2:289914521333:targetgroup/digitalreign-prod-alb-tg/c8f0a479686bcaf0"
~ target_id = "i-0ffa0d29b8fc91930" -> (known after apply) # forces replacement
}
# module.alb_engine-ui.aws_alb_target_group_attachment.alb_target_group_attachment must be replaced
-/+ resource "aws_alb_target_group_attachment" "alb_target_group_attachment" {
~ id = "arn:aws:elasticloadbalancing:us-west-2:289914521333:targetgroup/engine-ui-prod-alb-tg/a2aedefc0c88b5e4-20190701134129654000000001" -> (known after apply)
port = 2016
target_group_arn = "arn:aws:elasticloadbalancing:us-west-2:289914521333:targetgroup/engine-ui-prod-alb-tg/a2aedefc0c88b5e4"
~ target_id = "i-0ffa0d29b8fc91930" -> (known after apply) # forces replacement
}
# module.alb_example-backend.aws_alb_target_group_attachment.alb_target_group_attachment must be replaced
-/+ resource "aws_alb_target_group_attachment" "alb_target_group_attachment" {
~ id = "arn:aws:elasticloadbalancing:us-west-2:289914521333:targetgroup/example-backend-prod-alb-tg/fa7eb3eb4ac1aa95-20190610084319317500000005" -> (known after apply)
port = 2010
target_group_arn = "arn:aws:elasticloadbalancing:us-west-2:289914521333:targetgroup/example-backend-prod-alb-tg/fa7eb3eb4ac1aa95"
~ target_id = "i-0ffa0d29b8fc91930" -> (known after apply) # forces replacement
}
# module.alb_tenant-mobile-api.aws_alb_target_group_attachment.alb_target_group_attachment must be replaced
-/+ resource "aws_alb_target_group_attachment" "alb_target_group_attachment" {
~ id = "arn:aws:elasticloadbalancing:us-west-2:289914521333:targetgroup/tenant-mobile-api-prod-alb-tg/76edfa9edba45f58-20190610084319318900000006" -> (known after apply)
port = 1983
target_group_arn = "arn:aws:elasticloadbalancing:us-west-2:289914521333:targetgroup/tenant-mobile-api-prod-alb-tg/76edfa9edba45f58"
~ target_id = "i-0ffa0d29b8fc91930" -> (known after apply) # forces replacement
}
Plan: 9 to add, 0 to change, 9 to destroy.
------------------------------------------------------------------------
根据计划输出,正在重新创建实例,因为 delete_on_termination
卷已更改。当它附加到恢复实例时,这可能会发生变化。
虽然aws_instance
可能不支持更新选项。但是according to the documentation应该是可以的。
有两种可能的解决方案:
- 如果您不关心在实例终止时删除卷,您可以简单地将
delete_on_termination = false
添加到您的root_block_device
。由于您尚未设置它,因此使用默认值(即true
according to the documentation)。 - 在 Terraform 外部将
DeleteOnTermination
参数更改为true
using the CLI documentation。