1. HOME
  2. What's New
  3. Docker上でSlurmを動作させてみましょう (POC)

What's New

最新情報

Tech Blog

Docker上でSlurmを動作させてみましょう (POC)

当社のお客様の中には、独自のHPCワークフローをコンテナ化したり、Dockerコンテナーを使用してHPCインフラストラクチャをスケーリングすることに興味をお持ちの方がいらっしゃるものと思います。そこで、コンテナーのセットとして動作するSlurmを使って、小規模なHPCクラスターを実行する方法について解説したいと思います。

Slurmは、Linuxクラスター向けのオープンソースのジョブスケジューリングシステムです。並列ジョブの実行、管理、監視など多くの機能を備えており、ハイパフォーマンスコンピューティング(HPC)の分野で広く利用されています。また、CaffeやTensorFlowなどの一般的な機械学習用フレームワークにも対応しています。

従来、Linuxクラスターでは、各ノードのシステムにインストールされたHPCソフトウェアへの共有アクセスを複数のユーザーに提供するために、各ノード上のオペレーティングシステムで直接Slurmを実行していました。この方法では、最大の計算性能を得ることができますが、管理に手間がかかったり、ソフトウェア更新による変更の影響を受けやすいといった問題があります。

コンテナー技術を利用するという別のアプローチも可能です。コンテナーとは、軽量な仮想化ソリューションであり、別々のプロセスを共有のOSコアを使って実行することができます。コンテナーには以下のような利点があり、Slurmを利用したクラスターを強化するのに適したツールです。

  • オールインワン –  必要なHPCソフトウェアとその関連ファイルのすべてを1つのファイル、つまりイメージとして束ねることができます。
  • 分離 – 同一システム内で実行されるコンテナーは、お互いに予期せぬ影響を与えることはありません。
  • スケーラビリティ – イメージファイルを使用することで、複雑なインストールをせずに、必要な数のコンテナーインスタンスを起動することができます。
  • ポータビリティ – コンテナー技術によって、あるシステム用に開発されたソフトウェアを別のシステムで実行することが可能となります。

一般的にSlurmはコンテナーに依存することはないので、既存のコンテナー管理システムと一緒に使うことができます。

この記事では、コンテナーとして動作するSlurmを使って、小規模なHPCクラスターを実行する方法を紹介します。コンテナー管理システムとしてDockerを選択したのは、その柔軟なインフラストラクチャーにより、実験環境を簡単に構築できるからです。また、

  • Dockerは、コンテナーを実行するための最も一般的なソリューションです。
  • Dockerには、大きなユーザーコミュニティがあります。
  • Dockerは、人気のあるオペレーティングシステムでサポートされています。Linux、Windows、MacOS、FreeBSD、その他。
  • Dockerコンテナーは、Azure、AWS、OCI、GCPなどのクラウド上で利用することができます。

SlurmをDocker上で実行する際には、注意点があります。

  • 公式にはSlurmはDockerをサポートしていません。その理由は、Dockerには複数の設計ポイントがあり、特権を持たないユーザーが多数いる従来のHPCシステムには不向きだからです。
  • HPCジョブをコンテナーで実行することにより、計算中のパフォーマンスが悪影響を受けることがあります。

この記事の目標は以下の通りです。

  • SlurmをDockerで実行する詳細方法を示す
  • イメージ構築とコンテナー実行に必要なDockerコマンドの基本的な知識を提供する
  • Dockerで独自のクラスターを構築する際に参考となるサンプル設定ファイルを集めたリポジトリを作成する

この記事で紹介したDockerとSlurm用のスクリプトと設定ファイルは、すべてXTREME-DのGitHubリポジトリで共有されています。

1. アーキテクチャー

ここでは、以下のような構成でシンプルなHPCクラスターを構築します。

クラスターには、1つのヘッドノード「axc-headnode」、4つのコンピュートノード「axc-compute-[01-04]」、Slurmのアカウンティングデータ用のMariaDB RDBMSサーバ「mariadb」が配置されています。

