如何自动将打包器输出ami id链接到terraform变量?

fip*_*ips 18 bash packer amazon-web-services terraform

我正在使用带有ansible配置器的打包器来构建一个ami,并使用这个ami作为源来设置基础设施 - 与本文有点类似:http://www.paulstack.co.uk/blog/2016/01/ 02 /建筑物-AN-elasticsearch群集式-AWS与-封隔器和terraform

当命令packer build pack.json成功完成时,我以这种格式获得输出ami id:

eu-central-1: ami-12345678
Run Code Online (Sandbox Code Playgroud)

在我的terraform变量中,variables.tf我需要指定源ami id,region等.这里的问题是我不想手动或多次指定它们.对于区域(我事先知道),因为我可以在两种情况下使用环境变量,所以很容易,但是输出ami呢?是否有内置的方式来链接这些产品或一些不那么hacky方法来做到这一点?

编辑: Hacky方法适用于任何可能感兴趣的人.在这个解决方案中,我是grep来自packer输出的aws region&ami,并在perl中使用正则表达式将结果写入terraform.tfvars文件:

vars=$(pwd)"/terraform.tfvars"
packer build pack.json | \
    tee /dev/tty | \
    grep -E -o '\w{2}-\w+-\w{1}: ami-\w+' | \
    perl -ne '@parts = split /[:,\s]+/, $_; print "aws_amis." . $parts[0] ." = \"" . $parts[1] . "\"\n"' > ${vars}
Run Code Online (Sandbox Code Playgroud)

day*_*r4b 20

您应该考虑使用Terraform的数据源进行aws_ami.这样,您可以依赖在创建AMI时在AMI上设置的自定义标记(例如版本号或时间戳).然后,在Terraform配置中,您只需过滤此帐户和区域的可用AMI即可获取所需的AMI ID.

https://www.terraform.io/docs/providers/aws/d/ami.html

data "aws_ami" "nat_ami" {
  most_recent = true
  executable_users = ["self"]
  filter {
    name = "owner-alias"
    values = ["amazon"]
  }
  filter {
    name = "name"
    values = ["amzn-ami-vpc-nat*"]
  }
  name_regex = "^myami-\\d{3}"
  owners = ["self"]
}
Run Code Online (Sandbox Code Playgroud)

注意:在上面的示例中(来自文档),过滤器的组合可能过多.你可以通过以下方式得到很好的结果:

data "aws_ami" "image" {
  most_recent = true
  owners = ["self"]
  filter {                       
    name = "tag:Application"     
    values = ["my-app-name"]
  }                              
}

output "ami_id" {
  value = "${data.aws_ami.image.id}"
}
Run Code Online (Sandbox Code Playgroud)

这样做的另一个好处是,您可以部署到具有相同配置且没有变量映射的多个区域!

  • 我发现对此工作流程有用的一点是包含 git commit hash 作为标签。这样,如果 terraform 模板可以使用打包程序构建的相对路径引用来获取提交哈希,则可以通过一种方式检索链接到版本控制的 AMI。例如 `export PKR_VAR_commit_hash="$(git rev-parse HEAD)"` (3认同)

Mar*_*ins 7

Hashicorp推荐的"官方"方式是将他们的产品Atlas用作两者之间的"中间人".您可以在Packer中使用Atlas后处理器来记录工件(在您的情况下为AMI ID),然后使用Terraform中atlas_artifact资源再次读取ID以便在Terraform中使用.

在这种情况下,您将从资源获取ID,而不是使用变量传递它们.

除了Atlas之外,其他选择相当有限,在某些情况下是hacky.

如果你想在没有任何外部服务的情况下完成它,那么你可以尝试使用本地shell后处理器作为在工件上运行本地命令的方法,或者你可以使用机器可读输出来提取AMI ID和将它们写入Terraform的变量文件中.

另一个选择是编写自己的后处理器插件,与您已经使用的某些软件交互,作为Atlas的替代品.例如,我和我的一些同事编写了一个后处理器,用于将工件记录为Buildkite中的元数据,然后我们使用Buildkite API进行检索.这需要在Go中编写自定义代码.

在撰写本文时,Terraform 0.7版仍处于开发阶段,但计划包含一项新功能,允许直接查询AMI的EC2 API,如果它确实为0.7,则允许进一步选择标记AMI使用Packer,然后使用这些标签直接从EC2中找到它.这使用EC2本身作为"中间人",这可能不那么尴尬,因为它已经作为AMI的存储而已经涉及.

  • 在我写下这篇评论之后,HashiCorp 的“atlas”服务已于 2017 年停产,所以我在这里写的内容当时有效,但第一段今天不再有效。 (2认同)
  • 请编辑您的回复以反映该更新 - 以帮助其他人节省时间,并防止不必要的否决 (2认同)