[英]How can I chain packer output ami id to terraform variables automatically?
I'm using packer with ansible provisioner to build an ami, and terraform to setup the infrastructure with that ami as a source - somewhat similar to this article: http://www.paulstack.co.uk/blog/2016/01/02/building-an-elasticsearch-cluster-in-aws-with-packer-and-terraform我正在使用加壳器和 ansible 供应商来构建一个 ami,并使用 terraform 来设置以该 ami 作为源的基础设施 - 有点类似于这篇文章: http://www.paulstack.co.uk/blog/2016/01/ 02/building-an-elasticsearch-cluster-in-aws-with-packer-and-terraform
When command packer build pack.json
completes successfully I get the output ami id in this format:当命令
packer build pack.json
成功完成时,我以这种格式获得 output ami id:
eu-central-1: ami-12345678
In my terraform variables variables.tf
I need to specify the source ami id, region etc. The problem here is that I don't want to specify them manually or multiple times.在我的 terraform 变量
variables.tf
中,我需要指定源 ami id、区域等。这里的问题是我不想手动或多次指定它们。 For region (that I know beforehand) it's easy since I can use environment variables in both situations, but what about the output ami?对于区域(我事先知道)这很容易,因为我可以在两种情况下使用环境变量,但是 output ami 呢? Is there a built-in way to chain these products or some not so hacky approach to do it?
是否有一种内置的方法来链接这些产品或一些不那么 hacky 的方法来做到这一点?
EDIT: Hacky approach for anyone who might be interested.编辑:适用于任何可能感兴趣的人的 Hacky 方法。 In this solution I'm
grep
ing the aws region & ami from packer output and use a regular expression in perl to write the result into a terraform.tfvars
file:在这个解决方案中,我
grep
从打包机 output 获取 aws 区域和 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}
You should consider using Terraform's Data Source for aws_ami
. 你应该考虑使用Terraform的数据源来实现
aws_ami
。 With this, you can rely on custom tags that you set on the AMI when it is created (for example a version number or timestamp). 这样,您可以依赖在创建AMI时在AMI上设置的自定义标记(例如版本号或时间戳)。 Then, in the Terraform configuration, you can simply filter the available AMIs for this account and region to get the AMI ID that you need.
然后,在Terraform配置中,您只需过滤此帐户和区域的可用AMI即可获取所需的AMI ID。
https://www.terraform.io/docs/providers/aws/d/ami.html 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"]
}
NOTE: in the example above (from the docs), the combination of filters is probably excessive. 注意:在上面的示例中(来自文档),过滤器的组合可能过多。 You can probably get by just fine with something like:
你可以通过以下方式得到很好的结果:
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}"
}
An additional benefit of this is that you can deploy to multiple regions with the same configuration and no variable map! 这样做的另一个好处是,您可以部署到具有相同配置且没有变量映射的多个区域!
The "official" way that is recommended by Hashicorp is to use their product Atlas as a "middleman" between the two. Hashicorp推荐的“官方”方式是将他们的产品Atlas用作两者之间的“中间人”。 You'd use the Atlas post-processor in Packer to record the artifacts (AMI ids, in your case) and then use the
atlas_artifact
resource in Terraform to read the ids back out again for use in Terraform. 您将在Packer中使用Atlas后处理器来记录工件(在您的情况下为AMI ID),然后使用Terraform中的
atlas_artifact
资源再次读取ID以便在Terraform中使用。
In this case, you would obtain the ids from the resource rather than passing them in using variables. 在这种情况下,您将从资源获取ID,而不是使用变量传递它们。
Aside from Atlas the other options are rather limited, and in some cases hacky. 除了Atlas之外,其他选择相当有限,在某些情况下是hacky。
If you want to do it without any external services at all then you can experiment with the local shell post-processor as a way to run a local command on your artifact, or you can use the machine-readable output to extract the AMI ids and write them into a variables file for Terraform. 如果你想在没有任何外部服务的情况下完成它,那么你可以尝试使用本地shell后处理器作为在工件上运行本地命令的方法,或者你可以使用机器可读输出来提取AMI ID和将它们写入Terraform的变量文件中。
A further option is to write your own post-processor plugin that interacts with some software you already use, as an alternative to Atlas. 另一个选择是编写自己的后处理器插件,与您已经使用的某些软件交互,作为Atlas的替代品。 For example, with some of my colleagues I wrote a post-processor to record artifacts as metadata in Buildkite , which we then subsequently retrieve using the Buildkite API .
例如,我和一些同事编写了一个后处理器,用于将工件记录为Buildkite中的元数据 ,然后我们使用Buildkite API进行检索。 This requires writing custom code in Go.
这需要在Go中编写自定义代码。
At the time of writing Terraform version 0.7 is still under development, but it is planned to include a new feature that allows querying the EC2 API for AMIs directly, which will (if it indeed lands for 0.7) allow a further option of tagging the AMI with Packer and then finding it directly from EC2 using those tags. 在撰写本文时,Terraform 0.7版仍处于开发阶段,但计划包含一项新功能,允许直接查询AMI的EC2 API,如果它确实为0.7,则允许进一步选择标记AMI使用Packer,然后使用这些标签直接从EC2中找到它。 This uses EC2 itself as the "middleman", which is perhaps less awkward since it was involved already as the storage for the AMI anyway.
这使用EC2本身作为“中间人”,这可能不那么尴尬,因为它已经作为AMI的存储而已经涉及。
This is the approach that I used: 这是我使用的方法:
It is similar to the version in the edited answer. 它类似于编辑答案中的版本。 In more detail, it can look like this:
更详细地说,它看起来像这样:
First, create a file called ami.tf.template
: 首先,创建一个名为
ami.tf.template
的文件:
# "ami.tf" was automatically generated from the template "ami.tf.template".
variable "ami" {
default = "${AMI_GENERATED_BY_PACKER}"
description = "The latest AMI."
}
This template will be used to create the ami.tf
file, which makes the AMI from packer available to your existing Terraform setup. 此模板将用于创建
ami.tf
文件,这使得ami.tf
器中的AMI可用于现有的Terraform设置。
Second, create a shell wrapper script for running packer. 其次,创建一个用于运行打包程序的shell包装器脚本。 You can use the following ideas:
您可以使用以下想法:
# run packer (prints to stdout, but stores the output in a variable)
packer_out=$(packer build packer.json | tee /dev/tty)
# packer prints the id of the generated AMI in its last line
ami=$(echo "$packer_out" | tail -c 30 | perl -n -e'/: (ami-.+)$/ && print $1')
# create the 'ami.tf' file from the template:
export AMI_GENERATED_BY_PACKER="$ami" && envsubst < ami.tf.template > ami.tf
Once the script is done, it has created an ami.tf
file, which may look like this: 脚本完成后,它创建了一个
ami.tf
文件,该文件可能如下所示:
# "ami.tf" was automatically generated from the template "ami.tf.template".
variable "ami" {
default = "ami-aa92a441"
description = "The latest AMI."
}
Finally, put that file next to your existing Terraform setup. 最后,将该文件放在现有Terraform设置旁边。 Then you can then access the AMI like this:
然后,您可以像这样访问AMI:
resource "aws_launch_configuration" "foo" {
image_id = "${var.ami}"
...
}
I used the simplest approach, I gave my AMI a name, and looked up for the name in Terraform. image.pkr.hcl
file -我使用了最简单的方法,我给了我的 AMI 一个名字,然后在
image.pkr.hcl
文件中查找这个名字——
packer {
required_plugins {
amazon = {
version = ">= 0.0.2"
source = "github.com/hashicorp/amazon"
}
}
}
source "amazon-ebs" "ubuntu" {
ami_name = "your_ami_name"
instance_type = "t2.micro"
region = "${var.aws_region}"
source_ami_filter {
filters = {
name = "ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"
root-device-type = "ebs"
virtualization-type = "hvm"
}
most_recent = true
owners = "${var.image_owners}"
}
ssh_username = "ubuntu"
}
build {
name = "build-image"
sources = [
"source.amazon-ebs.ubuntu"
]
#.....
}
and ec2.tf
file is - ec2.tf
文件是 -
data "aws_ami" "ami" {
most_recent = true
owners = ["self"]
filter {
name = "name"
values = ["your_ami_name"]
}
}
output "ami_id" {
value = data.aws_ami.ami.id
}
resource "aws_instance" "myEc2" {
ami = data.aws_ami.ami.id
instance_type = "t2.micro"
key_name = "----key"
vpc_security_group_ids = [
"launch-wizard-18"
]
user_data = <<-EOL
#!/bin/bash -xe
echo "if done file exists it went ok"
touch done.txt
EOL
tags = {
Name = "child-of-your-ami"
}
}
Hope this helps希望这可以帮助
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.