如何通过Terraform为AWS EC2实例保留固定公网IP
问题与解决方案:保留EC2实例原有公网IP的Terraform配置调整
问题描述
我使用Terraform配置创建了4个EC2实例并为其分配静态公网IP,配置代码如下:
resource "aws_instance" "kit-prod-api" { subnet_id = element(module.vpc.public_subnets, count.index) ami = data.aws_ami.kit_prod_api_ami.id instance_type = "c5.large" associate_public_ip_address = true vpc_security_group_ids = [module.vpc.default_security_group_id, aws_security_group.prod_ssh_security_group.id, aws_security_group.prod_lb_instances_security_group.id] count = 4 lifecycle { create_before_destroy = "true" ignore_changes = [ ami, instance_type, ] } # there are tags and provisioner blocks here too }
当我需要更新实例以使用新AMI时,会逐个终止实例并执行terraform apply来替换它们。此操作虽能成功,但实例会获取新的公网IP。我发现旧IP会出现在AWS控制台的EIP区域,但之前并未显示。请问是否可以修改该脚本/工作流,使新实例关联原有公网IP?
解决方案
要保留原有公网IP,核心是把自动分配的临时公网IP转为**弹性公网IP(EIP)**并独立管理,再绑定到新实例上。具体步骤如下:
1. 分离EIP资源,独立创建并绑定到实例
修改Terraform配置,新增aws_eip资源,为每个实例分配固定EIP,并通过实例ID绑定:
# 为每个EC2实例创建独立的弹性公网IP resource "aws_eip" "kit-prod-api" { count = 4 vpc = true # 绑定到对应的EC2实例 instance = aws_instance.kit-prod-api[count.index].id subnet = element(module.vpc.public_subnets, count.index) # 保留EIP,避免实例销毁时自动释放 lifecycle { prevent_destroy = true } } resource "aws_instance" "kit-prod-api" { subnet_id = element(module.vpc.public_subnets, count.index) ami = data.aws_ami.kit_prod_api_ami.id instance_type = "c5.large" # 关闭自动分配公网IP,改用手动绑定EIP associate_public_ip_address = false vpc_security_group_ids = [module.vpc.default_security_group_id, aws_security_group.prod_ssh_security_group.id, aws_security_group.prod_lb_instances_security_group.id] count = 4 lifecycle { create_before_destroy = true ignore_changes = [ ami, instance_type, ] } # 保留原有的tags和provisioner配置 }
2. 执行配置迁移,保留现有IP
- 先执行
terraform import将现有实例的公网IP导入为aws_eip资源:
对于每个实例(0到3索引),运行:terraform import aws_eip.kit-prod-api[0] <实例对应的公网IP> terraform import aws_eip.kit-prod-api[1] <实例对应的公网IP> terraform import aws_eip.kit-prod-api[2] <实例对应的公网IP> terraform import aws_eip.kit-prod-api[3] <实例对应的公网IP> - 然后执行
terraform apply,此时Terraform会将现有临时IP转为EIP并绑定,不会改变现有IP。
3. 更新AMI时的工作流调整
后续更新AMI时,直接执行terraform apply即可:
- 由于开启了
create_before_destroy,Terraform会先创建新实例(无自动公网IP) - 然后将对应的EIP从旧实例解绑,绑定到新实例
- 最后销毁旧实例,EIP会保留并继续绑定在新实例上,实现IP不变
关键说明
- 关闭
associate_public_ip_address:避免新实例自动分配临时IP,确保仅使用我们管理的EIP prevent_destroy:防止Terraform在销毁实例时误删EIP,确保IP资源持久保留- 导入现有IP:将之前自动分配的临时IP转为EIP,无需重新分配新IP
内容的提问来源于stack exchange,提问作者mckeed
相关产品推荐
相关产品推荐

