web-dev-qa-db-ja.com

パッカーの出力AMIIDをテラフォーム変数に自動的にチェーンするにはどうすればよいですか?

私はパッカーとアンシブルプロビジョナーを使用して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}
19
fips

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}"
}

これの追加の利点は、同じ構成で変数マップなしで複数のリージョンにデプロイできることです。

20
dayer4b

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のストレージとしてすでに関与しているため、おそらくそれほど厄介ではありません。

7
Martin Atkins

これは私が使用したアプローチです:

  1. パッカー呼び出しをラップし、出力を解析してAMIを取得します
  2. 解析されたAMIを使用して、値を変数として提供するTerraformファイルを作成します

編集した回答のバージョンと似ています。より詳細には、次のようになります。

まず、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}"
  ...
}
0
Philipp Claßen