Packer をプロビジョニングツールっぽく使う
業務で使用している OpenStack のプライベートクラウド環境では、 LDAP 設定や共通で使うパッケージ/ユーザが入ったイメージを Packer で作り、新規にサーバを構築する際にそのイメージから VM を立ち上げています。一旦イメージを作ってしまえば、それ以降立ち上げる VM は同じ設定が入った状態になっているので、その後の運用方法を統一できて良いですね。
しかし、管理対象に素の cloud-image から立ち上げた VM や物理サーバが混ざってくるとちょっと厄介です。 Chef や Ansible などの他のプロビジョニングツールを適用する前に、 Packer で行ったのと同じ変更を適用しておきたいケースが出てきました。物理サーバのためだけにレシピを書き足しメンテナンスするのもだるい。
"provisioners"
で使っているシェルスクリプトを、対象のサーバに全部アップロードして直接実行してしまえば良いのですが、手運用が入ってしまうのはちょっとイケてない。
"provisioners": [
{
"type": "shell",
"execute_command": "sudo -S sh '{{.Path}}'",
"override": {
"openstack": {
"scripts": [ ## <- ここで指定しているスクリプト達な
"./scripts/01_base.sh",
"./scripts/02_create_user.sh",
...
Packer でイメージを作る時は builder で VM 立ち上げ → スクリプトを適用 → イメージ化
が順に行われるわけですが、最後のイメージ化だけ行わなければ、 Packer の枠組みを使いつつ既存のサーバも同じ状態に揃えられるんじゃね? と思いました。つまり、Packer をプロビジョニングツール的に動作させ、 "provisioners"
のスクリプトを指定したサーバに適用する道具として使うというイメージです。
前置きが長くなりました。 Packer の Null Builder とやらを使うと、想定した動作が実現できました。
Null Builder
https://www.packer.io/docs/builders/null.html
指定したサーバに SSH で入って provisioners を走らせ、成果物としてイメージは作らない builder のようです。今回の目的を達成できそうな雰囲気。本来の使用用途としてはデバッグ目的っぽいですが。
今回は物理サーバにスクリプトを適用し、 Packer イメージから立ち上げた VM と同様の設定が入った状態を作ってみます。
どういう構成にしたか
Packer で使っているファイルが入ったリポジトリに、VM イメージ作成用とは別に、物理サーバに provisioners を適用するための json ファイルを作成しました。builders
の type
で "null"
を指定します。
{
"variables": {
"ssh_host": "",
"ssh_user": "",
"ssh_key": ""
},
"builders": [
{
"type": "null",
"communicator": "ssh",
"ssh_pty": "true",
"ssh_host": "{{user `ssh_host`}}",
"ssh_username": "{{user `ssh_user`}}",
"ssh_private_key_file": "{{user `ssh_key`}}"
}
],
"provisioners": [
{
"type": "shell",
"execute_command": "sudo -S sh '{{.Path}}'",
"override": {
"null": {
"scripts": [
"./scripts/physical/01_base.sh",
"./scripts/10_create_user.sh",
"./scripts/11_hogehoge.sh",
"./scripts/12_hugahuga.sh"
]
}
}
}
]
}
複数サーバにに繰り返し適用する際に、一々 json を書き換えるのは面倒なので、SSH 接続に必要な情報はユーザ変数として外出しし Packer 実行時にコマンドライン引数で渡すようにしました。ループでホスト名を変えつつ実行することを想定しています。
実行時のコマンドはこんな感じ。
packer build \
-var "ssh_host=prd-web01.example.com" \
-var "ssh_user=ope_user" \
-var "ssh_key=$HOME/.ssh/ope_user.pem" \
physical_server.json
実行すると、指定したサーバに SSH 接続しに行き、 provisioners のスクリプトが順番に実行されていきます。 build 終了後はイメージ作成などは行われず Packer が終了します。
==> null: Provisioning with shell script: ./scripts/12_hugahuga.sh
Build 'null' finished.
==> Builds finished. The artifacts of successful builds are:
--> null: Did not export anything. This is the null builder
これで Packer の枠組みを使いつつ、 build
コマンド実行で既存サーバにもスクリプト適用ができるようになりました。
今回用意したスクリプトは、元々 VM 作成時に 1 度だけ実行されることを想定したシェルスクリプトのため、冪等性は保証されていないものでした。実行されるスクリプトに状態チェックのコードが書かれていなければ、繰り返し packer build
することは出来ないという点に注意しなければなりません。
元々はイメージ作成のためのツールなので、プロビジョニング目的だけに新たに Packer を導入するようなことはしないほうが良いかと思います。
Previous Post
Next Post