chef-solo + capistrano で複数ホストを管理する

chef-server は仕組みが大げさでインストールも大変だし、10〜20台ぐらいなら chef-solo と capistrano を組み合わせればいいよね?(同案多数)

実はこれまでもずっと、適当に書き殴った shell script で rsync && chef-solo 実行というのをやっていたのですが、複数json をいい感じにマージして適用したかったので、capistrano で書き直してみました。

fujiwara/chef-solo-with-capistrano · GitHub

方針

  • cookbook などのファイルの同期は rsync
  • 共通で使用する json とホストごとにそれを上書きする json を用意しておき、各ホストにはそれを merge して適用する

前提

  • chef-solo が各ホストにインストール済み
  • capistrano を実行するホストから各ホストに ssh でログインできる

ファイル構成

├── Capfile
├── bin
│     └── merge_json
├── config
│     └── deploy.rb
├── cookbooks
│     └── ( cookbookはここ )
└── json
    ├── base.json
    ├── app01.json  ( hostname -s で表示されるホスト名で命名 )
    └── web01.json

設定

config/deploy.rb でファイルを配置するディレクトリを指定。

    set :chef_dir,    "/root/chef"

json/base.json で定義された hosts に対して実行される。

    {
      "hosts": {
        "web01": "192.168.1.101",
        "app01": "192.168.1.102"
      },
      "nameservers": [ "192.168.1.1", "8.8.8.8" ]
      "run_list": [
        "os-defaults"
      ]
    }
  • run_list は base.json + {hostname}.json の内容が連結される
  • それ以外の key が重複した場合は {hostname}.json の内容が使用される

実行

# cap -T
cap chef:run_chef # run chef-solo
cap chef:sync     # rsync /root/chef
# cap chef
  * executing `chef'
  * executing `chef:init_config'
  * executing `chef:sync'
  * executing `chef:merge_json'
  * executing "export HOST=`hostname -s`; /root/chef/bin/merge_json /root/chef/json/base.json /root/chef/json/${HOST}.json > /root/chef/config/self.json"
    servers: ["app01", "web01"]
  * executing `chef:run_chef'
  * executing "chef-solo -c /root/chef/config/solo.rb -j /root/chef/config/self.json"
...

特定のホストのみ実行したい場合は

# cap -S hosts=web01,web02 chef

のように、引数 -S hosts に "," 区切りの値を指定する。

あまり台数が多くなければ、こんなので十分戦えるんじゃないかなと思う今日この頃です。