Chef を学んで使ってみた

空前の DevOps ブームに乗り遅れてはいけないとChefを学び、お客様の次期サーバーやRuby on Rails教育で使うサーバーを構築してみました。

http://docs.opscode.com/_static/opscode_chef_html_logo.png

感想

今回、お客様の次期サーバーを作るにあたりChefを使ってみたたところ、一度recipesを作ってしまえば サーバー環境が 10 〜30分くらいで自動的に出来てしまうのは画期的だと感じました!

私は教育・開発者なので、新しいサーバーの構築は年に数回、管理しているサーバーは数台程度です。従来はサーバーの構築・管理は手動で行い、作業内容をメモファイルに残していました。また、再度使う可能性があるサーバー環境はEC2のイメージとして保存して来たりしました。
しかし、作業のメモは必ずしも完璧ではないですし、メモを見落としてインストールに失敗する事もままありました。また保存してあるイメージですが、RubyRailsがバージョンアップし教育では使えなくなってしまう事もあります。

手動でサーバー環境を構築しようとすると半日仕事になってしまいますが、Chefがあれば 10 〜30分くらい。しかも勝手にやってくれます。今までは、環境構築がおっくうで一つのサーバーに色々なアプリをrbenvとかを駆使して動かしていましたが、コスト面で問題がなければクラウドVPSでサーバーを立ち上げ、すぐに環境が作れてしまいます。
また、recipe はコードなので少し考えて作っておけば再利用が可能で、新たな環境用に Chef も比較的短時間で作れます。

私のように、頻繁にサーバーを構築する事のない開発者も学んだ方が良い技術だと思います。

学び方

入門

入門は、やはり naoyaさんの 入門Chef Solo を読みましょう。原理的な事から実践的な事までがコンパクトにまとっまている良い書籍だと思います。私は kindle版が出た時に買ってしまったのでMacの横にiPadを置きKindleアプリで見ながら作業をしましたが、今なら 達人出版会からPDF(EPUB)版を買えば PC, Mac で見ながら作業出来るので、こちらがお勧めです。

http://tatsu-zine.com/images/books/78/cover_s.jpg

実際に作ってみる

実際にrecipe作る際には、

Recipe作りの基本

Resources

詳細は、入門書やリファレンスを読むとして、実際に Ruby on Railsアプリを動かすサーバーを構築するにはよく使う 以下のResources (Ruby DSL) を recipe に並べるだけです。

  • package: OSのパッケージ(apt, yum) 等のインストール
  • gem_package: RubyGemsのインストール
  • cookbook_file: 設定ファイル等の作成、用意した設定ファイルのコピー+α
  • template: 設定ファイル等の作成、設定ファイルをテンプレート化(Ruby のERB)出来るの汎用性がある
  • remote_file: ネット上からファイルをダウンロードする
  • file, directory: ファイル、ディレクトリーの作成
  • user, group: Unixのユーザー、グループの作成
  • service: デーモン(サーバープロセス)の起動、停止・・・
  • execute: OSコマンドを実行することで上記の Resources では出来ないような操作を行う

べき等性 (冪等性, idempotence)

Chefのrecipeでは既にrecipeと同じ状態になっている場合は、何も行わないという べき等性を保つようにrecipeを作る必要性がります。
これは、Chef がインストールツールではなく、サーバー等の環境の変更を管理する為のツールだからです。packageをはじめ殆どのResourceは、既にインストールされている場合は何もおきません。
ただし、execute などは自分でべき等になるように作る必要があります、その為の仕組みが幾つかあります。

  • creates属性: executeを実行した場合に出来るファイルを書いておくと、そのファイルがある場合は execute が実行されません
  • only_if, not_if属性: 書かれたRubyの式、またはshellコマンドの文字列を実行した結果で実行する・しないを制御出来ます

Notifies

設定ファイルが作成・変更された時だけサーバーをリスタートする事が良くあります、このような場合は以下のサンプルのように設定ファイルを作るresource内に notifies を書くことで、設定ファイルが作成・変更された時にサーバーのリスタートを実行できます。
ちなみに、service "mysql" do 〜 のactionがnothingになっているので、最初に service "mysql" do 〜 が実行される際には何も起きません。

service "mysql" do
  supports :status => true, :restart => true, :reload => true
  action :nothing
end

cookbook_file "/etc/mysql/conf.d/character_set_utf8.cnf" do
  source "character_set_utf8.cnf"
  owner 'root'
  group 'root'
  mode  0644
  notifies :restart, 'service[mysql]', :immediately
end

Ruby

recipe は Rubyのコードなので、当然 Rubyの式、変数、メソッド(関数)が使えます、何度も出てくるパス名や処理は変数やメソッドを使うとメンテナンス性の高い recipe になります。 ただし、resource内で呼び出すメソッドは libraries ディレクトリーに置きます。

repository > cookbook > recipe

複数のrecipe が集まり cookbook になり、複数の cookbook が集まりrepository になります。 したがって、一つ recipe ファイルはある程度の粒度(作業単位)で書き、cookbook, chef を分ける事が再利用性の高い recipe 作りに役立つと思います。

Chef Cookbooks

http://community.opscode.com に既に作られたrecipe (Cookbooks) がたくさんあります。naoyaさんの本にもChef初心者はCookbooks を使わずに自分で recipe を作った方が良いと書かれていますが、私もその通りだと思います。
一般的にCookbooksにあるものは汎用的で高機能ですが、自分専用の環境を作ったりする際には resouces や LWRP を使い recipe を作った方が勉強になるだけでなく、後々のバージョンアップ等でトラブルが起きにくいと思います。

私の勉強のために iptablesの設定に simple_iptables を使ってみましたが、自分でシンプルなrecipeを書いた場合に比べ良いのかは疑問です ;-)
ちなみに、Cookbooksは http://community.opscode.com/cookbooks ここで検索すると、評価(rating)やダウンロード数が判るので、どれを使うかの参考になると思います。

Vagrant

recipe の作成、確認はローカル(Mac)上のVM(仮想マシン、私の場合はVMWare fusionを持っていたのでこれを利用)で行います。recipeは べき等に出来ているので、OSだけがインストールされた新しいVMから再実行する必要な状況が良くおきます。その際には Vagrant を使うと、コマンド一つで新しいVMが直ぐに作れとても便利です。