開発メモ#5 : Amazon Linux で knife-solo を使って chef-solo 実行
開発メモその5です。表題どおり EC2 インスタンスの Amazon Linux で knife-solo を使う話。
開発メモ#4 : EC2スナップショットとの差分は chef-solo で解決 - naoyaのはてなダイアリー で、chef-solo を使って EC2 の環境管理をしていると書きました。うち chef-solo の実行は capistrano like な perl のデプロイツール Cinnamon に任せている、という旨を述べました。
が、件のデプロイツール任せだと chef-solo 実行の度にレポジトリ経由でレシピをサーバー側に転送する必要がある。自分は github を使っているので github に push してサーバー側で fetchc される。デプロイツールがこの辺をやってくれるとは言え、レシピの動作確認のためにちゃんと動くことが保証されていないレシピをレポジトリに push する必要があって良くないなと思うようになりました。
knife-solo
chef に同梱されている chef の管理コマンド knife、そのプラグインに当たる knife-solo を使うと、ローカルで作ったレシピをリモートに sync してリモート側で chef-solo を実行してくれる。これなら github を経由しなくていい。
## 手元の OSX # knife-solo インストール % gem install knife-solo # chefレポジトリを作る % knife solo init chef-repo % cd chef-repo # リモートでの chef-solo 実行環境を整える % knife solo prepare ec2-user@chef-test.ap-northeast-1 # ローカルのレシピを転送しリモートで chef-solo 実行 % knife cook ec2-user@chef-test.ap-northeast-1
なんとこれだけでございます。chef-client や chef-server を使うまでもないけど chef-solo のサーバーサイドでの実行を簡単にしたい!という状況にマッチしてますね。
・・・なのですが、残念ながら knife solo prepare と cook は Amazon Linux ではそのまま動かないのでした。
$ knife solo prepare ec2-user@chef-test.ap-northeast-1 ERROR: RuntimeError: Distro not recognized from looking at /etc/issue. Please fork https://github.com/matschaffer/knife-solo and add support for your distro.
こんな感じのエラーになる。ググラビリティのために載っけておきましょう。
2/4 20:20 追記
knife solo prepare は chef-solo が実行可能かどうかを調べて、もしそうでなければ実行可能になるよう調整する・・・ということをします。要するに、chef-solo が入ってなかったらインストールする。この時インストールされるのは Omnibus Chef Packaging というバージョンの chef で、ruby バイナリそのほか組み込みの独立で動く chef になります。
knife solo cook は Omnibus Chef Packaging で入った chef-solo の PATH なども考慮して chef-solo を実行します。
knife-solo を修正する
というわけで knife-solo を Amazon Linux でも動くようにパッチを当てます。
knife-solo のバージョンは
- 2月4日現在 github のレポジトリはバージョン 0.2.0.pre1
- gem install で入る stable は 0.1.0
となってますが、前者はうまく動かなかったので後者にパッチを当てて使います。git tag で v0.1.0 がついてるのでそれを拝借。
% git clone git@github.com:matschaffer/knife-solo.git % cd knife-solo % git checkout -b amazonlinux v0.1.0
diff は以下。要するに、/etc/issue を見てディストリビューションを判定するにあたり Amazon Linux の /etc/issue は面倒みてなかったのを、見るようにしてやるだけ。
diff --git a/lib/knife-solo/bootstraps/linux.rb b/lib/knife-solo/bootstraps/linux.rb index a171f27..74961ac 100644 --- a/lib/knife-solo/bootstraps/linux.rb +++ b/lib/knife-solo/bootstraps/linux.rb @@ -104,6 +104,8 @@ module KnifeSolo::Bootstraps {:type => "yum_omnibus", :version => "RHEL5"} when %r{Scientific Linux.*? 6} {:type => "yum_omnibus", :version => "RHEL6"} + when %r{Amazon Linux} + {:type => "yum_omnibus", :version => "Amazon"} when %r{SUSE Linux Enterprise Server 1[12]} {:type => "omnibus", :version => "SLES11"} when %r{openSUSE 1[12]}
変更が済んだら、パッチ済みの knife-solo を入れる。
% rake install
これで無事 knife solo prepare が動くようになります。
EC2 で knife solo
knife solo prepare では、chef-solo の実行環境が整っているかどうかを調べてなければ chef-solo そのものをインストールするところまで面倒みてくれます。従って、knife solo prepare すれば EC2 インスタンスを立ち上げた直後から chef-solo が使える。わざわざ ssh ログインして rubygems や chef をインストールしたりする必要がない。
立ち上げてすぐ knife solo prepare & cook することで、環境構築を完全に自動化できるわけですなあ。ライフチェンジングですね。
ちょっとその様子を実践すべく、幾つか EC2 の初期環境構築を自動化してみましょう。
ところまでやってみます。
まずは knife solo init で chef レポジトリを作り、git init する。
% knife solo init chef-repo % cd chef-repo % git init % git add . % git commit -m 'first commit'
% knife cookbook create mkswap -o site-cookbooks
site-cookbooks/mkswap/receipes/default.rb は以下の感じ。
bash 'create swapfile' do not_if { File.exists?('/swap.img') } code <<-EOC dd if=/dev/zero of=/swap.img bs=1M count=2048 && chmod 600 /swap.img mkswap /swap.img EOC end mount '/dev/null' do # swap file entry for fstab action :enable # cannot mount; only add to fstab device '/swap.img' fstype 'swap' end bash 'activate swap' do code 'swapon -ae' end
次は yum の EPEL 有効化。レシピを自分で書いてもいいけど、ここはコミュニティで配布されてるものを使っちゃおう。knife cookbook site vendor yum
で、cookbook 以下にダウンロードされる。なお、site vendor を実行するのには http://community.opscode.com/ への登録が必要。登録してプロフィールページから private key を取得して ~/.chef/naoya.pem とかに保存するべし。(保存すべきパスは ~/.chef/knife.rb に設定されてます。)
% knife cookbook site vendor yum
あとは sysstat と mosh を入れるレシピを作る。今後それ以外にも基本的なパッケージを入れるためのレシピとして拡張することも考え名前は base_packages にしました。
% knife cookbook create base_packages -o site-coookbooks
レシピは以下。簡単。
%w{sysstat mosh}.each do |pkg| package pkg do action :install end end
これでレシピは揃った。EC2 のマイクロインスタンスを立ち上げて完了したら prepare。
% knife solo prepare ec2-user@chef-test.ap-northeast-1
ちなみに過去にも言及した通り、自分は EC2 インスタンスのホスト名管理は ec2ssh を使ってます。もうこれ3回目な!
prepare すると、nodes 以下に chef-test.ap-northeast-1.json という、ホスト名をファイル名にした json ファイルができている。中身を
{ "recipes":[ "mkswap", "yum::epel", "base_packages" ] }
と書き換え。これで準備は完了。いざ、chef-solo 実行。*1
% knife cook ec2-user@chef-test.ap-northeast-1
スワップが作られて EPEL が有効になって、sysstat や mosh が入ったはず。検証してみよう。
% mosh chef-test.ap-northeast-1 $ free total used free shared buffers cached Mem: 608740 404352 204388 0 15192 341780 -/+ buffers/cache: 47380 561360 Swap: 2097148 300 2096848 $ sar 1 1000 Linux 3.2.30-49.59.amzn1.x86_64 (ip-10-152-95-236) 2013年02月04日 _x86_64_ (1 CPU) 09時42分32秒 CPU %user %nice %system %iowait %steal %idle 09時42分33秒 all 0.00 0.00 0.00 1.00 0.00 99.00 09時42分34秒 all 0.00 0.00 0.00 0.00 0.00 100.0
最後にレシピを git commit して完了です。ちなみに同手順は vagrant でも使えるので、vagrant 側で動作確認して問題なかったら EC2 に適用・・・みたいなこともできますね。vagrant についてはまた後日書きます。
てなわけで、Amazon Linux も knife-solo が疎通することがわかったので Cinnamon との連携部分を knife-solo を使うように書き換えてハッピー☆となる予定です。
*1:設定は solo.rb がデフォルトで使われます