私はパッカーとアンシブルプロビジョナーを使用してAMIを構築し、テラフォームを使用してそのAMIをソースとしてインフラストラクチャをセットアップしています-この記事に多少似ています: http://www.paulstack.co.uk/blog/ 2016/01/02/building-an-elasticsearch-cluster-in-aws-with-packer-and-terraform
コマンドpacker build pack.json
が正常に完了すると、次の形式で出力AMIIDを取得します。
eu-central-1: AMI-12345678
テラフォーム変数variables.tf
で、ソースAMI ID、リージョンなどを指定する必要があります。ここでの問題は、手動または複数回指定したくないことです。リージョン(事前に知っている)の場合、両方の状況で環境変数を使用できるので簡単ですが、出力amiはどうですか?これらの製品をチェーンする組み込みの方法はありますか、それともそれほどハックではないアプローチがありますか?
編集:興味があるかもしれない人のためのハッキーなアプローチ。このソリューションでは、パッカー出力からawsリージョンとAMIをgrep
し、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}
aws_AMI
にはTerraformのデータソースの使用を検討する必要があります。これにより、AMIの作成時に設定したカスタムタグ(バージョン番号やタイムスタンプなど)を利用できます。次に、Terraform構成で、このアカウントとリージョンで使用可能なAMIをフィルタリングするだけで、必要なAMIIDを取得できます。
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を2つの間の「仲介者」として使用することです。 PackerのAtlasポストプロセッサ を使用してアーティファクト(この場合はAMI ID)を記録してから、 atlas_artifact
Terraformのリソース Terraformで使用するためにIDを再度読み取ります。
この場合、変数を使用してIDを渡すのではなく、リソースからIDを取得します。
アトラスを除いて、他のオプションはかなり制限されており、場合によってはハッキーです。
外部サービスなしでそれを実行したい場合は、アーティファクトでローカルコマンドを実行する方法として ローカルシェルポストプロセッサ を試すか、 機械可読出力 AMI IDを抽出し、Terraformの変数ファイルに書き込みます。
さらなるオプションは、Atlasの代わりに、すでに使用しているソフトウェアと相互作用する独自のポストプロセッサプラグインを作成することです。たとえば、同僚の何人かと一緒に アーティファクトをメタデータとしてBuildkiteに記録するポストプロセッサ を作成し、その後 Buildkite API を使用して取得しました。これには、Goでカスタムコードを作成する必要があります。
執筆時点では、Terraformバージョン0.7はまだ開発中ですが、AMIのEC2 APIに直接クエリを実行できる新機能を含める予定です。これにより、AMIにタグを付けるオプションがさらに追加されます(実際に0.7に到達した場合)。 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を既存のTerraformセットアップで使用できるようになります。
次に、packerを実行するためのシェルラッパースクリプトを作成します。次のアイデアを使用できます。
# 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}"
...
}