如何在Terraform的aws_instance资源的data.aws_ami部分传递拼接变量
问题根源
HCL 语法不支持通过变量动态拼接资源/数据源的引用路径,Terraform 在执行规划阶段需要静态解析所有资源的依赖关系,你尝试的字符串插值拼接引用名的写法无法被识别,因此会抛出「点后需要属性名」的语法错误。
解决方案1:最小改动适配现有代码
你可以通过 lookup 函数配合映射表,根据变量值匹配对应数据源的ID,直接修改 aws_instance 资源的 ami 参数即可:
resource "aws_instance" "linux" { key_name = var.ami_key_pair_name ami = lookup({ amazon = data.aws_ami.amazon.id ubuntu = data.aws_ami.ubuntu.id # 后续新增其他系统的data源后,在这里加对应映射即可 }, var.ami_name, data.aws_ami.ubuntu.id) # 第三个参数为默认值,避免传入非法ami_name时报错 instance_type = "t2.micro" tags = { Name = var.instance_name } vpc_security_group_ids = [ aws_security_group.allow-ssh-http.id ] }
解决方案2:更易扩展的通用写法
不用定义多个 aws_ami 数据源,直接通过变量映射不同系统的筛选规则,后续新增操作系统只需要加映射条目即可,不需要新增data块:
- 先定义不同系统的AMI配置映射
variable "ami_name" { default = "ubuntu" # 可选项限定为你支持的操作系统,避免传入非法值 type = string validation { condition = contains(["amazon", "ubuntu", "rhel", "suse"], var.ami_name) error_message = "仅支持的AMI名称为:amazon、ubuntu、rhel、suse。" } } locals { # 不同操作系统对应的AMI筛选参数,后续新增系统直接加条目即可 ami_config_map = { amazon = { owner = "amazon" name_filter = ["amzn2-ami-hvm*"] } ubuntu = { owner = "099720109477" name_filter = ["ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-server-*"] } } current_ami_config = local.ami_config_map[var.ami_name] }
- 仅保留一个通用的
aws_ami数据源
data "aws_ami" "selected" { most_recent = true owners = [local.current_ami_config.owner] filter { name = "name" values = local.current_ami_config.name_filter } filter { name = "virtualization-type" values = ["hvm"] } }
- 实例资源直接引用通用数据源的ID即可
resource "aws_instance" "linux" { key_name = var.ami_key_pair_name ami = data.aws_ami.selected.id # 其余参数保持不变 }
内容的提问来源于stack exchange,提问作者greenszpila
相关产品推荐
相关产品推荐

