chef-soloで作業環境構築の自動化

さくらのVPSを契約して放置しておいたままだったので、これを機に環境構築をしてみることにした。
なお現状はユーザーakahigeの追加とsshの設定だけ済ませた状態になっている。

  • すべての設定はChef経由で行うこと

というルールでChefで同じ環境をいくらでも作れるものを目指してみよう。
Chefサーバーのセットアップはめんどくさいのでchef-soloでがんばる所存。

Rubyのインストール

とはいえChefの動く環境はChef以外で作らないといけない。
このあたりを省略するならシェルスクリプトによる自動化か、Chefが動くところまでセットアップした仮想マシンのイメージを使うほかなさそうだ。

必要なパッケージのインストール
$ wget http://download.fedora.redhat.com/pub/epel/5/i386/epel-release-5-4.noarch.rpm
$ sudo rpm -ivh epel-release-5-4.noarch.rpm
$ wget http://packages.sw.be/rpmforge-release/rpmforge-release-0.5.1-1.el5.rf.x86_64.rpm
$ sudo rpm -ivh rpmforge-release-0.5.1-1.el5.rf.x86_64.rpm
$ sudo yum install -y git
$ sudo yum install -y gcc-c++ patch readline readline-devel zlib zlib-devel libyaml-devel libffi-devel openssl-devel git
$ sudo yum update

Rubyに必要なパッケージとついでにGitとかも入れちゃう。GitはChefリポジトリのひな形を持ってくるのに必要なので。

Ruby 1.9.2のインストール
$ wget ftp://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.2-p0.tar.bz2
$ tar xjf ruby-1.9.2-p0.tar.bz2
$ cd ruby-1.9.2-p0
$ ./configure
$ make
$ sudo make install

ごく普通にインストール。

Chefのインストール

$ sudo gem install chef --no-rdoc --no-ri

chef-soloでがんばるのでサーバーは入れないでおk。

chef-repoの準備とchef-solo用の設定

Chefリポジトリのひな形をGitHubからいただいて来て設定ファイルを作る。

$ git clone git://github.com/opscode/chef-repo.git
$ cd chef-repo
$ mkdir .chef
.chef/solo.rb
file_cache_path "/tmp/chef-solo"
cookbook_path "/home/akahige/chef-repo/cookbooks"

これが設定ファイル。
chef-soloを実行したときに参照するクックブックの場所などを指定する。

.chef/chef.json
{
  "run_list": [ "recipe[base_packages]" ]
}

JSONで適用するレシピを定義する。
とりあえずbase_packagesというレシピを適用することにしてみる。

chef-soloを実行してみる
$ sudo chef-solo -c .chef/solo.rb -j .chef/chef.json

この時点ではレシピを書いてないのでもちろんエラーが出るのみ。

レシピを書く

クックブックを作る
$ rake new_cookbook COOKBOOK=base_packages

deprecatedだからknifeを使いなさい、と警告が出るけどその通りにknifeを使ってもエラーになってうまく動かないので無視。
ともあれこれでいろいろとディレクトリやファイルを含んだクックブックができる。

cookbooks/base_packages/recipes/default.rb

レシピはクックブックのディレクトリ以下のrecipes/default.rbに書いていく。

%w{zsh screen nmap}.each do |package_name|
  package package_name do
    action :install
  end
end

とりあえず思いついたところでzshとscreenとnmapなどを入れてみることとする。
ループの部分とかRubyで書けるのが予想以上に気持ちいい。

再びchef-soloを実行してみる
$ sudo chef-solo -c .chef/solo.rb -j .chef/chef.json

めでたく動作してzshとscreenとnmapが入った。

zsh

しかしzshだけ入っても使い慣れた環境は再現されない。
.zshrcを設置したい。

レシピがちょっと複雑になるのでzshをインストールを別のクックブックとして独立させる。

$ rake new_cookbook COOKBOOK=zsh
cookbooks/zsh/recipes/default.rb
package "zsh" do
  action :install
end

rcfile = '/home/akahige/.zshrc'
template rcfile do
  source "zshrc.erb"
end

file rcfile do
  owner "akahige"
  group "akahige"
  mode "0644"
end

