💭
Pakcerで異なるsourceのビルドを並列処理する時、buildブロックを複数指定する
環境
- Packer v1.7.9
経緯
- 1つのテンプレート・1つのbuildブロックで複数のsourceを実行したかったのだが、変数を使用しているのでできなかった
- (なぜ)buildを並列処理してビルド時間を短縮したかった
- packer実行時に変数
app
を引数から取得する - provisioningブロックでAnsibleを実行するとき、
app
を渡す-
app
の値がそれぞれのsourceで違うため、同一のbuildブロックを使用できない
-
結果
- buildブロックを1つのテンプレートに複数書くことで並列処理ができた
- 公式ドキュメント(https://learn.hashicorp.com/tutorials/packer/docker-get-started-parallel-builds)を見ても記載がないので無理かと思っていた
- アドバイスをもらって試しにやってみたら可能だった
手順
ディレクトリ構成
$ tree mock
mock
├── packer.sh
├── packer
│ └── foo.pkr.hcl # 1つのテンプレート
└── provisioning
├── doc
├── group_vars
├── fuga.yml
│ └── foo.yml
├── roles
│ // 省略
├── fuga.yml
└── foo.yml
- packer buildするとき
$ pwd
mock
$ sh packer.sh foo dev
- 実行するスクリプト
packer.sh
APP=$1
ENV=$2
# 変数ファイル
(echo app=\"${APP}\"; echo env=\"${ENV}\") > packer/${APP}.pkrvars.hcl
# 変数ファイルを使ってビルド
packer validate -var-file="packer/${app}.pkrvars.hcl" ${app}.pkr.hcl
packer build -var-file="packer/${app}.pkrvars.hcl" packer/${app}.pkr.hcl
実現したかったこと
foo.pkr.hcl
source "amazon-ebs" "foo" {
ami_description = "foo ami"
ami_name = "${var.image_name}-foo"
// 省略
}
source "amazon-ebs" "fuga" {
ami_description = "fuga ami"
ami_name = "${var.image_name}-fuga"
// 省略
}
build {
sources = [
"source.amazon-ebs.foo",
"source.amazon-ebs.fuga" // sourceを複数指定する
]
provisioner "ansible" {
extra_arguments = ["-vv", "--extra-vars", "app=${var.app} env=${var.env}"] // ここで変数`app`の値がそれぞれのsourceで異なるので実行できない
playbook_file = "provisioning/${var.app}.yml" // playbookの中身も違ったりする
user = "ec2-user"
}
post-processor "manifest" {
output = "manifest.json"
strip_path = true
}
}
修正後
foo.prk.hcl
source "amazon-ebs" "foo" {
ami_description = "foo ami"
ami_name = "${var.image_name}-foo"
// 省略
}
source "amazon-ebs" "huga" {
ami_description = "huga ami"
ami_name = "${var.image_name}-fuga"
// 省略
}
build {
sources = [
"source.amazon-ebs.foo"
]
provisioner "ansible" {
extra_arguments = ["-vv", "--extra-vars", "app=${var.app} env=${var.env}"]
playbook_file = "provisioning/${var.app}.yml"
user = "ec2-user"
}
post-processor "manifest" {
output = "manifest.json"
strip_path = true
}
}
build {
sources = [
"source.amazon-ebs.fuga"
]
provisioner "ansible" {
extra_arguments = ["-vv", "--extra-vars", "app=fuga env=${var.env}"] // 変数を使わず直接指定
playbook_file = "provisioning/fuga.yml" // playbook名も直接指定
user = "ec2-user"
}
post-processor "manifest" {
output = "manifest_fuga.json" // manifestファイルは出しわけ
strip_path = true
}
}
- 実行結果
- 実行結果が出力される
- 並行して処理されていることがわかる
- 1つずつ処理していた時と比べ、処理時間短縮できた(およそ1/2ぐらい)
packer.sh
# 省略
amazon-ebs.foo: prevalidationg AMI Name: test-foo
amazon-ebs.fuga: prevalidationg AMI Name: test-fuga
# 省略
Discussion