chef-soloを使ってサーバ設定を自動化して楽をしよう! 〜chef-soloの使い方〜

アドウェイズエンジニアの波切です、こんにちは。
秋口に入ってようやく暑さも一段落してきましたね。

ここ最近は、ただひたすらサーバ設定をする日々が続き、バタバタして更新が遅れてしまいました。すみません!

chef-soloを導入するまでの経緯


そのサーバ設定作業なのですが、最初のうちは、手順書を作って、一人ちまちまと作業していたのですが、「パッケージのインストール」「ソースのコンパイルCPANモジュールのインストール」等々、サーバ設定の作業は、結構待たされる事も多く、コマンドを叩いては、しばらく待ってまた、コマンドを打つというような単純な繰り返し作業に苛立ちを感じてしまいました。
短気であること、これもプログラマの性でしょうか?(美徳という意見もありますが)

そんな中、なんとか楽ができないかとWebを調べたところ、すごい人達はRubyの構成管理ツールである「chef」を使って楽をしているというじゃないですか!

ならば僕も挑戦してみようではないか!
と思い立って、chef-soloに入門してみました。

chef-soloのここが分かりづらい!

いきなりネガティブな話ですみません!
しかし、chef-soloを触り始めてすぐわかりました。
「これは、簡単なツールじゃないぞ」と。

実際、この部分がネックになって、chef-soloの導入を諦める方も結構いるのではないかと思うので、まずはchef-soloの分かりづらい部分を把握しておきましょう。

(1)用語/概念
 通常のコンピュータ用語ではなく、クックブック、レシピなど独自の用語を使ってます。
 おそらく、サーバ設定を料理に見立てて命名しているのでしょうね。
 しかし、どの言葉が何を意味するのか、分かりづらかったり、Webで検索する時に非常に困りました。

(2)エラーメッセージ

 chef-soloのスクリプトは、Rubyの内部DSLを使って記述をしていきます。
 このDSLは非常に分かりやすくできています。
 ところがいざ、chef-soloを実行してエラーが発生すると、それはDSLレベルの高レベルなエラーメッセージではなく、chef-soloの実行プログラムの例外スタックトレースが表示されるだけ。
 せっかく、わかりやすい構文を用意して難しい概念を隠蔽しているのですから、エラーメッセージも同じレベルで出てくれたらいいのにと思いました。

(3)汎用性が高いツールなので、どうまとめるのが良いのか迷った。
 chef-soloがどういう仕様かという資料は結構揃っていたのですが、どういうふうに記述していくのがベターなのかという記事が少なかったので、非常に迷いました。

chef-soloは割りきって使う!

僕が上記の点についてどう対応したかというと、用語を別の言葉に置き換えて理解したり、概念を単純化したりして、割りきって使っています。
ですので、内容の正しさや、万人にとってわかりやすいかは保証できないのですが、ざっくりとchef-soloを理解したい人向けに、自分流のchef-soloの使い方を公開したいと思います。

(1)用語・概念

まず用語ですが、手っ取り早く使うには、クックブックレシピノードアトリビュートテンプレートあたりの用語がわかれば、問題ないとおもいます。分かりやすく図にまとめてみました。

Untitled
chef-solo概要図
(クリックすると拡大します)
(2)エラーメッセージ

対処方法としては、
こまめにトライアンドエラーを繰り返えして慣れる」
「最初から、人が作ったクックブックを使わない。」等があります。

逆に、何か良い、デバッグの方法がありましたら、教えていただけるとありがたいです。

(3)レシピの書き方や運用方法等をどうまとめるのが良いのか?

ベスト・プラクティス集のようなものがないかネットで探したのですが、あいにく見つからなかったので、試行錯誤しながら、次のような考え方でchef-soloを使ってます。

・ネットに上がっているopscodeのcookbooksはパラメータが多すぎて、分かりづらいので使わない。
・汎用性の高いレシピを作るのは、時間と労力がかかるので過度に追求し過ぎない
・設定ファイル等は、検証された設定ファイルをテンプレートにベタ張りして作る。(後々、再利用時にリファクタリングすれば良い)
・最初から、設定を全部自動化しようとしない。8割、9割自動化できれば良いと考える。
・構築で時間のかかる処理を優先的にレシピ化する。


「汎用性」、「完全自動化」、「ソースの綺麗さ」等を追求しすぎると、chef-soloを使う本来の目的である、繰り返し作業から解放され、時間の節約を行うこと」から外れていってしまうので、最初はシンプルにまとめ、必要が生じたらリファクタリングを行えばいいのではないかと考えています。

chef-soloの設定スクリプトの編集フロー

chef-soloの実行に登場するマシンとして、「chef-soloのレシピを編集するマシン」(PC)と「設定対象のサーバ」があります。

僕は、PCと設定対象のサーバを頻繁に行き来したくないので、基本的に、PCからrsyncして、設定対象のサーバでchef-soloを動かすまでの手順をスクリプト化しています。

