HPCシステムズではエンジニアを募集しています。詳しくはこちらをご覧ください。
HPCシステムズのエンジニア達による技術ブログ

Tech Blog

PDSH使ってますか?

PDSHとは

もともとIBMのクラスター管理ユーティリティ群だったClusterITの中にあったdsh(Distributed shell)のパラレル版です。dshは同じ処理を多数のマシンで行いたい場合に使うものですが、クラスターシステムの大規模化やスピードアップのために、並列動作に対応させたのがPDSHです。

RHEL/CentOSではEPELリポジトリからインストール可能ですし、ビルド自体も難しくはありません。PDSHソースコード配布元はこちら

ここでは計算ノードがnode001からnode128まで128台あるとし、ログインしている管理ノードからは、全てのマシンにパスワードなしでsshでコマンド実行できるようになっていることとします。

では、全てのノードの時刻を表示させてみましょう。

# pdsh -w 'node[001-128]' date
node007: 2019年 5月 20日 月曜日 10:30:23 JST
node002: 2019年 5月 20日 月曜日 10:30:23 JST
・・・・・・・

32台ずつsshを実行して各ノードの時刻が表示できます。表示はレスポンスの先着順なので順番はそのたびバラバラですが、その分処理は速くなります。シャットダウンするのであれば

# pdsh -f 128 -w 'node[001-128]' 'shutdown -h now'

で、一斉に実行できます。-fオプションは同時実行数でデフォルトが32です。1を指定すれば、順番通りに実行されます。ノードが落ちていたり処理に時間がかかっているノードがあった場合、Ctrl-Cを入力すると、処理が終了していない(始まっていない)ノードがcommand in progessというメッセージと共に列挙されます。連続で2回入力すると諦めて処理を落とします。

グループ指定

予めホスト名をグループ化しておいて、定型処理しやすくしてみましょう。指定の方法にはdsh由来のグループ指定と、netgroupを使う方法、machinesファイルを使う方法などです。dsh由来の方法では、システム標準のグループ指定の他に、各ユーザーがホームディレクトリ内でグループ指定を持つことが出来ます。一方でnetgroupを使うと、設定をNISで共有することが可能になります。

グループ対応はモジュールで実現されており、rpmでインストールする場合、別パッケージになっています。入っていない場合はpdsh-mod-dshgroupやpdsh-mod-netgroupを追加インストールしてください。ubuntuのリポジトリにはpdshはありますが、モジュールは用意されてないようなので、自前でビルドする必要がありそうです。現在利用可能なモジュールはpdsh -Lで確認できます。

今回は設定が楽なdshgroupの使い方を紹介します。システム共有設定は/etc/dsh/group/、ユーザー別の設定は~/.dsh/group/に任意のグループ名でホスト名を列挙したファイルを置くだけです。

上記構成では例えば、group1, group2, group3, group4と4つのファイルを作り、それぞれにnode001-node032, node033-node064, node064-node096, node097-node128が各行に含まれるように書きます。グループを入れ子にはできませんのでご注意ください。入れ子にする必要がある場合はnetgroupであれば可能です。

実際に指定する場合は、上記例の-wではなく、-gオプションでグループ指定であることを明示します。複数並べる場合は’,’で区切るか、-gを複数使用します。

# pdsh -g group1,group3 cat /etc/redhat-releas

予め落ちているノードが分かっている場合など、特定のマシンを省きたい場合があります。その場合は-xで指定できます。

# pdsh -g group1 -x 'node[008-011]' cat /etc/redhat-release

表示方法の工夫

上記の例のように同じような結果が大量に出てくる場合、同じものだけをまとめ、違うものだけをあぶり出してみましょう。同梱されているdshbakを使います。

# pdsh -g group1,group3 cat /etc/redhat-release | dshbak -c
----------------
node[001-009,012-032,049-058,061-064]
----------------
CentOS Linux release 7.6.1810 (Core) 
----------------
node[010-011,059-060]
----------------
CentOS Linux release 7.5.1804 (Core)

dshbakはpdshの出力結果を整形するツールで、パイプでデータを流し込むのが一般的な使い方です。-cは重複する結果をまとめて出力するようになります。この例ではnode010, node011, node059, node060の4台だけアップデートできていないことが分かりました。

次に、出力が多いコマンド、ここではジャーナルログの出力をホスト名毎にファイルにして保存してみます。dshbakの-dオプションで保存するディレクトリを指定します。-fを使うとディレクトリが無い場合は作成します。

# pdsh -g group1 journalctl -xe | dshbak -f -d log
# ls -l log/
-rw-r--r-- 1 root root 98765  5月 20 11:01 node01
-rw-r--r-- 1 root root 99887  5月 20 11:01 node02
・・・・・

展開される名前を利用する

pdsh -Lでrcmd/execモジュールがあることを確認してください。無ければpdsh-rcmd-execパッケージを検索しインストールします。

pdsh -R execとしてこのモジュールを使うと、sshでコマンドを投げることをしません。代わりにユーザー名を%u、ホスト名を%hで展開してコマンドを実行できます。例えば計算ノードのホスト名に.ipmiを追加すると、各ノードのIPMI(BMC)へアクセスできるようなシステムの場合、以下のようにしてシステムイベントログを取得できたり、電源コントロールができます。(ID/Passwordは適宜)

# pdsh -R exec -g group1 ipmitool -H %h.ipmi -U admin -P XXXXX sel list
# pdsh -R exec -g group1 ipmitool -H %h.ipmi -U admin -P XXXXX power on

この例では、sshでリモート実行するのではなく、32個のコマンドをホスト名を変えて作成し、手元のマシンで並行実行します。つまり以下のようにすると本稿の最初の例と同じことをしていることになります。

# pdsh -R exec -w 'node[001-128]' ssh %h date

変わっった使い方として、500ノードのクラスターの/etc/hostsファイルを作ってみましょう。pdshは-wオプションで作成したホスト名はそのホストの有無によらずコマンドを生成します。

# pdsh -N -f 1 -R exec -w 'node[001-500]' echo 192.168.10.%n %h.local %h >> hosts
# head hosts
192.168.10.1 node001.local node001
192.168.10.2 node002.local node002
・・・・・

-Nは出力の先頭にホスト名を表示しないことを指定し、%nは生成順を表す番号でMPIのようにRankと呼ばれます。

プロンプト利用

単純にpdsh -w ‘node[001-064]’とだけ実行するとプロンプトが出ます。インタラクティブにコマンドを実行できます。

# pdsh -w 'node[001-004]'
pdsh> date
node003: 2019年 5月 20日 月曜日 13:44:43 JST
node001: 2019年 5月 20日 月曜日 13:44:43 JST
node002: 2019年 5月 20日 月曜日 13:44:43 JST
node004: 2019年 5月 20日 月曜日 13:44:43 JST

さすがにエディタを立ち上げてファイル編集などはできませんが、これもまた便利な使い方です。

まとめ

いかがでしょうか、管理するマシンが多い場合でも同じことを一斉にできるpdshはかなり有用なユーティリティだと思います。いろいろお試しください。

次はpdshの同梱ツールであるpdcpを使って、ファイルのやり取りを便利にしてみましょう。