現代のHPCシステムでは、何千人ものユーザーからの大量のジョブを管理する能力を持っています。スケジュールされたジョブを正常に実行し、消費された計算リソースに関する情報を適切に収集するためには、SlurmやPBSなどのジョブスケジューラーは、1つのジョブに関連するすべての計算ノードが、同じグループID、ユーザーID、パスワード、ホームディレクトリパスであってほしいと期待しています。つまり、HPCクラスターのすべての管理ノードと計算ノードの間で、既存ユーザーとグループを集中的に同期させる機能を提供する必要があります。
以前の記事で、Dockerで動作するSlurmでサポートされたシンプルなHPCクラスタを展開する方法に関する簡単なガイドを提供しました。ここでは、ユーザーとグループの管理システムを統合することで、その内容を拡張したいと思います。しかし、ソースコードや設定ファイルを修正する前に、Linuxオペレーティングシステム上で動作するHPCクラスタにおけるユーザとグループの管理の基本的なアーキテクチャについて説明したいと思います。アーキテクチャに関する知識を得た上で、ユーザー/グループの管理方法について解説します。
複数ユーザーに複数ノードへのアクセスを提供する方法
Linuxノードにおけるユーザーとグループ管理は、一見簡単そうに見えます。以下のファイルがユーザーとグループ管理に関連しています。
- etc/passwd/:ユーザー名、UID、GID、ホームディレクトリ、デフォルトシェル、GECOS(ユーザーの一般的な説明)を含む一般的なユーザー情報
- etc/shadow:ユーザーのパスワードをハッシュ化したもの
- /etc/group:グループ名、GID、GECOS を含む一般的なグループ情報 (グループの一般的な説明)
Slurmで管理されているシンプルなHPCクラスタがあり、そこでジョブを実行する必要があるとします。デフォルトでインストールされているLinuxでは、UIDとGIDが0のrootユーザーが存在するため、rootユーザーとしてジョブを実行すると、すべてが正常に実行されます。異なるジョブを異なるユーザーで実行したい場合は、各ノードにこれらのユーザーを作成し、各ユーザーのすべてのパラメータが、そのユーザーが実行するすべてのノードで同一でなければなりません。クラスタ上のユーザーとグループの分布は以下の図のようになります。

特定ユーザーの情報を更新したい場合、各ノードの対応するファイルを更新しなければなりません。これは便利でも合理的でもありません。そこで、ローカルファイルの代わりに、ユーザーとグループを集中管理するストレージと、ユーザーとグループをネットワーク内の関連するすべてのノードに配布するツールが必要となります。

更新された図では、「auth_server_01」というコンポーネントには、集中化されたユーザーとグループのストレージが含まれており、「auth_server_01 connector daemon」は、ユーザーとグループをストレージから特定のノードに配信するソフトウェアツールを表しています。
これは最初の構成より良くはなっていますが、まだ十分ではありません。ユーザーのストレージがダウンした場合、計算ノードにもアクセスできなくなってしまうからです。また、特定のノードが他のノードと共有すべきではないジョブを持っている場合もあります。例えば、そのノード専用のソフトウェアを実行するジョブなどです。
最善の解決策は、あらかじめ定義された優先順位で、ローカルファイルと集中管理されたストレージを管理することです。言い換えれば、最初のソースからユーザー情報を取得できなかった場合、次に2番目のソースからユーザー情報を取得できるように設定します。このアルゴリズムは、図の中で「SWITCH」と表示されています。

最後に、図に別の「auth_server」コンポーネントを追加することで、複数の独立した集中型ユーザーとグループストレージサービスが存在するようになります。

これで完了です。HPCクラスターのユーザーとグループの管理モデルが完成しました。これは、実際のHPCクラスターでも同じように動作します。つまり、図に示したコンポーネントはすべて、Linuxで実際に実装されています。

