
Slurmジョブ実行時に発生したI/Oタイムアウトの解決方法について整理してみました。
こんにちは、クラスメソッドのキム・ジェウク(Kim Jaewook)です。
今回は、Slurmジョブ実行時に発生したI/Oタイムアウトの原因と解決方法について整理してみました。
Slurmの検証内容については、以下のブログで紹介しています。
Slurmでジョブ実行時に発生する「connect io: Connection timed out」エラーの解決
Slurmクラスタを構築した後、簡単なsrunテストを実施したところ、予想外のI/Oタイムアウトエラーが発生しました。
最初は、Slurmデーモン(slurmctld、slurmd)が正常に動作しており、必要なポートもすべて設定済みだったため、原因の特定に時間がかかりました。
しかし、原因は、Slurmがジョブ実行時に使用するEphemeral Port(任意ポート)の通信設定にありました。
今回は、発生したエラーの内容、原因、そして解決方法について整理します。
問題発生
Slurmクラスタ構築後、動作確認のためhostnameを実行しました。
srun --nodes=1 --ntasks=1 hostname
しかし、何も出力されないまま数十秒間停止した後、以下のエラーが表示されました。
error: connect io: Connection timed out
error: _fork_all_tasks: IO setup failed: Slurmd could not connect IO
最初は、以下の問題を疑いました。
slurmdが正常に起動していないslurmctldとの通信問題- DNSまたはHostname設定問題
- Munge認証問題
しかし、確認した結果、これらの項目には、問題がなく、正常に動作していることを確認できました。
原因
原因は、SlurmのI/O接続方式にありました。
多くの人は、Slurmでは、6817、6818ポートを設定すれば問題ないと考えます。
代表的に使用されるポートは、以下の通りです。
| ポート | 用途 |
|---|---|
| 6817 | slurmctld |
| 6818 | slurmd |
| 6819 | slurmdbd(オプション) |
私も同様に、セキュリティグループ(Security Group)で、上記ポートをすべて許可していました。
そのため、最初はネットワーク設定が原因ではないと判断していました。
Slurmはジョブ実行時に別のI/Oチャネルを作成する
srunでジョブを実行すると、単純にslurmctldと通信するだけではありません。
基本的な実行の流れは、以下の通りです。
srun
│
▼
slurmctld(Master)
│
▼
slurmd(Worker)
│
▼
Task実行
ここまでは、多くの人がイメージする一般的な処理の流れです。
しかし、ジョブ実行時には、もう一つ重要な通信が行われます。
Worker
│
│(Ephemeral Port)
▼
Master
ワーカーノードで、実行されたプロセスの標準入力(stdin)、標準出力(stdout)、標準エラー(stderr)をマスターノードへ転送するため、別のI/O接続が確立されます。
この接続では、Slurm専用ポート(6817、6818)ではなく、OSが割り当てるEphemeral Port(任意ポート)が使用されます。
Linuxで一般的に利用されるEphemeral Portの範囲は、以下の通りです。
1024-65535
環境によって異なる場合もありますが、多くのLinuxディストリビューションでは、この範囲、またはこれに近い範囲が使用されています。
Worker
│
├── 6818 → slurmd通信
│
└── Ephemeral Port → I/O通信
このように、ジョブ実行時には2種類の通信が同時に行われます。
なぜタイムアウトが発生したのか?
今回構築した環境は、Amazon EC2上のSlurmクラスタでした。
マスターノードのセキュリティグループでは、以下のポートのみを許可していました。
6817
6818
そのため、Slurmデーモン同士の通信には、問題ありませんでした。
しかし、ワーカーノードからマスターノードへ新しいI/O接続を確立しようとした際、
Worker
│
│ 54321
▼
Master
セキュリティグループによって、該当ポートへの通信が遮断され、接続を確立できませんでした。
その結果、一定時間接続を再試行した後、以下のエラーが表示されました。
error: connect io: Connection timed out
error: _fork_all_tasks: IO setup failed:
Slurmd could not connect IO
つまり、Slurm自体は正常に動作していましたが、ジョブ実行時に必要となるI/Oチャネルを確立できなかったことが原因でした。
そのため、ジョブが開始されないように見えていました。
解決方法
解決方法は非常にシンプルでした。
マスターノードのセキュリティグループのインバウンドルールに、以下の設定を追加しました。
| ポート範囲 | プロトコル | ソース |
|---|---|---|
| 1024-65535 | TCP | Worker Security Group |
重要なポイントは、0.0.0.0/0で全体に公開するのではなく、Worker Security Groupのみを許可することです。
これにより、必要なノード間でのみEphemeral PortによるI/O通信が確立されるため、セキュリティを維持しながら問題を解決できます。
解決後のテスト
セキュリティグループを修正した後、同じコマンドを再度実行してみました。
srun --nodes=1 --ntasks=1 hostname
今回は正常に実行され、ワーカーノードのHostnameが返されました。
ip-10-0-yyy-yyy.ap-northeast-1.compute.internal
Slurmの設定を変更することなく、セキュリティグループの設定を修正するだけで問題を解決できました。
なぜ原因の特定が難しかったのか?
この問題は、Slurmを初めて構築する際によく陥りやすい落とし穴です。
多くのセットアップガイドでは、以下のポートのみが説明されています。
- 6817(slurmctld)
- 6818(slurmd)
- 6819(slurmdbd、オプション)
そのため、「必要なポートはすべて開放されている」と考えがちです。
しかし、srunによるジョブ実行時には、ワーカーノードからマスターノードへ別のI/O接続が確立され、この通信にはOSが動的に割り当てるEphemeral Port(任意ポート)が使用されます。
オンプレミス環境では、ファイアウォールの制限が比較的緩かったり、内部ネットワーク間の通信が自由に許可されていたりするため、この問題が表面化しないことがあります。
一方、AWSのSecurity Groupのように、明示的に許可されたポート以外は通信できない環境では、このI/O接続が遮断され、connect io: Connection timed outエラーが発生する原因となります。
最後に
error: connect io: Connection timed outやSlurmd could not connect IOが発生した場合でも、必ずしもSlurmの設定やMunge認証に問題があるとは限りません。
クラスタの基本的な通信が正常であっても、ジョブ実行時に作成されるI/OチャネルがファイアウォールやSecurity Groupによって遮断されている場合、同じエラーが発生することがあります。
AWS環境でSlurmクラスタを運用する場合は、以下の項目もあわせて確認することをおすすめします。
- 6817、6818ポートが正しく開放されているか
- マスターノードとワーカーノード間のSecurity Groupルールが正しく設定されているか
- ワーカーノードからマスターノードへのEphemeral Port(1024–65535/TCP)通信が許可されているか
srun hostnameなどの簡単なコマンドで事前に動作確認を行っているか
今回のように、Slurm自体の設定には問題がなくても、ネットワークポリシーが原因でジョブを実行できないケースは少なくありません。
connect io: Connection timed outエラーが発生した場合は、Slurmの設定だけでなく、Security Groupやファイアウォールの設定もあわせて確認することをおすすめします。






