昔社内で説明した、分散シェルについてのまとめ。どれも基本的にパスワードなしログインができることが前提。使いドコロが結構違うので、それぞれ使い分けると吉。pdshはクラスタの監視とかgrepでの集計、csshxは緊急のクラスタの設定変更とかレシピ作る前の調査とかに、gxpはクラスタでのタスク分散実行に使うことが多い。
プロダクション構成では、可能な限り直接サーバに入ってこういう作業しなくて済むような環境を構築するのが望ましいけど、クソシステムに分け入って直したり障害対応する仕事は世の中いっぱいあるので、このご時世でも知っていると便利だとは思う。
pdsh
pdshは複数のサーバに同時にssh接続して同時に同じコマンドを実行するための分散シェル。複数台のサーバのログを'tail -f'したり、ディレクトリの中身をまとめて表示したりするときに便利。
apiサーバのログを全台tail -f
して以上が出てないかを確認したり、ログが図れるディレクトリを確認してログ出力が止まっていないか(プロセスは生きてても無応答になったりする奴とかを)確認したり、エラーログを集めてサクッとリカバリしたりするのに便利。
インストール
% sudo yum --enablerepo=epel install pdsh
使い方
-wで複数のホストを,区切りで指定してシェルコマンドを実行。
% pdsh -w host-a,host-b 'ls -lh /var/log/nginx'
出力結果には、行頭にホスト名が付与される。帰ってきた順に表示されるので複数のサーバでの実行結果がまざって表示されてしまう。
そこで、pdshの出力をdshbakというコマンドにpipeすると、ホストごとに表示を整形してくれたり、-cオプションをつけると同じ結果が帰ってきたホストをまとめてくれたりする。
% pdsh -w host-01,host-02 'ls -lh /var/log/nginx'|dshbak
----------------
host-01
----------------
total 14.3M
-rw-r--r-- 1 nginx nginx 3.0M Sep 15 23:36 access.log
...
----------------
host-02
----------------
total 10.4M
-rw-r--r-- 1 nginx nginx 3.0M Sep 15 23:36 access.log
...
ホストを指定するときには正規表現っぽい指定も出来る。zshならquoteが必要
% pdsh -w 'host[01-10]' 'ls -lh /var/log/fluent'
grouping
毎回複数のホストを指定するのは面倒なので、pdsh-mod-dshgroupも一緒に入れておくと、複数のホストをグループで管理できるようになる
% sudo yum --enablerepo=epel install pdsh-mod-dshgroup
グループファイルは、$HOME/.dsh/group/以下に、グループ名をつけたファイルに複数のホストを1行1ホスト指定する。例えばserversというグループにhost[01-20]を登録する。
% less ~/.dsh/group/servers
host-01
host-02
...
host-20
'tail -f hogehoge'などを実行すると、全サーバのログが同時に確認できて便利。
% pdsh -g servers 'tail -f /var/log/nginx/access.log'
pdcp, rpdcp
pdcpを使うと同時にファイルを転送出来る。使い方はscpと同じ。ただし、事前に接続先にもpdshをインストールしておく必要がある
% pdcp -w host-01,host-02 hoge ~/
これで全サーバにファイルが転送される。逆に全サーバからファイルをコピーする場合はrpdcpを利用する。rpdcpコマンドを叩くと、suffixにhost名が付与された形で保存される。
rpdcp -w 'host-[01-02] ~/.bashrc tmp
ls -lha tmp
合計 16K
drwxrwxr-x 2 aihara aihara 4.0K 9月 16 00:27 .
drwxrwxr-x 3 aihara aihara 4.0K 9月 16 00:13 ..
-rw-r--r-- 1 aihara aihara 124 9月 16 00:31 .bashrc.host-01
-rw-r--r-- 1 aihara aihara 124 9月 16 00:31 .bashrc.host-02
csshx
csshxは複数のサーバに同一のキー入力を送信できる物。複数のサーバの設定ファイルを同時に書き換えて再起動するときなどに利用すると便利。マジでテンパってる時とか、プロダクションじゃないクラスタ構成のアプリの初期設定の調査なんかでたまに使う。
インストール
以下のコマンドでhomebrewでインストール出来る。
% brew install csshx
設定
$HOME/.ssh/configに各サーバの接続情報を書いておくと、踏み台サーバ経由でログインする設定を書くと良い。直で入れるようには普通はしないはず。
Host fumidai
Hostname fumidai.dayo.com
IdentityFile ~/.ssh/id_rsa
User username
Host host-01
ProxyCommand ssh fumidai nc %h %p
Host host-02
ProxyCommand ssh fumidai nc %h %p
...
起動
$ csshX host-01 host-02...
実行すると、ターミナルがサーバ数分立ち上がる。下の赤いところにフォーカスしておくと全台に同一の操作が出来る。それぞれのターミナルにフォーカスすると、一台ずつ操作することもできるけどあんまやらない。
gxp
gpxは他の分散シェルと毛色が違っていて、どちらかと言うといろんな処理を複数のサーバにばらまく(タスク並列)のための環境。ブライアンがいた東大の田浦研で開発されている。pdshと同様のことも可能だが、1行1処理のタスクファイルやmakeファイルを指定して様々な処理を接続しているサーバで分散実行することを主眼としている。実行するプログラムとかは予め全サーバに配置されているか、共有ストレージにおいてあることが前提。いろいろ複雑な事出来るっぽいけど、以下の事把握しておけば大体なんとかなる。
結構仕様が古くpopen2使ってるのでduplicate warningが出るけど無視。
高速な共有ストレージ前提なので、EC2上ではそこまで使いどころが無いかも。s3からそれぞれ読むようにするとよいかも。分散タスクばら撒く様の汎用celeryワーカーとかipython clusterのopsworksスタック作ってあったりするとあんまり使わないかも。
セットアップ
makeを使わないならsourceforgeから3.06を入れておくと良いと思う。最新版はsvnで入れる。
% mkdir local
% cd local
% wget 'http://downloads.sourceforge.net/project/gxp/gxp/3.06/gxp-3.06.tar.bz2?r=http%3A%2F%2Fsourceforge.net%2Fprojects%2Fgxp%2Ffiles%2Fgxp%2F&ts=1410796003&use_mirror=jaist' -O gxp.tar.bz2
% tar jxf gxp.tar.bz2
% echo '$PATH=$HOME/local/gxp-3.06:$PATH' >> ~/.bashrc
% source ~/.bashrc
svnで最新版を入れる場合
% mkdir local
% cd local
% cvs -d :pserver:anonymous@gxp.cvs.sourceforge.net:/cvsroot/gxp co gxp3
% echo '$PATH=$HOME/local/gxp3:$PATH' >> ~/.bashrc
% source ~/.bashrc
接続方法
pdshと比べると、ホストの登録が少し面倒。タスクの実行前に自前にコネクションを貼っておく必要がある
% gxpc use ssh fumidai host-01
% gxpc use ssh fumidai host-02
...
% gxpc use ssh fumidai host-[[01-20]]
% gxpc explore host-[[01-20]]
use sshは、踏み台ホスト・実行ホストの順番で指定。exploreで実際に接続。exploreには同時に実行してよいプロセスの数も指定できる。この場合、指定した分だけsshコネクションが張られる。
% gxpc explore host-01 4
単純に全ホストで同時実行するだけなら、以下のように'gxp e コマンド'で実行出来る。
gxpc use
gxp useで接続ホスト一覧が確認できる
gxpc e hostname
ep
gxp epは、1行1コマンドを書いたタスクファイルを指定して、複数のサーバにタスクをばらまいてくれる機能。gnu parallelの分散版っぽい機能。パラメータを変えて実験を同時実行したり、予め分割しておいたファイルをNFSなりにばらまいておくと、並列で処理してくれる。awsの環境であれば、S3上のログファイルを並列でパースしたりするときにとても便利。最新バージョンでは消えていて、若干使いにくくなったjsコマンドというものに置き換わっている。こいつは結構便利なので2010年以前の古いバージョンを利用すると良い。
タスクは以下の形式で指定。
% cat task_file
0 cat hoge00 > /usr/bin/python hogehoge.py | /usr/bin/python > hogehoge0
1 cat hoge01 > /usr/bin/python hogehoge.py | /usr/bin/python > hogehoge1
...
タスク番号は数値だけではなく、ユニークな値であれば問題なし。
実行時は引数にタスクファイルを指定する。-Hで実行させたくないホストを除外することができる。この場合は、fumidaiをヘッドノードとして、serversで並列実行をさせたいので、fumidaiを除外している。
gxpc ep -H fumidai task_file
実行結果はcurrentのstatusディレクトリに保存されている。どのタスクがどのサーバで実行されたかや、実行が正常終了したかどうかが記録されている。
killされたりエラーを吐いて正常終了しなかったタスクの情報も記録されるので、バグ直したりデータを直したりして再度同じepコマンドを実行すると正常終了しなかったタスクだけ再実行される。全部やり直したいときはstatusファイルを削除する必要がある。
js
jsは、epの大体。epと違ってstatusファイルが出力されないので途中からの再実行なんかは手でタスクを書き換える必要あり。
% gxpc js -a work_file=task_file
make
makeはまだ使いこなしていない。makeファイルを書くとタスクの依存関係を読み取って様々な処理を分散実行してくれる。説明はそのうち足す