上の図にあるように、HPCクラスターのすべてのノードでユーザーとグループを同期させるためには、3種類のコンポーネントを設定する必要があります。
- ディレクトリサービス(ネームサービス):ユーザーとグループの管理を担当するサービス
- ネームサービスデーモン:クラスタの各ノード上で動作するデーモンで、ディレクトリサービスから特定のノードへのユーザーとグループのデータ配信を担当します。
- ネームサービススイッチ:接続されたディレクトリサービスの順序と優先順位を定義するオペレーティングシステムツール
これらのコンポーネントを詳細に確認してみましょう。
ディレクトリサービス:集中型ユーザー/グループ管理
Linuxオペレーティングシステムは、ネットワーク指向のシステムであり、ネットワーク内で共有されているシステムリソースを動的にロードすることができるように設計されています。システムリソースとは、ユーザー、ユーザーのパスワード、グループ、メールエイリアス、DNS(Domain to IP Map)などである。ネットワークノード間でシステムリソースを提供・分配するネットワークサービスを「ディレクトリサービス」(またはネームサービス)と呼びます。
ユーザーやグループを管理するディレクトリサービスシステムは数多くあります。初期のものは、規格や慣習に頼らず、ゼロから作成されていました。その後、ディレクトリサービスの操作を定義し、共通のインターフェースを提供するために、X.500と呼ばれる一連のコンピュータネットワーク標準規格が作成されました。X.500規格では、ディレクトリサービスの以下の項目が定義されています。
- クライアントとディレクトリサービスの関係
- 2台のディレクトリサーバの相互運用方法
- ディレクトリサーバによる情報の複製方法
- 複製など、ディレクトリ同士の合意事項の管理方法
- 認証と認可
後にX.500規格は簡素化され、LDAP (Lightweight Directory Access Protocol) へと発展しました。この規格は、ディレクトリサービスの操作や手順をより正確に定義したものです。
例えば
- LDAP Data Interchange Format (LDIF)を用いて、追加、変更、削除、検索などの操作手順を文書化したもの
- データ構造をカスタマイズするための拡張可能なメカニズム、”スキーマ “と呼ばれるもの
- データの暗号化とセキュリティ
このように、ディレクトリサービスの実装は2つのグループに分けることができます。
- LDAPベースのシステム
- OpenLDAP
- FreeIPA(レッドハット)
- Active Directory(マイクロソフト)
- LDAP以前に作られたシステム
- ヘシオド
- Network Information Service (NIS)、旧Yellow Pages (YP)(サンマイクロシステムズ)
- バニヤンVINES
現在、最も普及しているディレクトリサービスシステムはLDAPです。しかし、シンプルで信頼性の高いLDAP以外のシステムも広く利用されています。
ネームサービスデーモン:ディレクトリサービスコネクター
ネットワークノードとディレクトリサービスの間の接続を提供するために、各ノードは特定のデーモンを実行する必要があります。各ディレクトリサービスディストリビューションは、コネクターデーモンのための独自の実装を提供することができます。LDAPベースのサービスの場合は、LDAPをサポートするデーモンを使用することができます。
例えば、以下のパッケージをネームサービスデーモンとして使用することができます。
- nslcd:LDAP用
- システムセキュリティサービスデーモン(SSSD):LDAP用
- ypbind:NISバージョン2用
- rpc.nisd:NISバージョン3 (NIS Plus) 用
通常、ネームサービスデーモンを設定するには、以下の手順を踏む必要があります。
- 接続するディレクトリサービスのネットワークアドレスの設定
- ディレクトリサービス上の現在のノードの認証の設定
- デーモンの実行
ネームサービススイッチ:複数のディレクトリサービス間のルーティング
前述の通り、ネームサービススイッチ(NSSwitch)は、システムリソースに優先順位をつけるように設計されています。Linuxシステムでは、設定ファイル”/etc/nsswitch.conf “を変更することで、優先順位を設定することができます。デフォルトでは、以下のようになっています。(この設定ファイルのコメント行は省略しました。)
passwd: files
group: files
shadow: files
gshadow: files
hosts: files dns
networks: files
protocols: db files
services: db files
ethers: db files
rpc: db files
netgroup: nis
設定ファイルは、key: valueのペアのリストで構成されています。
- keyは、リソースの名前になります
- valueは、スペースで区切られたソースの名前のリストで、これらのソースは、最初の応答が成功するまで、要求されたリソースのために次々とポーリングされます
ご覧のように、Linuxではデフォルトでローカルのプレーンテキストファイル (files) や拡張子が.dbのローカルバイナリファイルから情報を取得します。しかし、このファイルは必要に応じて自由に更新することができます。
例えば、NSSwitchの設定で以下のような構成となっている場合、システムはまずローカルファイルでユーザーとグループを探し、次にLDAPデータベースで探し、最後にNISデータベースで探します。何も見つからなかった場合、システムはエラーレスポンスを返します。
passwd: files ldap nis
group: files ldap nis
shadow: files ldap nis
システム構成によっては、以下の例のようにフォールバックシナリオを提供することもできます。つまり、LDAPとNISのどちらのデータベースでもユーザーやグループが見つからなかった場合、システムはローカルのユーザーやグループのリストにフォールバックする必要があります。
passwd: ldap nis files
group: ldap nis files
shadow: ldap nis files
[NOTFOUND=return]により、現在の行でこのキーワードの後にリストされているすべてのソースを無視されます。以下の例では、ルックアップは「ldap」ソースの後で停止します。
passwd: files ldap [NOTFOUND=return] nis
group: files ldap [NOTFOUND=return] nis
shadow: files ldap [NOTFOUND=return] nis
ソース名は以下のようになります。
- files:ローカルファイルpasswd、shadow、group
- db:バイナリデータベースにコンパイルされたローカルファイル (.dbファイル)
- nis:NISバージョン 2 (Yellow Pages (YP) とも呼ばれる) 用
- nisplus:NISバージョン 3 以降用
- dns:ドメインネームサービス用
- compat:NIS のコンパティモード用
- hesiod:Hesiod用
- ldap:nslcd (LDAP) 用
- sssd:システムセキュリティサービスデーモン用
詳細は、関連するLinuxのマニュアル「man 5 nsswitch.conf」に記載されています。
まとめ
この記事では、HPCクラスタのすべてのノードのユーザーとグループの同期を提供する方法について解説しました。ここまでで、ディレクトリサービスとそれと通信するLinuxツールに関する基本的な知識が得られました。今後の記事では、前回説明したDockerのSlurmクラスタの拡張機能として、ディレクトリサービスをインストールして設定する方法について説明します。
<著者について>
Yury Krapivkoは、10年以上の豊富な実務経験を持つソフトウェアエンジニアです。フルスタックのウェブ開発、クラウドエンジニアリング、ハイパフォーマンスコンピューティングなど、さまざまなプロジェクトに携わっており、HPC分野だけでも5年以上の経験を持っています。