簡単にするために、複数のプロセスを1つのコンテナーにデプロイします。これはDockerのガイドラインの観点からは最適ではありませんが、Docker SlurmのデプロイをHPCクラスターの古典的な「ヘッドノード-コンピュートノード」のハードウェアアプライアンスと比較するには最適な方法です。

ここでは、ヘッドノードとコンピュートノードの両方のベースとして使用される単一のDockerイメージを作成します。また、SlurmのスプールデータとMariaDBのファイルをホストマシンのファイルシステムに保存します。これにより、クラスターを終了した後にジョブ情報を保存し、クラスター起動時にそれを復元することができます。

クラスターでは以下のソフトウェアを使用します。

  • Slurm v20.02.7
  • Munge(ノード間認証用)
  • Supervisor(コンテナー用の軽量プロセスマネージャ)
  • MariaDB v10.4(独立したコンテナー向けアカウントデータ用)

ホストマシンには、最低でもDocker CEdocker-composeが必要です。

2. 実装

まず、クラスターのコンテナーを実行する順番を決めます。

  1. MariaDBコンテナーの起動
  2. ヘッドノードコンテナーを起動します。ヘッドノードはslurmdbdプロセスを実行しているため、MariaDBに依存します。
  3. コンピュートノードコンテナーを起動します。コンピュートノードはヘッドノードに依存しているので、ヘッドノードを待たなければなりません。

また、Slurmが起動する前に完了しなければならない重要なステップがあります。

  1. Mungeキーを生成する
  2. Slurmデーモン用のスプールディレクトリの存在を確認し、存在しない場合は作成する。Slurmデーモンは自分でディレクトリを作ることができないので、これは非常に重要なステップです。
  3. slurmdbdでSlurmクラスターのエントリーを開始します。これはSlurmを起動した後に行う必要があります。

最後に、コンテナープロセスは次のような順序で実行されなければなりません。

  • mungedプロセス
  • slurmdプロセス
  • slurmctldプロセス(ヘッドノードのみ)
  • slurmdbd (ヘッドノードのみ)

2.1 設定

上に挙げた要件を満たしたら、次に何を実行するかを決めます。

  • コンテナーの実行順序を維持するために、docker-compose services の depends_on プロパティを使用します。
  • コンテナーのプロセスを決められた順序で実行するために、supervisorのpriorityプロパティを使用します。
  • 初期データを生成するために、コンテナー用のエントリーポイントスクリプトを作成します。
  • slurmdプロセスとの通信を必要とするslurmdbdの初期データを生成するために、ワンショットのsupervisorプロセスを作成し、slurmdの後に配置します。

また、

  • ノードのdockerイメージには設定ファイルを含めず、コンテナーにマウントするようにします。
  • 安定した動作を実現するために、MariaDBコンテナーには特別な設定を行います。
  • docker logs “コマンドの出力で見られるように、コンテナープロセスのすべてのログを/dev/stdoutに送ります。

2.2 設定ファイル

次に、クラスターに追加する必要のある設定ファイルを定義します。

2.2.1 slurm.confファイル

「slurm.conf」は、Slurmプロセスの共通の設定ファイルです。ベースとなるのは、デフォルトの slurmd.conf ファイルで、いくつかの値をオーバーライドする必要があります。最も重要なオーバーライドをチェックしてみましょう。

まず、クラスターの名前を定義します。

ClusterName=docker-slurm-cluster

slurmctldが動作しているホストを指定します。

SlurmctldHost=axc-headnode

ノードの認証タイプを選択します。

AuthType=auth/munge

slurmのスプールデータのパスを定義します。ホストマシンからマウントされているディレクトリである必要があります。

StateSaveLocation=/var/spool/slurm/ctld

アカウントに関連する設定を定義します。

AccountingStorageHost=localhost
AccountingStoragePass=/var/run/munge/munge.socket.2
AccountingStorageType=accounting_storage/slurmdbd

最後に、slurmのノードとクラスターのパーティションを定義する必要があります。ここでは、すべてのコンピュートノードを含む1つのパーティションを定義します。

