Chefを利用する機会があり、体系的に知りたいと持って、Chef実践入門を読んだ。 自分用に、そのメモを残しておく。

概要

  • 管理サーバを介するかどうかによって、2種類の動作形態がある。1つ目は、管理サーバとしてChef Serverを介するサーバクライアントモデル。ローカル端末と、管理対象ノードの他に、Chef Serverを必要とする。ローカル端末・Chef Server間、Chef Server・ノード(Chef Client)間でやり取りする。ノード数の増加に強い。2つ目は、Chef Soloを使ったスタンドアロンモデル。Chef ServerもChef Clientも不要。小規模な環境で使われることが多い。いずれもRubyで実装されているので、gem install chef knife-solo berkshelfのように、gemによってインストールできる。
  • リポジトリ(キッチン)、クックブック、レシピという階層構造を持つ。リポジトリは、Gitなどでバージョン管理をする。site-cookbooksに自作のクックブック、cookbooksに外部クックブック、data_bagsにリポジトリ全体でグローバルなスコープのデータ、environmentsにdev/prodなどの環境情報、nodesにノードごとの設定情報(nodeオブジェクト)を配置する。また、Berksfileに依存する外部クックブック一覧を記述する。

クックブックの実装

  • 同一構成の複数ノードを管理する場合には、ノードをまとめたroleを定義する。<repository>/roles/<role name>.jsonを作り、run_listなどを書いていく。また、Attributesを上書きすることもできる。default_attributesは定義されていないものを定義し、override_attributesは強制的に上書きするもの。
  • Attributeというkey-valueを管理する仕組みがある。自分で設定したり、システムから自動抽出することができる。自動抽出する場合には、ohaiコマンドの結果が使われる。慣習的に、ohaiで取得したの値のキーに関してはnode[:platform]のようにシンボルを利用し、Nodeオブジェクトで定義したキーに関しては、node["httpd"]["port"]のように文字列を利用する。Attributeは、<cookbook name>/attributes/defaults.rbにデフォルト値を定義できる。Attributeの優先順は、Nodeオブジェクト>ロール>Environment>レシピのAttribute>クックブックのAttribute。
  • cookbook_fileリソースは<cookbook name>/files以下のファイルを転送し、fileリソースはファイルを新規作成するために使われる。
  • ifconfigmountgem_packagegithttp_requestrouteruby_blockリソースなどがある。もし、これらのリソースを使っても管理できないものがあれば、scriptリソースを使う。ただ、not_ifonly_ifなどをうまく使って、冪等性を自分で保証する必要がある。
  • 設定ファイルの配置後に、notifies :reload, "service[httpd]"のようにして、サービスのリロードできる。あるいは、subscribes :reload "template[/etc/httpd.conf]"によって、逆方向で定義できる。どちらも動作は同じで、キューに詰め込まれてまとめて実行される。
  • if文でインデントが深くなり可読性が下がってしまう場合には、only_ifなどの条件付きアクションを使うと良い。
  • レシピに書かれたリソースはコンパイル後に収束のタイミングで実行されるが、その他のRubyコードはコンパイル時に実行される。収束のタイミングで実行されるRubyコードを書きたければ、ruby_blockリソースを使う。
  • 一連のリソースや処理は、Definitionとして、マクロのように実装できる。

Chef Solo

  • Cookbookを開発するサーバと、管理対象ノードが同一の場合には、knife cookbook create <cookbook name>によりクックブックを作成し、chef-solo -o <cookbook name>によりクックブックを実行する。こういう使い方はあまりしないのかな。
  • 開発サーバと管理対象ノードが異なる場合には、開発サーバでknife-soloを使う。knife-soloコマンドは、手元のクックブックをノードへ転送し、chef-soloを実行する。まず、開発サーバで、knife solo init .により、リポジトリを準備する。次に、knife solo prepare <hostname>により、管理対象ノードにche-soloをインストールする。続いて、knife cookbook create <cookbook name> -o <repository>/site-cookbooksで、クックブックを作成する。その後、クックブックを編集して、<repository>/nodes/<hostname>.jsonの中で{'run_list': ["recipe[<cookbook name>:<recipe name>]"]}と記述する。<recipe name>を省略すると、default.rbが参照される。最後に、knife solo cook <hostname>で、ノードをプロビジョニングする。なお、knife solo prepare <hostname>knife solo cook <hostname>をまとめたknife solo bootstrap <hostname>コマンドもある。また、chef-soloにのみ依存するものはknife soloを使い、それ以外のものはknifeを使う。

その他

  • Test Kitchenを使って、クックブックを統合テストできる。Vagrantなどで、複数のOSを立ち上げる。テストの実行は、クックブックの適用後に、surverspecによって行われる。実際にテストを適用せずに、振る舞いをテストしたければ、ChefSpecを利用する。
  • knife cookbook site search <cookbook name>で外部のクックブックを検索して、Berksfilecookbook '<cookbook>'追加する。その後、berksコマンドで、cookbooksディレクトリにダウンロード、展開される。
  • Opscode、Basecamp、RiotGames、aws、engineyard、pivotal-sproutなどがコミュニティクックブックを公開している。
  • Chef Serverは、新規clientの登録時に双方のvalidation.pemをチェックして、認証する。その後、クライアントに秘密鍵を発行する。
  • knife statusで最後にChef Clientが実行された時間を確認できる。
  • Chefの持つ冪等性と、緊急時のロールバックは相性が悪い。そのため、Chefによるアプリケーションのデプロイは理想的ではない。
  • クックブックの適用忘れを防ぐためには、Chef Soloを定期実行するか、Server/Client構成にして自動適用する。
  • knifeコマンドやohaiコマンドのプラグインは、指定のディレクトリにRubyコードを配置することで、簡単に実装できる。