2008-12-18 [長年日記]
_ Capistrano は思ったよりシンプルで思ったよりすごい
システム管理者のみなさん、こんにちは。今日は Rails アプリの deploy ツールとして有名な(らしい)Capistrano についてです。紹介? いえいえ。紹介はすでに有名な人たちによってなされています。ワタシがしたいのは検討。こいつはどこにどのように使えそうか。
システム管理の話なのになんで Puppet じゃないの?と思うかもしれません。それは、以前 Puppet の OSX 対応があまりよくなかったことと、また自分の環境が PPC Mac だったため、仮想マシンを使って他の OS を動かすのも現実的でなく、面倒になってしまっていたからです。
で、巡り巡って Capistrano って実は deploy 以外にも結構使えそうじゃない?と思えましたよというお話。想定しているバージョンは Capistrano 2.5.3 です。
なお、例によって嘘書いてる可能性があります。識者のツッコミお待ちしております。
Capistrano の動作に必要なのは Ruby と ssh だけ
- Puppet は daemon をいくつか用意してやる必要があります。
- https を使ってくれるので fw friendly ですが、それにしたっていろいろ準備が必要です。
- Capistrano の準備で大事なのは以下の2点だけ。
- Capistrano*1 をセットアップする1台のマシン
- 管理される方のマシンには sshd と作業用の ssh アカウント
しかも Puppet と違い C/S 方式ではないため、Capistrano のセットアップが必要なマシンは1台だけです。
なんか、ちょっとお手軽な感じがしませんか。
Capistrano 自体は Windows でも動く
依存している gem パッケージは以下の通り。
$ gem dependency capistrano Gem capistrano-2.5.3 net-ssh (>= 2.0.0, runtime) net-sftp (>= 2.0.0, runtime) net-scp (>= 1.0.0, runtime) net-ssh-gateway (>= 1.0.0, runtime) highline (>= 0, runtime) echoe (>= 0, runtime)
あと echoe がこんな感じ。*2
$ gem dependency echoe Gem echoe-3.0.2 rake (>= 0, runtime) rubyforge (>= 1.0.0, runtime) highline (>= 0, runtime)
ext なライブラリはないので Capistrano 自体は Windows でも動かせます。*3自分で実際に確認はしてないですけど、動かしている例は探せばすぐ見つかります。
ただ管理対象は ssh でなんでもできる Un*x 系システムじゃないと Capistrano の利用に旨味はないでしょう。
要するにできることは ssh HOST COMMAND
ssh は interactive な login shell を提供するだけではなく、
ssh HOST COMMAND
の形で
HOST に接続して COMMAND に書かれた処理を実行して終了する
という使い方もできます。大雑把に言うと Capistrano はこの機能をより便利に使うために
- 接続先の管理と接続の自動化
- 接続先と作業内容のセットをタスクで管理
- タスクの実行
を提供してくれるものです。そして
そのために Rake を使う
ようになっています。
deploy ツールとして紹介されることの多い Capistrano ですが、それは deploy 用のタスクがあらかじめ定義されていて、変数をセットするだけで便利に使えるようにしてあるからであって、
タスクを用意すれば ssh でできる仕事はなんでもできます。
たぶん。
ただし、Puppet と違い、接続先のサーバ OS の抽象化などは行ってくれないため、基本的にその部分は生で相手しないといけません。逆に Puppet のように独自文法の習得を要求しません。
ということは従来の方法からの移行コストが小さい
まともな管理者なら、サーバ上のたいていの作業は sh や Perl、Ruby などのスクリプトである程度自動化されていると思います。これが cron ジョブとして管理できるなら手作業はずいぶん減っているはずです。ただ、
完全に定期実行になっていない作業
も中にはあるでしょう。その場合、しぶしぶ個々のサーバにログインしてスクリプトを実行していませんか? 恥ずかしながら自分はそうです。しかし Capistrano を導入すれば
最後の「ログイン -> 実行」の部分を自動化、管理できます。
そうです。個々のサーバの管理方法を大幅に変える必要はありません。「ログイン -> 実行」という、最後に残った手作業部分を Capistrano のタスクとして管理できるようになるだけなのです。しかもサーバ側は基本的にいじる必要がありません。
これが複数のサーバ上の作業なら目に見えて楽になりますし、サーバの数がそれほど多くなくても
一定のワークフローを保証しやすくなります。
つまり
管理作業の共有、引き継ぎを楽にしてくれます。
もちろん独自タスクの管理のためには Ruby と Rake への理解を要求するので、楽になる一方ではありません。しかも Rake も Capistrano もそんなにドキュメントが充実しているわけでもありません。しかし、スクリプトを書いて自動化して、手作業によるミスを減らせるようにしてあるはずなのに、なんとなく属人的な作業が残っちゃう部分があって、なんか気持ち悪いなぁと感じているような場合には Capistrano の導入は十分に検討の価値があるんじゃないでしょうか。
超簡単な例
えーと概念の話からインストールの方法をすっ飛ばしていきなり実例に入ります。*4
カレントディレクトリに以下のような内容で Capfile という名前のファイルを作ってください。ここでログイン先のサーバのユーザー名、パスワードは一致しているものとします。
role :server, 'server1, 'server2' set :user, 'user' set :password, 'password' desc "reporting disk usage with 'df -h'" task :check_disk, :roles => :server do run 'df -h' end
で
cap check_disk
と実行すると
* executing `check_disk' * executing "df -h" servers: ["server1", "server2"] [server1] executing command [server2] executing command ** [out :: server1] Filesystem Size Used Avail Use% Mounted on ** [out :: server1] /dev/xvda1 32G 24G 7.2G 77% / ** [out :: server1] tmpfs 201M 0 201M 0% /dev/shm ** [out :: server2] Filesystem Size Used Avail Use% Mounted on ** [out :: server2] /dev/mapper/XXX 17G 14G 2.1G 88% / ** [out :: server2] /dev/xvda1 99M 27M 67M 29% /boot ** [out :: server2] tmpfs 181M 0 181M 0% /dev/shm command finished
みたいな結果が得られます。つまり、server1, server2 にログインして実際に df -h した結果をそのまま、Capistrano をインストールしたマシン上で確認できたということです。
どうです、なかなか面白くないですか。
情報収集が楽になるはず
これはちょっといきすぎてるかな?と思わなくもないのですが、cron ジョブの実行を Capistrano マシンに集中させることも可能ですね。こうすると
- 個々のサーバで crond が不要
- cron ジョブのレポートメールを Capistrano マシン上に集約可能
- cron ジョブの様子を一カ所で確認できるので、スケジュールを考えやすくなる
というメリットがあります。もちろんデメリットや不安材料もあって、
- ssh login のコスト
- 長い時間掛かる仕事をさせたときの ssh connection はどうなる?
なんかが気になるところです。まだ見落としてることもあるかもしれません。
cron のレポートの受け取りが面倒くさい
ただ、cron はレポートのメールの受け取りが面倒だなと以前から感じていたので、この問題を解決しやすくなるとしたらとても嬉しいです。というのも、cron のレポートは基本的にローカルのアカウントにメールされるのですが、
どうやって読むの?
という問題がつきまといます。今思いつくのは
- 個々のサーバにログインして読む
- 個々のサーバに POP サーバ立てる
- forward する
- mail -> html -> feed 変換して feed reader で読む
くらいですかね。数が増えてくれば当然 1, 2 はナシだと思うんですが、
forward する場合、forward 先のサーバには SMTP サーバと SMTP の通る穴が必要
になります。これがまた悩ましい。メールサーバが LAN 内にあるなら LAN 内のレポートは文句なし LAN 内のメールサーバで処理すればいいです。でもインターネット向けに公開しているサーバのメールはどうしましょう? LAN 内のサーバ向けに forward ? fw で閉じてませんか? じゃあインターネット上の SMTP サーバに転送? OBP25 とかに引っかかりませんか? それにインターネット上に置いた SMTP サーバはあっという間に spam やエラーメールの嵐に飲み込まれてしまいます。すると今度は spam filter だ anti virus だ…。ふー。違うんだよ、オレはそんなことしたいんじゃないの。要するに
forward も意外に面倒なのです。
もう一つ、メールったってこんなの返信の必要もないし、みんな feed reader で読みたいなぁと以前から思っていました。実際、mail -> html -> feed 変換をしている人は見かけます。HTML にして URI が付けば内容の共有も楽です。*5しかしどうしても転送の部分がネックになります。各サーバで feed 吐いてそれpla で収集してもいいですけど、なんかそれもどうなんだと。
でも Capistrano からタスクを実行すれば、自動的に、少なくとも stdout や stderr の内容は取得できます。結果をファイルに落とすタイプでもファイルの転送が可能*6なのでそれを取得してくればオッケーです。
てことは、レポートの収集の部分は自動的にクリアしてしまいます。おう、なんかこれ面白そうじゃん。
できそうなことの一覧
クラスの一覧から一部を抜粋。
Capistrano::Configuration Capistrano::Configuration::Actions Capistrano::Configuration::Actions::FileTransfer Capistrano::Configuration::Actions::Inspect Capistrano::Configuration::Actions::Invocation Capistrano::Configuration::Actions::Invocation::ClassMethods Capistrano::Configuration::Callbacks Capistrano::Configuration::Connections Capistrano::Configuration::Execution Capistrano::Configuration::Loading Capistrano::Configuration::Loading::ClassMethods Capistrano::Configuration::Namespaces Capistrano::Configuration::Namespaces::Namespace Capistrano::Configuration::Roles Capistrano::Configuration::Servers Capistrano::Configuration::Variables Capistrano::Deploy Capistrano::Deploy::Dependencies Capistrano::Deploy::LocalDependency Capistrano::Deploy::RemoteDependency Capistrano::Deploy::SCM Capistrano::Deploy::SCM::Accurev Capistrano::Deploy::SCM::Accurev::InternalRevision Capistrano::Deploy::SCM::Base Capistrano::Deploy::SCM::Base::LocalProxy Capistrano::Deploy::SCM::Bzr Capistrano::Deploy::SCM::Cvs Capistrano::Deploy::SCM::Darcs Capistrano::Deploy::SCM::Git Capistrano::Deploy::SCM::Mercurial Capistrano::Deploy::SCM::None Capistrano::Deploy::SCM::Perforce Capistrano::Deploy::SCM::Subversion Capistrano::Deploy::Strategy Capistrano::Deploy::Strategy::Base Capistrano::Deploy::Strategy::Checkout Capistrano::Deploy::Strategy::Copy Capistrano::Deploy::Strategy::Export Capistrano::Deploy::Strategy::Remote Capistrano::Deploy::Strategy::RemoteCache
いやーこうして見ると Deploy の充実っぷりがやはりすごいですね。Mercurial や Bzr なんて文字も見えるので、これらを使った deploy もできるんでしょう。
使えそうなリソース
Capistrano 自体が github でホスティングされているためか、github で検索するといちばんたくさん引っかかるようです。
- Capistrano 入門 - Ruby on Rails with OIAX
- まとまって日本語で読めるのってこれくらい?
あとはシステム管理系のレシピが載ってそうなところとか。まだあんまちゃんと見てないですけど。
- deprec - Trac
- sauliusgrigaitis's centostrano at master ― GitHub
- → ‘capitate’: Capistrano recipes, plugins and templates.
- vigetlabs's capistrano_rsync_with_remote_cache at master ― GitHub
- capistrano-mailer - Google Code
- Capistrano 2.1向けのAPTレシピ : \ay diary
- Andrew Beacock's Blog: A Capistrano recipe for restarting Apache 2 (on Linux)
- CapistranoでタスクをDRY化したいときは Capistrano.plugin が便利 - 半隠遁日記
最後に。
みんな、実際に試してオラにやり方を教えてくれ!
*1 当然、Ruby も必要
*2 これ recursive に取れないのかな? もしかして使ってる gem が古い?
*3 公開鍵認証を利用するための鍵作成には Putty などの ssh クライアントがたぶん必要です。
*4 実際、rubygems さえ動いていればインストールはそれくらい簡単です。
*5 例えば管理用のメールを複数人で受信していて、何か気になるアラートがあったとします。この情報を共有したいわけですが、メールを一意に特定するのは Message-ID です。しかし Message-ID の確認や検索の容易なメーラーは寡聞にして知りません。
*6 やり方はまだ分かってません!
大変分かりやすいです。参考にさせていただきます。