[英]How can I chain packer output ami id to terraform variables automatically?
我正在使用加殼器和 ansible 供應商來構建一個 ami,並使用 terraform 來設置以該 ami 作為源的基礎設施 - 有點類似於這篇文章: http://www.paulstack.co.uk/blog/2016/01/ 02/building-an-elasticsearch-cluster-in-aws-with-packer-and-terraform
當命令packer build pack.json
成功完成時,我以這種格式獲得 output ami id:
eu-central-1: ami-12345678
在我的 terraform 變量variables.tf
中,我需要指定源 ami id、區域等。這里的問題是我不想手動或多次指定它們。 對於區域(我事先知道)這很容易,因為我可以在兩種情況下使用環境變量,但是 output ami 呢? 是否有一種內置的方法來鏈接這些產品或一些不那么 hacky 的方法來做到這一點?
編輯:適用於任何可能感興趣的人的 Hacky 方法。 在這個解決方案中,我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}
你應該考慮使用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"]
}
注意:在上面的示例中(來自文檔),過濾器的組合可能過多。 你可以通過以下方式得到很好的結果:
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}"
}
這樣做的另一個好處是,您可以部署到具有相同配置且沒有變量映射的多個區域!
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的存儲而已經涉及。
這是我使用的方法:
它類似於編輯答案中的版本。 更詳細地說,它看起來像這樣:
首先,創建一個名為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."
}
此模板將用於創建ami.tf
文件,這使得ami.tf
器中的AMI可用於現有的Terraform設置。
其次,創建一個用於運行打包程序的shell包裝器腳本。 您可以使用以下想法:
# 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
腳本完成后,它創建了一個ami.tf
文件,該文件可能如下所示:
# "ami.tf" was automatically generated from the template "ami.tf.template".
variable "ami" {
default = "ami-aa92a441"
description = "The latest AMI."
}
最后,將該文件放在現有Terraform設置旁邊。 然后,您可以像這樣訪問AMI:
resource "aws_launch_configuration" "foo" {
image_id = "${var.ami}"
...
}
我使用了最簡單的方法,我給了我的 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"
]
#.....
}
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"
}
}
希望這可以幫助
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.