NodeName=axc-headnode CPUs=2 State=UNKNOWN
NodeName=axc-compute-[01-04] CPUs=2 State=UNKNOWN
PartitionName=compute Nodes=axc-compute-[01-04] Default=Yes MaxTime=24:00:00 State=UP OverSubscribe=Yes

2.2.2 slurmdbd.confファイル

この設定ファイルには slurmdbd プロセスの特定の設定が含まれています。ここで最も重要なオーバーライドは、アカウンティングデータ用に使用するデータベースの認証情報になります。

StorageType=accounting_storage/mysql
StorageHost=mariadb
StoragePort=3306
StoragePass=
StorageUser=slurm
StorageLoc=slurm_acct_db

2.2.3 supervisor設定

前述したように、クラスターコンテナ内のプロセスをスーパーバイザープログラムとして実行することになります。そのため、プロセスごとにsupervisor app configファイルを作成する必要があります。さらに、定義された実行順序を維持しなければなりません。

axc-headnode
- (1) munged
- (2) slurmd
- (3) slurmctld
- (4) slurmdbd
- (5) slurmdbd_init__oneshotaxc-compute-[01-04]
- (1) munged
- (2) slurmd

「slurmdbd_init__oneshot」コマンドで、アカウンティングデータベースにクラスターエントリが存在していない場合、これを作成します。

2.2.4 mariadb-slurmdbd.cnf

MariaDBコンテナーが安定して動作するように、以下のように設定した設定ファイルを追加する必要があります。

innodb_buffer_pool_size=1024M
innodb_log_file_size=48M
innodb_lock_wait_timeout=900

2.3 ビルドと実行

すべての準備が完了したら、dockerクラスターをビルドし実行してみましょう。

リポジトリをクローンします。

git checkout git@github.com:xtreme-d/docker-slurm-cluster.git docker-slurm-cluster
cd docker-slurm-cluster

envファイルを複製して、内容を以下のように変更します。

cp .env-sample .env
vi .env

<SECRET>の部分にmariadbのパスワードを入力し、ノードイメージをビルドします。

docker-compose build

クラスターを開始します。

docker-compose up -d

コンテナーの状況を確認します。

$ docker-compose ps                                                                                                        
     Name                   Command               State              Ports            
--------------------------------------------------------------------------------------
axc-compute-01   /docker-entrypoint.sh /bin ...   Up      6817/tcp, 6818/tcp, 6819/tcp
axc-compute-02   /docker-entrypoint.sh /bin ...   Up      6817/tcp, 6818/tcp, 6819/tcp
axc-compute-03   /docker-entrypoint.sh /bin ...   Up      6817/tcp, 6818/tcp, 6819/tcp
axc-compute-04   /docker-entrypoint.sh /bin ...   Up      6817/tcp, 6818/tcp, 6819/tcp
axc-headnode     /docker-entrypoint.sh /bin ...   Up      6817/tcp, 6818/tcp, 6819/tcp
axc-mariadb      docker-entrypoint.sh mysqld      Up      3306/tcp                    
$

すべてが起動し、テストを実行する準備が整いました。

3. テスト

クラスターの起動後、Slurmコマンドをテストします。そのためには、ヘッドノードのシェルにアクセスします。

docker exec -it axc-hednode bash

Slurmのプロセスが起動していることを確認します。

[root@axc-headnode /]# supervisorctl status                                                                                                                                          
munged                           RUNNING   pid 114, uptime 0:45:43
slurmctld                        RUNNING   pid 209, uptime 0:45:29
slurmd                           RUNNING   pid 116, uptime 0:45:43
slurmdbd                         RUNNING   pid 196, uptime 0:45:32
slurmdbd_init__oneshot           EXITED    Jun 29 09:25 AM
sshd                             RUNNING   pid 113, uptime 0:45:43

Slurm関連のプロセスはすべて稼働しています。相互接続を確認するために、mungeをテストしてみましょう。

