Chef Cookbook の管理に librarian を使う

みなさん chef してますか? (挨拶)

今回は chef を使う時の要、cookbook を管理するツールである librarian を紹介します。

Opscode Community のサイトには、有志によってアップロードされた 800 以上の cookbook が公開されており、
また、様々な人が github で自身が作成した cookbook を公開しています。
これまでは、これらの cookbook を使う際には手動でダウンロードして利用していましたが、
librarian を使うことで、ダウンロードの部分を自動的に行なってくれるようになります。
また、cookbook 間の依存関係も考慮してくれるため、必要な cookbook も一緒にダウンロードしてくれます。
Ruby の Bundler や、Python の pip + requirements.txt をイメージするとわかりやすいかもしれません。

なお、類似のツールとして Berkshelf があります。
vagrant との連携機能などいくつか追加の差がありますが、cookbook の管理部分の機能はおおよそ差はないようです。
どちらもほぼ変わらないので、好みの方を使ってください(僕は最初に見つけたという理由で librarian を使っています)。

インストール

gem で入ります。

$ gem install librarian-chef

追記 4/4(15:50): パッケージ名が変わったようなので追従 (librarian → librarian-chef)。

使いはじめる (初期化)

librarian では Cheffile という、利用する cookbook のリストを作ります。
Cheffile のひな形は librarian-chef init コマンドで作ることができます。

$ librarian-chef init
      create  Cheffile
$ ls
Cheffile

作成された Cheffile を開くと次のようになっています。

#!/usr/bin/env ruby
#^syntax detection

site 'http://community.opscode.com/api/v1'

# cookbook 'chef-client'

# cookbook 'apache2', '>= 1.0.0'

# cookbook 'rvm',
#   :git => 'https://github.com/fnichol/chef-rvm'

# cookbook 'postgresql',
#   :git => 'https://github.com/findsyou/cookbooks',
#   :ref => 'postgresql-improvements'

cookbook をダウンロードする

では、Cheffile を書き換えて、cookbook をダウンロードしてみましょう。
試しに timezone を書き足してみます。

site 'http://community.opscode.com/api/v1'
cookbook 'timezone'

この状態で librarian-chef install コマンドを実行します。

$ librarian-chef install
Installing timezone (0.0.1)
$ ls
Cheffile	Cheffile.lock	cookbooks/	tmp/
$ ls cookbooks/
timezone/

install を実行すると、Cheffile の定義にもとづいて必要な cookbook をダウンロードしてきます。
ダウンロードされた cookbook は cookbooks/ ディレクトリの下に保存されます。

install を実行した際に、Cheffile.lock というファイルも一緒に生成されます。
このファイルはインストールされた cookbook のバージョン情報と依存関係を記録しているファイルで、
複数の環境間で同じバージョンの cookbook を使うために利用されます。
bundler の Gemfile、Gemfile.lock の関係と同じですね。
バージョン管理する場合は Cheffile と Cheffile.lock の両方をコミットしておきましょう。

librarian-chef install コマンドでは、Cheffile.lock に記載されているバージョンの cookbook をダウンロードするので、
もしより新しいバージョンの cookbook をダウンロードしたい場合は librarian-chef update コマンドを実行します。

依存関係を持った cookbook のダウンロード

次はもう少し複雑な cookbook をダウンロードしてみます。
試しに jenkins を書き足してみます。

site 'http://community.opscode.com/api/v1'
cookbook 'timezone'
cookbook 'jenkins'

そして、もう一度 librarian-chef install コマンドを実行してみます。
すると、今度は指定した jenkins の他に、依存関係をもった cookbook も一緒にダウンロードされます。

$ librarian-chef install
Installing build-essential (1.3.4)
Installing chef_handler (1.1.4)
Installing windows (1.8.4)
Installing java (1.10.0)
Installing runit (1.1.0)
Installing jenkins (0.6.3)
Installing timezone (0.0.1)
$ ls cookbooks/
build-essential/	java/			runit/			windows/
chef_handler/		jenkins/		timezone/

github からのダウンロード

今度は github からの cookbook をダウンロードしてみましょう。
ここでは opscode community にアップロードされていない、td-agent cookbook を利用してみましょう。
Cheffile に :git オプション付きの定義を追加します。

site 'http://community.opscode.com/api/v1'
cookbook 'timezone'
cookbook 'td-agent',
  :git => 'https://github.com/treasure-data/chef-td-agent'

そして、もう一度 librarian-chef install コマンドを実行してみます。
そうすると、github から td-agent cookbook をダウンロードしてきてくれます。

$ librarian-chef install
Installing apt (1.9.0)
Installing timezone (0.0.1)
Installing yum (2.1.0)
Installing td-agent (0.0.1)
$ ls cookbooks/
apt/		td-agent/	timezone/	yum/

github で公開されていても使い方は変わりませんね。

ローカルにある cookbook を指定する

残るもうひとつの cookbook の取得方法はローカルのファイルを指定するものです。
この場合は :path オプションを付けて指定します。

site 'http://community.opscode.com/api/v1'
cookbook 'timezone'
cookbook 'app',
  :path => 'vendor/cookbooks/app'

それ以降の使い方は他と同じなので説明は割愛します。

まとめ

librarian を用いることで、簡単に cookbook の管理を行うことができます。
チューニングが必要な箇所、特殊なインストールをする箇所以外は community cookbook を利用することで
サーバ構築がもっと簡単に、高速化されるのではないかと思います。
(個人的には、いかに cookbook を書かずに chef を利用するかが重要だと考えています)

できれば、cookbook が公開されていない場合は
自分で作った cookbook を公開して、他の人の苦労を軽減していきたいですね。