その上で、次のようなフローでchef-soloを使っています。

(1) PCでレシピを編集
(2) 設定対象のサーバにレシピを転送して、実行(コマンド一発)
(3) (1),(2)をバグがなくなり、構築確認が取れるまで実行
(4) 使ったレシピをgitに保存

図にすると、以下のような感じになります。

chef-solo
chef-soloの編集フロー
(クリックすると拡大します)


実際にchef-soloを動かしてみる!

基本的な説明が終わったところで、chef-soloの導入方法から簡単なレシピを実行するところまで見ていきたいと思います!

(1)インストール

まず、PCにchef-soloのツールを入れます。
予め、chef-soloのインストールに必要なruby環境は、導入しておいてくださいね。
 
なお、chefは、chefの基本パッケージで、knife-soloは、chefをchef-soloで運用していく時に便利なコマンドを収録したパッケージです。

(2)レシピを入れておくディレクトリを作る

次に、レシピを入れておくディレクトリを作ります。

コンフィグファイルがないというエラーが出ますが、設定ファイルを使うようなコマンドは使わないので無視します。(気になる方は、knife.rbという設定ファイルを設置してください。)

また、レシピを入れておくディレクトリの命名は、自由なのですが、opscodeのサイトで「chef-repo」が使われていたので、それに倣いました。

ディレクトリの構成については、次のように使っています。

chef-repo/
├── cookbooks -> 拾ってきたクックブックを改変せずに使う(ライブラリ的なクックブック)場合にここに置く。
├── data_bags -> 僕は使っていない
├── nodes     -> 個別のノードごとの設定ファイル(node.json)を入れておく。
├── roles     -> 僕は使っていない。MainCookbookで代用。
├── site-cookbooks -> 自作のCookbookあるいは、拾ってきたCookbookに手を入れて使う場合はここに置いている。
└── solo.rb   -> chef-soloの環境設定ファイル

(3)rsyncしてchef-soloを実行するスクリプトを作ろう!

chef-soloは、設定する対象のサーバ(対象サーバ)で実行するツールですが、対象サーバにchef-soloをインストールして、レシピを転送して、chef-soloを実行していては捗りません。特に、レシピの変更、chef-soloの実行は繰り返し行うことになるので、1コマンドにしておかないと、これ自体が苦痛な作業になってしまいかねません。

そこで、僕は、対象サーバにchef-soloをインストールし、レシピを転送して、chef-soloを実行するまでをまとめてやってくれるスクリプトを準備しています。こんなかんじです。

[chef-repo/run_chef]

このスクリプトが動く前提としては、
・対象ユーザがsshで鍵方式でログインできる
・対象ユーザがパス無しでsudo chef-soloできる
ことを想定しています。

上記の作業を行うためには、まだchef-soloが使えない段階なので、手動で設定を行うか、別途「expect」等のツールを使うといいのではないかと思います。あるいは、OSのインストールから自動化している場合は、初期設定で仕込んでおくといいのかもしれませんね。

(4)クックブックを作る。

最初は簡単なクックブックを作ってみましょう。


これでクックブックのディレクトリができました。
最初説明したように、クックブックというのは単なるレシピをまとめたネームスペースなので、次はそれぞれのクックブックにレシピを追加して行きましょう。

(5)レシピを編集する。

まずは、レッスンとして、lessonクックブックの中に
adduser.rbというユーザを追加するレシピを追加してみましょう。

[chef-repo/site-cookbooks/lesson/recipes/adduser.rb]


(6)ノードファイルを編集する

次に、(4)で作ったレシピをテストするために、(4)のレシピを含むノードファイルを作成します。
[chef-repo/nodes/mynode.js]


今回は、ただ単にlesson::adduserというレシピを実行するだけなので、上記のような簡単な内容になります。

(7)chef-soloを実行する

(8)構築の確認をする

最後にchef-soloによって対象サーバにユーザが想定どおりに作られたかどうか確認します。


どうでしょうか?ユーザは出来ましたか?
もし、できていないようだったらば、再度(5)から(8)までを行う流れになります。

(9)リポジトリにコミット
ここまでの作業の確認が取れたら、レシピをリポジトリにコミットです。

まとめ


いかがだったでしょうか?
若干ハマるところはあるかもしれませんが、Chef-Soloの導入部分はこれでいけるのではないかと思います。

ここまで出来れば、あとはリファレンスを見ながら、いろいろなレシピを作りこんでいけるはずです。

[opscode chef Resources]
http://wiki.opscode.com/display/chef/Resources

また、今回作ったソースをgithubにあげておきますので、興味のある方は見てみてください。
もし、次回書く機会(需要)があれば、chef-soloを使ってnginxをインストールするところまでの流れをご紹介できたらと思います。

[今回のソース]
https://github.com/fugafigs/chef-repo-example