[root@axc-headnode /]# munge -n; munge -n | unmunge; remunge
MUNGE:AwQDAAArpg0TEMSR/tGLHgcMv147rFy/HUkAqav3bPZf2wkQ+aQMYOTanDD57KdjKyMWQMPslybNHwkzqdiveudyMWz79e+MTPos1yhRbSqc8HNhhhOAPAE=:
STATUS:           Success (0)
ENCODE_HOST:      axc-headnode (172.20.0.3)
ENCODE_TIME:      2021-06-29 11:23:44 +0000 (1624965824)
DECODE_TIME:      2021-06-29 11:23:44 +0000 (1624965824)
TTL:              300
CIPHER:           aes128 (4)
MAC:              sha1 (3)
ZIP:              none (0)
UID:              root (0)
GID:              root (0)
LENGTH:           0

2021-06-29 11:23:44 Spawning 1 thread for encoding
2021-06-29 11:23:44 Processing credentials for 1 second
2021-06-29 11:23:45 Processed 2248 credentials in 1.000s (2247 creds/sec)
[root@axc-headnode /]#

Slurmコマンドをテストします。

[root@axc-headnode /]# squeue
             JOBID PARTITION     NAME     USER ST       TIME  NODES NODELIST(REASON)
[root@axc-headnode /]# sinfo
PARTITION AVAIL  TIMELIMIT  NODES  STATE NODELIST
compute*     up 1-00:00:00      4   idle axc-compute-[01-04]
[root@axc-headnode /]# sacct
       JobID    JobName  Partition    Account  AllocCPUS      State ExitCode 
------------ ---------- ---------- ---------- ---------- ---------- --------

すべて問題なく動作していますので、テスト用のバッチジョブを作成して実行します。

[root@axc-headnode /]# cat > test.batch <<EOF
#!/bin/bash
#
#SBATCH --job-name=xs-test-job
#SBATCH --ntasks=4

srun hostname
srun sleep 10
EOF
[root@axc-headnode /]# sbatch test.batch
Submitted batch job 6
[root@axc-headnode /]# squeue
             JOBID PARTITION     NAME     USER ST       TIME  NODES NODELIST(REASON)
                 6   compute xs-test-     root  R       0:03      2 axc-compute-[01-02]
[root@axc-headnode /]# sinfo
PARTITION AVAIL  TIMELIMIT  NODES  STATE NODELIST
compute*     up 1-00:00:00      2  alloc axc-compute-[01-02]
compute*     up 1-00:00:00      2   idle axc-compute-[03-04]
[root@axc-headnode /]#

最後に、アカウントを確認してみます。

[root@axc-headnode /]# sacct
       JobID    JobName  Partition    Account  AllocCPUS      State ExitCode 
------------ ---------- ---------- ---------- ---------- ---------- -------- 
2              headnode    compute       root          1     FAILED      2:0 
3              hostname    compute       root          1  COMPLETED      0:0 
4              hostname    compute       root          4  COMPLETED      0:0 
5              hostname    compute       root          5 CANCELLED+      0:0 
6            xs-test-j+    compute       root          4  COMPLETED      0:0 
6.batch           batch                  root          2  COMPLETED      0:0 
6.0            hostname                  root          4  COMPLETED      0:0 
6.1               sleep                  root          4  COMPLETED      0:0 
[root@axc-headnode /]#

4. 結論

これまで見てきたように、SlurmはDocker環境上で問題なく機能しますし、その自動化されたデプロイ機能には大きな可能性があると言えます。しかし、現在のDockerクラスターは、本番運用に対応したソリューションとは言えません。これはパフォーマンスの状況だけではなく、Slurmだけでできることが限られているからです。

機械学習フレームワークのサポートが追加されれば、より良いものになるでしょう。また、以下のような改善が必要な点もあります。

  • ユーザー管理用認証サーバーの追加
  • Docker SwarmやKubernetesなどのコンテナーオーケストレーションツールを利用したクラスターデプロイ機能の提供
  • クラスターをクラウドサービスにデプロイする機能の提供

次回の記事ではこのような内容を取り上げる予定です。

<著者について>
Yury Krapivkoは、10年以上の豊富な実務経験を持つソフトウェアエンジニアです。フルスタックのウェブ開発、クラウドエンジニアリング、ハイパフォーマンスコンピューティングなど、さまざまなプロジェクトに携わっており、HPC分野だけでも5年以上の経験を持っています。