问题描述
在使用Terraform创建AWS资源时遇到了问题。他在模板中创建了2个EC2实例,每个实例都附加了一个1GB的EBS卷。然而,当他尝试删除其中一个EC2实例时,两个1GB的EBS卷都被销毁了。他确认这两个卷连接到不同的实例上,因此对此情况感到困惑。
以下是他执行的删除命令:
$ terraform destroy -target=aws_instance.jumpserver[1]
这是他的主要Terraform配置文件(main.tf
):
# 定义位于公共子网中的web服务器
resource "aws_instance" "jumpserver" {
count = "${var.num_of_instances}"
ami = "${var.ami}"
instance_type = "t2.micro"
key_name = "${aws_key_pair.ProdKeypair.id}"
subnet_id = "${aws_subnet.public_subnet.id}"
vpc_security_group_ids = ["${aws_security_group.sg_internet_facing.id}"]
associate_public_ip_address = true
source_dest_check = false
root_block_device = {
volume_type = "gp2"
volume_size = "8"
delete_on_termination = "${var.delete_on_termination}"
}
tags = {
Name = "${format("jump-%01d",count.index+1)}"
}
provisioner "remote-exec" {
inline = ["sudo apt-get -y install python"]
connection {
type = "ssh"
user = "ubuntu"
private_key = "${file(var.private_key_path)}"
}
}
}
# 定义EBS卷
resource "aws_ebs_volume" "vol_generic_data" {
size = "1"
count = "${var.num_of_instances}"
type = "gp2"
availability_zone = "${element(aws_instance.jumpserver.*.availability_zone, count.index)}"
tags = {
Name = "${format("jump-%01d",count.index+1)}"
}
}
# 将EBS卷附加到EC2实例
resource "aws_volume_attachment" "generic_data_vol_att" {
device_name = "/dev/xvdf"
volume_id = "${element(aws_ebs_volume.vol_generic_data.*.id, count.index)}"
instance_id = "${element(aws_instance.jumpserver.*.id, count.index)}"
count = "${var.num_of_instances}"
}
# 定义位于私有子网中的web服务器
resource "aws_instance" "backendserver" {
ami = "${var.ami}"
instance_type = "t2.micro"
key_name = "${aws_key_pair.ProdKeypair.id}"
subnet_id = "${aws_subnet.private_subnet.id}"
vpc_security_group_ids = ["${aws_security_group.sg_backend.id}"]
associate_public_ip_address = false
source_dest_check = false
user_data = "${file("install.sh")}"
tags = {
Name = "backendserver"
}
}
解决方案
请注意以下操作可能因版本差异或个人环境不同而有所不同,请在操作前进行充分的备份和测试。
解决方案1:修复EBS卷的可用区问题
问题的根本在于aws_ebs_volume
资源的availability_zone
属性。该属性取决于aws_instance
资源,因此当Terraform销毁EC2实例时,它会认为EBS卷无法独立存在。即使这是一个独立于EC2实例的变量。
为了修复这个问题,您可以将availability_zone
属性更改为参考您的VPC的可用区,而不是依赖于EC2实例的可用区。您可以使用类似module.vpc-prod.azs[0]
的引用。
下面是您可以进行的更改:
# 定义EBS卷
resource "aws_ebs_volume" "vol_generic_data" {
size = "1"
count = "${var.num_of_instances}"
type = "gp2"
availability_zone = "us-east-1a" # 更改为您的VPC的可用区,或使用引用方式
tags = {
Name = "${format("jump-%01d",count.index+1)}"
}
}
解决方案2:使用Terraform生命周期设置
您还可以通过Terraform的生命周期设置来解决这个问题,确保EBS卷在EC2实例销毁之前被销毁。这可以防止Terraform在销毁EC2实例时自动销毁EBS卷。
下面是一个可能的示例配置:
resource "aws_ebs_volume" "vol_generic_data" {
size = "1"
count = "${var.num_of_instances}"
type = "gp2"
availability_zone = "us-east-1a" # 更改为您的VPC的可用区,或使用引用方式
tags = {
Name = "${format("jump-%01d",count.index+1)}"
}
lifecycle {
prevent_destroy = true # 防止Terraform销毁EBS卷
}
}
通过设置prevent_destroy = true
,您可以阻止Terraform销毁EBS卷,从而确保在EC2实例销毁之前手动处理EBS卷。
总结
在使用Terraform创建AWS资源时,确保您正确设置EBS卷的可用区,以及根据实际需求使用适当的Terraform生命周期设置,以避免意外的资源销毁。
正文完