テンプレートファイルをコピーしてパーミッションなどを指定。
環境ごとのカスタマイズは必要ないのでfileリソースだけでいけるのかと思ったが、templateリソースじゃないとsourceが指定できなかった。(※後で気がついたがこういう用途のためにcookbook_fileというリソースがあった)

パッケージのインストール部分がbase_packagesのrecipes/default.rbと重複するがそのままでも問題ない。

ユーザー名がべた書きなのがちょっと気になるけど、自分専用レシピということでとりあえず気にしないことにする。

cookbooks/zsh/templates/default/zshrc.erb

テンプレートファイルとして設置したい.zshrcの内容そのままのzshrc.erbを置く。
内容は割愛。

クックブック内に置けるのはまとまりがよくていい。

.chef/chef.json
{
  "run_list": [ "recipe[base_packages]", "recipe[zsh]" ]
}

新しく作ったレシピを適用するためrun_listに含める。

三度chef-soloを実行してみる
$ sudo chef-solo -c .chef/solo.rb -j .chef/chef.json

.zshrcが見事設置された。やっほい。

screen

次は.screenrc。zshのクックブックの時と同じ手順。

$ rake new_cookbook COOKBOOK=screen
cookbooks/screen/recipes/default.rb
package "screen" do
  action :install
end

rcfile = '/home/akahige/.screenrc'
template rcfile do
  source "screenrc.erb"
end

file rcfile do
  owner "akahige"
  group "akahige"
  mode "0644"
end

zshと同じ。
なんかDRYにできないだろうかと思うがひとまずこのままで。

cookbooks/screen/templates/default/screenrc.erb

設置したい.screenrcの内容そのままのscreenrc.erbを置く。
内容は割愛。

.chef/chef.json
{
  "run_list": [ "recipe[base_packages]", "recipe[zsh]", "recipe[screen]" ]
}

screenのレシピも追加。

またまたchef-soloを実行してみる
$ sudo chef-solo -c .chef/solo.rb -j .chef/chef.json

あかひげ はscreenが使えるようになった!

Git

一段落したところで変更をコミットしておこうとGitを使ったらgitのuser.nameとuser.emailを登録してないので怒られた。
これもChefで設定してみよう。

cookbooks/base_packages/recipes/default.rb
%w{git nmap}.each do |package_name|
  package package_name do
    action :install
  end
end

`git config --global user.name "akahige"`
`git config --global user.email "akahigeg@gmail.com"`

超やっつけでこめんなさい。
まじめにやるなら~/.gitconfigをrcファイルと同じように置く方向か。

ついでにインストールするパッケージのリストからzshとscreenを消してgitを加えた。

最後のchef-soloを実行してみる
$ sudo chef-solo -c .chef/solo.rb -j .chef/chef.json

gitで怒られなくなりました。

ひとまず終わり

$ git commit -a

ということで保存完了。
これでCentOSの環境だったらどこへ行ってもすぐにzshとscreenなどよく使うツールの環境を整えられるようになった。

後で引き続きsshとかvimの設定なんかも追加してみよう。

chef-soloの感想

これはもうPuppetに戻れないかも。
Rubyでレシピを書けるということが想像していたよりずっとよかった。

それと実行を繰り返しながらちょっとずつ環境を構築していくのがTDDのノリに近くて楽しい。
この感覚はなぜかPuppetにはなかったな。なんでだろう。
TDDと言えばrake test_cookbooksというタスクもあるけどこれはなんなのかな。

しかしこれCapistranoと組み合わせたらchef-soloだけでもけっこういけるんじゃないかしら、とか思った。
chef.jsonの代わりにweb.jsonとかdb.jsonとか作って指定したらロールの代わりになるし。

そういう事を思ってしまうくらいChefサーバー立てるのがめんどくさいです。

2010/09/30追記

Chefサーバーを利用する場合、このエントリで扱っているような個々のユーザーの設定にはData Bagsという仕組みを使うことができる。
シェルの設定や各種ファイルの設置などができ、しかもknifeで検索も可能とか。

Chefの機能をフルに使うならChefサーバーは必須ということのようだ。

2011/05/23追記

chef-soloとCapistranoの組み合わせを実際やってみたらChefサーバーなしでもかなりいけるような気がしてきた。

 

One Response to chef-soloで作業環境構築の自動化

  1. Pingback: cocoa*life - Installing Chef Server with RVM