如何阻止Terraform每次运行时刷新从IPAM获取的CIDR数据
解决方案:固定IPAM分配的CIDR避免重复获取
问题核心在于aws_vpc_ipam_preview_next_cidr是数据源,每次执行terraform plan/apply都会重新查询IPAM获取新的可用CIDR,而非持久化已分配的网段。正确的做法是使用aws_vpc_ipam_pool_cidr_allocation资源来完成CIDR的持久化分配,再基于该资源的属性构建后续VPC配置。
修正步骤与代码
1. 替换数据源为分配资源
直接使用aws_vpc_ipam_pool_cidr_allocation分配CIDR,该资源会被Terraform状态跟踪,仅在第一次创建时分配新CIDR,后续执行不会变更:
resource "aws_vpc_ipam_pool_cidr_allocation" "vpc_cidr_allocation" { ipam_pool_id = data.aws_vpc_ipam_pool.ipv4_ipam_pool.id netmask_length = var.vpc_mask_length["standard"] description = "dev-vpc cidr allocation" }
2. 持久化CIDR到SSM并防止覆盖
将分配好的CIDR存入SSM Parameter,同时通过lifecycle.ignore_changes避免后续执行时被意外覆盖:
resource "aws_ssm_parameter" "vpc_cidr" { name = "/test/custom-fields/vpc_cidr" type = "String" value = aws_vpc_ipam_pool_cidr_allocation.vpc_cidr_allocation.cidr lifecycle { # 一旦创建完成,忽略value字段的变更,防止被重新分配的CIDR覆盖 ignore_changes = [value] } }
3. 基于已分配的CIDR计算子网
使用分配资源的CIDR计算子网,确保子网配置始终与已分配的VPC网段一致:
locals { partition = cidrsubnets(aws_vpc_ipam_pool_cidr_allocation.vpc_cidr_allocation.cidr, 1, 1) private_subnets = cidrsubnets(local.partition[0], 2, 2, 2) }
4. 配置VPC模块
直接使用分配资源的CIDR传递给VPC模块,避免依赖数据源的动态值:
module "vpc" { source = "terraform-aws-modules/vpc/aws" version = "3.19.0" name = "dev-vpc" cidr = aws_vpc_ipam_pool_cidr_allocation.vpc_cidr_allocation.cidr azs = formatlist("${data.aws_region.current.name}%s", ["a", "b", "c"]) private_subnets = local.private_subnets }
完整修正代码
# 假设你已有的IPAM池数据源 data "aws_vpc_ipam_pool" "ipv4_ipam_pool" { # 你的IPAM池配置 } data "aws_region" "current" {} # 1. 从IPAM分配持久化的CIDR resource "aws_vpc_ipam_pool_cidr_allocation" "vpc_cidr_allocation" { ipam_pool_id = data.aws_vpc_ipam_pool.ipv4_ipam_pool.id netmask_length = var.vpc_mask_length["standard"] description = "dev-vpc cidr allocation" } # 2. 将分配的CIDR存入SSM并锁定 resource "aws_ssm_parameter" "vpc_cidr" { name = "/test/custom-fields/vpc_cidr" type = "String" value = aws_vpc_ipam_pool_cidr_allocation.vpc_cidr_allocation.cidr lifecycle { ignore_changes = [value] } } # 3. 计算子网网段 locals { partition = cidrsubnets(aws_vpc_ipam_pool_cidr_allocation.vpc_cidr_allocation.cidr, 1, 1) private_subnets = cidrsubnets(local.partition[0], 2, 2, 2) } # 4. 创建VPC module "vpc" { source = "terraform-aws-modules/vpc/aws" version = "3.19.0" name = "dev-vpc" cidr = aws_vpc_ipam_pool_cidr_allocation.vpc_cidr_allocation.cidr azs = formatlist("${data.aws_region.current.name}%s", ["a", "b", "c"]) private_subnets = local.private_subnets }
关键说明
aws_vpc_ipam_pool_cidr_allocation是资源类型,Terraform会将其分配的CIDR纳入状态管理,仅在资源被销毁重建时才会分配新的CIDR。- 移除了
aws_vpc_ipam_preview_next_cidr数据源,避免每次执行都获取新的预览CIDR。 - SSM Parameter的
lifecycle.ignore_changes确保一旦CIDR存入参数存储,后续执行不会因为任何变更覆盖该值(除非手动修改资源配置)。
内容的提问来源于stack exchange,提问作者ANURAG parchuri
相关产品推荐
相关产品推荐

