Slurm HPCクラスタとKubernetesを同居させてみた（前編）

## はじめに
こんにちは、(株)日立製作所 研究開発グループ サービスコンピューティング研究部の小林です。

DockerやKubernetesに代表されるコンテナ技術がWebアプリ開発を始め様々な場面で使われるようになりました。最近ではHPC向けのコンテナランタイムとして`Singularity`が開発され、より一層コンテナ活用の幅が広がりそうですね。

本日のアドベントカレンダーでは、HPCジョブスケジューラの一つである`Slurm`クラスタとコンテナオーケストレータの`Kubernetes`クラスタを同居させ`Singularity`ベースのワークロードを双方から実行可能な環境を構築してみます。

アドベントカレンダーではHPCジョブスケジューラの一つである`PBS`に[関する記事](https://qiita.com/MasafumiTsuyuki/items/acf4b19b54937496e32b)もあるので興味がある方は要チェックです。

## なぜ同居させるのか
### データ分析技術の多様化

従来のデータ分析に関するいくつかの主要な動向として、HPCクラスタを用いた大規模バッチ処理や並列同期型のシミュレーションなどが挙げられます。また、新しいデータ分析の潮流として機械学習や深層学習も一般的になりつつあります。
機械学習に関する技術開発は近年一層活発に行われ、開発技術がコンテナイメージとして公開されています。更にはコンテナのスケーラビリティや可搬性/再現性を最大化する`コンテナオーケストレータ`として[Kubernetes](https://kubernetes.io/)が台頭し、コンテナを用いた機械学習のワークフローを管理する[Kubeflow](https://www.kubeflow.org/)などの便利技術なども続々と開発されています。

### HPCジョブスケージューラへのコンテナ統合
一方で、従来のHPCクラスタを用いたバッチ/パラレルジョブに`コンテナ技術`を取り入れる動きがあります。HPCジョブスケジューラの一つである[Slurm](https://slurm.schedmd.com/)ではコンテナ化されたジョブの実行をサポートし始めたり、HPCでの実行を想定したコンテナランタイムである[Singularity](https://sylabs.io/docs/)なども登場したことを受け、HPCジョブスケジューラとコンテナの距離は縮まっています。

### HPCジョブとコンテナアプリのワークロード統合
更には、Kubernetes側からも従来のHPCジョブとコンテナベースの処理のワークロード統合を示唆する[ブログ記事](https://kubernetes.io/blog/2017/08/kubernetes-meets-high-performance/)や、Singularity用のKubernetes対応コンテナランタイムインターフェース(CRI)として[Singularity-CRI](https://sylabs.io/guides/cri/1.0/user-guide/k8s.html)が開発されています。


特に、Singularity-CRIの登場により、HPCクラスタの多量のリソースの以下のような柔軟な活用が可能になります。

- 従来のHPCジョブ実行
- 実験作業の再現性確保が容易なコンテナベースのHPCジョブ実行
- GPUなどの潤沢なリソースを投入した高スケールなコンテナベースのデータ分析

## 構成

SlurmとKubernetes(K8s)の同居クラスタを作ります。UbuntuベースのマスタサーバにはSlurmとK8sのマスタとして役割を、ワーカサーバには同じくSlurmとK8sのワーカとしての役割を実行させます。

また、K8sのコンテナランタイムには、一般的なDocker(Containerd)ではなくSingularityを使います。

![fig1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/511483/ff4fae1a-d03c-e9c3-dc2b-dbfca69072af.png)


## 手順

### 概要
手順の概要を示します。マスタサーバとワーカサーバではデーモンや依存ソフトで共通するものも多いので、作業が分岐する場合は適宜言及します。

1. <a href='#-1-slurmクラスタを構築する-'>Slurmクラスタを構築する</a>
    1. <a href='#-11-マスタワーカ共通準備'>マスタ/ワーカ共通準備</a>
    2. <a href='#-12-slurmマスタの構築'>Slurmマスタの構築</a>
    3. <a href='#-13-slurmワーカの構築'>Slurmワーカの構築 (本日はここまで)</a>
2. Singularityを導入する(マスタ/ワーカ共通)
    1. Singularityの導入
    2. Singularity-CRI(Sycri)の導入
3. K8sクラスタを構築する
    1. マスタ/ワーカ共通準備
    2. K8sマスタの構築
    3. K8sワーカの構築
    4. CNIの設定

###  <a id='1'> 1. Slurmクラスタを構築する </a>
####  <a id='1-1'> 1.1. マスタ/ワーカ共通準備</a>

Slurmサーバの構築方法は[公式のQuickStart](https://slurm.schedmd.com/quickstart_admin.html)を参照します。
依存ツールのライブラリが足りないエラーが起きたので[こちらのサイト](https://mumeiyamibito.0am.jp/%E5%88%86%E5%AD%90%E3%82%B7%E3%83%9F%E3%83%A5%E3%83%AC%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E9%96%A2%E9%80%A3/%E7%92%B0%E5%A2%83%E6%A7%8B%E7%AF%89/slurm#%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E6%96%B9%E6%B3%95)も参考にしています。

まずは認証用の[MUNGE](https://github.com/dun/munge#munge-uid-n-gid-emporium)をインストールします。

```
sudo apt update
sudo apt install -y munge libmunge-dev libmunge2
sudo systemctl start munge && sudo systemctl enable munge
```
`MUNGE`はデーモンを起動すると認証用の秘密鍵を`/etc/munge/munge.key`に作成します。この秘密鍵はSlurmクラスタのマスタ・ワーカで共通のものを使うので`1.3.`にてマスタの鍵をコピーします。また、`MUNGE`は`/var/log/munge`以下にログを出力しますが、フォルダ所有者がユーザ`MUNGE`でない場合起動に失敗する場合があります。

最新版のSlurmを入手してインストールします。執筆時点での最新版は`slurm-19.05.4`です。
インストール前に、依存するライブラリ等を導入していきます。

```
sudo apt install -y build-essential python
```

続いてSlurmをソースコードからビルドします。ビルド後に`MUNGE`のライブラリに参照できないエラーが出たので`configure`のフラグを追加しました。

```
wget https://download.schedmd.com/slurm/slurm-19.05.4.tar.bz2
tar --bzip -x -f slurm*tar.bz2
cd slurm-19.05.4
sudo ./configure --with-munge="/usr/bin/munge"
sudo make && sudo make install
```

`Slurm`関連のサービスファイルを`/etc/systemd/system/`以下にコピーします。

```
sudo cp /home/ubuntu/slurm-19.05.4/etc/*.service /etc/systemd/system/
```

また、[公式のSuper Quick Start](https://slurm.schedmd.com/quickstart_admin.html)の`７ NOTE`にあるように、Slurm用のユーザを作成します。

```
sudo adduser slurm
```
Slurmユーザは、`/var/run/spool`, `/var/log/syslog`への参照や書込権限が必要なのでグループなりユーザに権限を付与します。環境によってポリシーが異なると思いますが、`root`グループなどに`slurm`ユーザを加えて適宜必要なフォルダにグループ権限を与えるなどの対応があると思います。


#### <a id='1-2'> 1.2. Slurmマスタの構築</a>
`Slurm`マスタサーバを構築します。構築前に`MUNGE`サービスが正常に動いていることを`systemctl status munge`などで確認しておきましょう。
マスタサーバ構築では、`Slurmクラスタ`のコンフィグ作成が主な作業になります。コンフィグの作成はSlurmが提供する`WebGUI`に必要事項を入力して出力されるファイルを`/usr/local/etc/slurm.conf`に配置します。

私は[Ubuntuサーバ版](https://blog.amedama.jp/entry/2018/08/04/230601)を入れてしまったので、他のPCからブラウザアクセスして作成することにしました。設定のためだけに`apache2`を入れて`http://HOSTNAME:80/html2/configurator.easy.html`にアクセスします。

```
sudo apt install -y apache2
sudo ln -s /home/ubuntu/slurm-19.05.4/doc/html /var/www/html/html2
```

サーバの設定に必要なリソース情報は下記のコマンドで適宜取得します。

```
# CPU関連
lscpu | grep -E '^Thread|^Core|^Socket|^CPU\('
> CPU(s):              2
> Thread(s) per core:  1
> Core(s) per socket:  1
> Socket(s):           2
```

```
# メインメモリ関連
free -m
>             total        used        free      shared  buff/cache   available
> Mem:           7976         102        5514           0        2359        7570
> Swap:             0           0           0
```

ひとしき入力し終えたら`submit`ボタンを押して得られる情報を`/usr/local/etc/slurm.conf`として出力します。
マスタサーバでは`slurmctld`をサービスとて起動します。

```
sudo systemctl start slurmctld && sudo systemctl enable slurmctld
```
起動後に`Can't open PID file /var/run/slurmctld.pid (yet?) after start: No such file or directory`などのエラーが出る場合がありますが、適宜ユーザやフォルダの権限を見直します。

#### <a id='1-3'> 1.3. Slurmワーカの構築</a>
ワーカで実施するべき作業は大きく２つです。

* `MUNGE`の秘密鍵をマスタサーバから入手し利用
* `Slurm`のコンフィグをマスタサーバから入手し利用

作業がうまく行かない場合は、マスタサーバとワーカサーバの`MUNGE`サービスや`slurm`関連サービスがキチンと`Active`になっているか適宜確認します。

`MUNGE`インストール後、マスタサーバの`munge.key`をコピーして`MUNGE`サービスを再起動します。

```
sudo scp SOME_USER@SLURM_MASTER:/etc/munge/munge.key SONE_USER@SLURM_WORKER:/ect/munge/munge.key
sudo systemctl restart munge
```
エラー無くサービスが起動できたことを確認します。


Slurmをインストール(サービスファイルのコピー含め)したのち、`Slurmコンフィグ`をコピーして利用します。

```
sudo scp SOME_USER@SLURM_MASTER:/usr/local/etc/slurm.conf SONE_USER@SLURM_WORKER:/usr/local/etc/slurm.conf
sudo chown root:root /usr/local/etc/slurm.conf
sudo start slurmd && sudo systemctl enable slurmd
```


ここまで完了し、`Slurm`マスタサーバで`MUNGE`と`SlurmCtld`が、ワーカサーバで`MUNGE`と`Slurmd`が正常稼働していること確認してからマスタサーバで`sinfo`を実行します。`AVAIL`が`up`ならSlurmクラスタの起動完了です。

```
sinfo
> PARTITION AVAIL  TIMELIMIT  NODES  STATE NODELIST
> debug*       up   infinite      1   idle test-slurm2
```

## 前編のおわりに

本日の投稿では`Slurm`と`Kubernetes`の同居クラスタ構築に関して、システム構成とSlurmクラスタの構築手順を紹介しました。[後編の投稿](https://qiita.com/mk32/items/2f7d551123571891ed0d)では`Singularity`とSingularity-CRIを利用して稼働する`Kubernetes`クラスタの構築手順とクラスタのサンプル実行を紹介したいと思います。