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

The null Packer builder is not really a builder, it just sets up an SSH connection and runs the provisioners. It can be used to debug provisioners without incur...

指定したサーバに SSH で入って provisioners を走らせ、成果物としてイメージは作らない builder のようです。今回の目的を達成できそうな雰囲気。本来の使用用途としてはデバッグ目的っぽいですが。

今回は物理サーバにスクリプトを適用し、 Packer イメージから立ち上げた VM と同様の設定が入った状態を作ってみます。

どういう構成にしたか

Packer で使っているファイルが入ったリポジトリに、VM イメージ作成用とは別に、物理サーバに provisioners を適用するための json ファイルを作成しました。builderstype"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 を導入するようなことはしないほうが良いかと思います。

スポンサーリンク
shiftky_blog_336

シェアする

  • このエントリーをはてなブックマークに追加

フォローする