我们使用Terraform来管理我们的基础设施已经有一段时间了,我目前正在重构其中的一部分。 我们希望在 AWS 中有两个自动扩展组,其中一个组运行最新版本的 AMI,另一个组使用以前的版本。 因此,我正在尝试查找两个 AMI。
首先,我们查找最新版本。 这就是我们当前基础设施的工作方式,并且很好:
data "aws_ami" "ami_latest" {
most_recent = true
filter {
name = "name"
values = ["server-name-*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
owners = ["self"]
}
我现在想去找我们以前的版本。 我以为我能够利用 Terraform 中的name_regex
选项,并对我刚刚在第一个块中返回的名称进行负面展望,从而返回之前的最新版本:
data "aws_ami" "ami_previous" {
most_recent = true
filter {
name = "name"
values = ["server-name-*"]
}
#our AMIs have . in them, so I'm escaping for the regex:
name_regex ="^(?!${replace(data.aws_ami.ami_latest.name, ".", "\.")}).+"
filter {
name = "virtualization-type"
values = ["hvm"]
}
owners = ["self"]
}
但是,这会导致崩溃:
panic: regexp: 编译('^(?!服务器名称-1234.1234.1234.1234).+'):解析正则表达式时出错:无效或不受支持的 Perl 语法:"(?!`
我们目前使用的是 Terraform 0.11.10。 虽然我们计划升级到 0.12+,但脚本中有许多地方需要更新,以修复两者之间的各种重大更改。
有没有办法过滤掉 AMI 以获得我在 0.11.10 中想要的东西? 有没有办法让内置的name
过滤器来做到这一点?
或者,0.12.6 是否有更新的正则表达式支持? - 我不愿意解决所有问题以尝试 0.12.6 只是为了发现它仍然存在相同的问题。
另一种方法是使用过滤器本身 - 似乎如果我直接在 AWS 控制台中过滤 AMI 列表,我可以使用名称上的两个过滤器来获取我需要的东西:server-name-*
和!'server-name.123.123.123.123'
,其中第二个是最新版本。 这给了我我需要的信息。 但是,我无法让它在 Terraform 的过滤器块中工作。 我已经尝试了以下各种组合:
filter {
name = "name"
values = ["server-name-*", "!'${data.aws_ami.ami_latest.name}'"]
}
并尝试其他事情,例如使用两个过滤器块,将否定的过滤器放在第一位等。 它们都不会导致找到 AMI——似乎虽然否定的过滤器在控制台上工作,但它们不通过 API 工作,所以这也是一个死胡同。
我找到了一种可能适用于我们特定用例的解决方法,至少是暂时的。
我们的版本号采用server-name-a.b.c.d
的形式,其中c
表示实际版本号。 通过从最新版本中找到该特定数字,减去一个数字,然后按此过滤,我可以找到以前的版本:
name_regex ="^server-name-\d+\.\d+\.${element(split(".", data.aws_ami.ami_latest.name), 2) - 1}\.\d+$"
它感觉不是特别健壮(例如,如果我们跳过一个版本就会失败),所以我仍然对其他解决方案持开放态度,但这暂时解除了我的阻碍......
我意识到这已经快一年了。
我用来解决此问题的模式是向 AMI 添加标签,并按标签进行筛选。这避免了依赖版本号,尽管它们可用于进一步扩展此概念。
标签,例如:
- 产品
- 元件
- 版本
- 环境
哪里:
产品:小部件1
组件:后端
版本: 1.2.3
环境:生产蓝色或生产绿色
祝你好运!