knife 関連の自動化ツール一覧

Chef クラサバ構成では knife というコマンドラインツールを用いて Chef サーバの情報を更新するわけだけど、この knife というのがサブサブサブコマンドまであったり (knife cookbook site install とか)、最小限なコマンドをいくつも打つ必要があったりして、もう少しなんとかならないのかなと思うことがよくある。

たとえば「Chef サーバからノード A を削除したい」というシチュエーションで、"knife node delete node_a", "knife client delete node_a" という 2 コマンドを打ち、さらに chef-repo に置いてある nodes/server01.json というファイルをレポジトリ上から削除するとか。

こんなときに複数の処理をバッチにまとめて使い回したいというのが当然の要請だと思うけど、今のところ下記 3 つが有力っぽい。

  • spiceweasel
  • knife プラグイン
  • knife スクリプト

それぞれ長所・短所があるので、概要を書き比較してみる。

spiceweasel

knife のサブコマンド cookbook/environment/role/data bag/bootstrap や、knife ec2/rackspace といった knife によるプロビジョニングを、バッチ処理として JSON/YAML の形式で実行できる。

こんな感じの YAML を書いて、

cookbooks:
- apache2:
- apt:
    - 1.2.0
- mysql:
 
environments:
- development:
- qa:
- production:
 
roles:
- base:
- iisserver:
- monitoring:
- webserver:

(以下省略)

こんなコマンドを実行すると、

spiceweasel path/to/infrastructure.yml

下記の操作を実行してくれる。

knife cookbook upload apache2
knife cookbook upload apt
knife cookbook upload mysql
knife environment from file development.rb
knife environment from file qa.rb
knife environment from file production.rb
knife role from file base.rb
knife role from file iisserver.rb
knife role from file monitoring.rb
knife role from file webserver.rb

簡単に書ける代わりにかなり自由度が低いし、ルールを覚えなければならないのでややだるい感じがする。

knife プラグイン

Opscode が提供している opscode/knife-ec2 とか拙作の tily/ruby-knife-nc みたいなやつ。こんな感じでゴリゴリとプラグインを書く。Chef 本家の knife サブコマンド と同等のコマンドを作っていく感じ。結構めんどくさい。

作ったプラグインはカレントディレクトリまたはホームディレクトリの .chef/plugins/ に置くと自動で認識される。また、knife-ec2 や knife-nc のように gem として配布できるのだけど、これが一番の強みだと思う。

knife スクリプト

個人的には手軽かつ自由度が高くて一番いいかなと思っている仕組み。DSL で柔軟に knife の処理を記述できる。書いた knife スクリプトは下記のような感じで実行できる。

knife exec script.knife

公式ドキュメントに載っている例だけど、Google スプレッドシートに現在のノード一覧を保存してくれるスクリプトとかすごくおもしろい。

require 'google_spreadsheet'
 
session = GoogleSpreadsheet.login ENV["GOOGLE_EMAIL"], ENV["GOOGLE_PASSWORD"]
sheet = session.create_spreadsheet "Instances #{Time.now.strftime "%Y%m%d"}"
 
ws = sheet.worksheets.first
 
ws[1,1] = "Check In"
ws[1,2] = "Node Name"
ws[1,3] = "Ruby Version"
ws[1,4] = "Recipes"
 
i = 2
nodes.all do |n|
  ws[i,1] = Time.at(n['ohai_time']).strftime("%F %R")
  ws[i,2] = n.name
  ws[i,3] = n['languages']['ruby']['version']
  ws[i,4] = n.run_list.expand.recipes.join(", ")
  i = i + 1
end
 
ws.save

まとめ

個人的な評価だけど、表にまとめると以下のような感じになると思う。

手軽さ 自由度 配布
spiceweasel ×
knife プラグイン ×
knife スクリプト

他にも似たようなものがあったら教えてもらえるとうれしいです。