Enroot と Pyxis を試してみた

# はじめに
2020年1月に開催された [Slurm User Group Meetup Tokyo #1](https://sugj.connpass.com/event/159409/) にて Enroot と Pyxis というものを知りました。

直近、Enroot は知っておく必要がありそうだったので、簡単に試してみました。
また Slurm 自体のセットアップについては割愛いたします。

# Enroot
## Enroot とは？
簡単に言うと Docker イメージを root 権限を必要なくできるランタイムでしょうか。
HPC 環境で Docker を利用する際、問題になってくるのが root 権限だと思います。Enroot を使うことで Docker イメージをシンプルに HPC 環境で利用することができます。
今回は試していませんが、MPI もコンテナ間で利用できるようです。

詳細は以下からご確認ください。
https://www.slideshare.net/SaSakiKuninobu/enrootpyxis
https://github.com/NVIDIA/enroot

## セットアップ
### Requirements
[ここ](https://github.com/NVIDIA/enroot/blob/master/doc/requirements.md) に書いてある通り実行してみます。

```
[opc@mgmt ~]$ curl -fSsL -O https://github.com/NVIDIA/enroot/releases/download/v2.2.0/enroot-check_2.2.0_$(uname -m).run
 
[opc@mgmt ~]$ chmod +x enroot-check_*.run
 
[opc@mgmt ~]$ ./enroot-check_*.run --verify
Kernel version:
 
Linux version 4.14.35-1902.3.2.el7uek.x86_64 (mockbuild@jenkins-10-147-72-125-e80953de-da77-4071-b997-208f4a68084f) (gcc version 4.8.5 20150623 (Red Hat 4.8.5-16.0.3) (GCC)) #2 SMP Tue Jul 30 03:59:02 GMT 2019
 
Kernel configuration:
 
CONFIG_NAMESPACES                 : OK
CONFIG_USER_NS                    : OK
CONFIG_SECCOMP_FILTER             : OK
CONFIG_OVERLAY_FS                 : OK (module)
CONFIG_X86_VSYSCALL_EMULATION     : OK
CONFIG_VSYSCALL_EMULATE           : KO (required if glibc <= 2.13)
CONFIG_VSYSCALL_NATIVE            : KO (required if glibc <= 2.13)
 
Kernel command line:
 
vsyscall=native                   : KO (required if glibc <= 2.13)
vsyscall=emulate                  : KO (required if glibc <= 2.13)
 
Kernel parameters:
 
user.max_user_namespaces          : OK
user.max_mnt_namespaces           : OK
 
Extra packages:
 
nvidia-container-cli              : KO (required for GPU support)
pv                                : KO (optional)
 
[opc@mgmt ~]$ ./enroot-check_*.run
Bundle ran successfully!
```

いくつか気になるところはありましたが、successfully! だったのでそのまま進めます。

### Install

[こちら](https://github.com/NVIDIA/enroot/blob/master/doc/installation.md) を参考に進めます。

```
[opc@mgmt ~]$ arch=$(uname -m)
[opc@mgmt ~]$ sudo yum install -y https://github.com/NVIDIA/enroot/releases/download/v2.2.0/enroot-2.2.0-1.el7.${arch}.rpm
[opc@mgmt ~]$ sudo yum install -y https://github.com/NVIDIA/enroot/releases/download/v2.2.0/enroot+caps-2.2.0-1.el7.${arch}.rpm
```

今回は試しませんが、GPU 環境で利用する際は以下も実施します。

```
[opc@mgmt ~]$ export DIST=rhel7.6
[opc@mgmt ~]$ curl -s -L https://nvidia.github.io/libnvidia-container/$DIST/libnvidia-container.repo | sudo tee /etc/yum.repos.d/libnvidia-container.repo
[opc@mgmt ~]$ sudo yum install libnvidia-container1 libnvidia-container-tools
```

## 動かす

動作チェックとして [cowsay](https://hub.docker.com/r/chuanwen/cowsay) を動かしてみます。

まずは cowsay のイメージを import します。

```
[opc@mgmt ~]$ enroot import docker://chuanwen/cowsay
```

import が終わるとカレントディレクトリに以下のようなファイルができるので、それを指定して create します。

```
[opc@mgmt ~]$ ls
chuanwen+cowsay.sqsh
 
[opc@mgmt ~]$ enroot create --name cowsay chuanwen+cowsay.sqsh
```

では、cowsay を実行してみます。

```
[opc@mgmt ~]$ enroot start cowsay     
 ________________________________________
/ No house should ever be on any hill or \
| on anything. It should be of the hill, |
| belonging to it.                       |
|                                        |
\ -- Frank Lloyd Wright                  /
 ----------------------------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
```

無事、動きました。

また、自己解凍アーカイブにすることも可能とのことで試してみたのが、こちら。

```
[opc@mgmt ~]$ enroot bundle --output cowsay.run chuanwen+cowsay.sqsh
[INFO] Extracting squashfs filesystem...
 
Parallel unsquashfs: Using 2 processors
11724 inodes (12233 blocks) to write
 
[======================================================================================================================================================================================|] 12233/12233 100%
 
created 10054 files
created 1325 directories
created 1655 symlinks
created 0 devices
created 0 fifos
 
[INFO] Generating bundle...
 
Header is 601 lines long
 
About to compress 192028 KB of data...
Adding files to archive named "/home/opc/cowsay.run"...
skipping crc at user request
Skipping md5sum at user request
 
Self-extractable archive "/home/opc/cowsay.run" successfully created.

[opc@mgmt ~]$ ls -l cowsay.run
-rwxrwxr-x. 1 opc opc 179176267 Jan 30 04:03 cowsay.run

[opc@mgmt ~]$ ./cowsay.run
 ________________________________________
/ Animals can be driven crazy by putting \
| too many in too small a pen. Homo      |
| sapiens is the only animal that        |
| voluntarily does this to himself.      |
|                                        |
\ -- Lazarus Long                        /
 ----------------------------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
```

### Slurm から実行する
動くのは分かっていますが、一応、slurm からも実行してみます。
Compute Node にも Enroot をインストール(手順は割愛)し、以下のジョブスクリプトを流してみます。cowsay に hostname をしゃべらせてみます。

```container.slm
[opc@mgmt ~]$ cat container.slm
#!/bin/bash
#SBATCH --nodes=1
#SBATCH --time=3:00
 
./cowsay.run /usr/games/cowsay `hostname`
```

ジョブを投げて、結果を確認します。

```
[opc@mgmt ~]$ sbatch container.slm
 
[opc@mgmt ~]$ cat slurm-23.out
 _________________________
< vm-standard2-1-ad1-0001 >
 -------------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
```


# Pyxis
## Pyxis とは
Meetup では(たしか・・・) 「Slurm のプラグインで Ennroot を Slurm 環境で使いやすくしたもの」 と紹介されていた。
どういうものかイメージできなかったので、こちらも試してみます。

## セットアップ

Slurm の Controller Node でセットアップを進めます。

コンパイルに以下が必要でしたのでインストールしておきます。

```
sudo yum install -y slurm-devel.x86_64
```

コンパイルをします。

``` bash:ControllerNode
[opc@mgmt ~]$ git clone https://github.com/NVIDIA/pyxis.git
[opc@mgmt ~]$ cd pyxis/
[opc@mgmt pyxis]$ ls
CONTRIBUTING.md  LICENSE  Makefile  README.md  common.c  common.d  common.h  common.o  debian  pyxis_slurmd.c  pyxis_slurmstepd.c  seccomp_filter.h
[opc@mgmt pyxis]$  sudo make install
cc -std=gnu11 -O2 -g -Wall -Wunused-variable -fstack-protector-strong -fpic  -D_GNU_SOURCE -D_FORTIFY_SOURCE=2 -I/usr/include/slurm -I/usr/include/slurm-wlm  -MMD -MF pyxis_slurmstepd.d -c pyxis_slurmstepd.c
cc -std=gnu11 -O2 -g -Wall -Wunused-variable -fstack-protector-strong -fpic  -D_GNU_SOURCE -D_FORTIFY_SOURCE=2 -I/usr/include/slurm -I/usr/include/slurm-wlm  -MMD -MF pyxis_slurmd.d -c pyxis_slurmd.c
cc -shared -Wl,-znoexecstack -Wl,-zrelro -Wl,-znow  -o spank_pyxis.so common.o pyxis_slurmstepd.o pyxis_slurmd.o
strip --strip-unneeded -R .comment spank_pyxis.so
install -d -m 755 /usr/local/lib/slurm
install -m 644 spank_pyxis.so /usr/local/lib/slurm
install -d -m 755 /usr/local/share/pyxis
echo 'required /usr/local/lib/slurm/spank_pyxis.so' | install -m 644 /dev/stdin /usr/local/share/pyxis/pyxis.conf
[opc@mgmt pyxis]$
```

Controller Node と Compute Node に設定を追加して、サービスを再起動させます。

```bash:ControllerNode_&_ComputeNode
[opc@mgmt pyxis]$ cp spank_pyxis.so /mnt/shared/etc/slurm/
[opc@mgmt pyxis]$ vi /etc/slurm/plugstack.conf
required /mnt/shared/etc/slurm/spank_pyxis.so

// Controler Node
sudo systemctl restart slurmctld

// Compute Node
sudo systemctl restart slurmd
```

## 動かしてみる

が、failed した。

```
opc@mgmt ~]$ srun --container-image=chuanwen/cowsay /usr/games/cowsay Hello
slurmstepd: pyxis: importing docker image ...
slurmstepd: error: pyxis: child 14283 failed with error code: 1
slurmstepd: error: pyxis: failed to import docker image
slurmstepd: error: pyxis: printing contents of log file ...
slurmstepd: error: pyxis:     mkdir: cannot create directory /run/enroot: Permission denied
slurmstepd: pyxis: could not remove squashfs: No such file or directory
slurmstepd: error: spank: required plugin spank_pyxis.so: task_init_privileged() failed with rc=-1
slurmstepd: error: spank_task_init_privileged failed
slurmstepd: error: write to unblock task 0 failed: Broken pipe
srun: error: vm-standard2-1-ad1-0001: task 0: Exited with exit code 1
```

/run/enroot 配下に権限が必要とのことです。
これはどう回避すべきなのか確認したのが [こちら](https://github.com/NVIDIA/pyxis/issues/12) 。
なるほど。今回は以下のようにした。

```bash:ControllerNode_&_ComputeNode
[opc@mgmt ~]$ sudo vi /etc/enroot/enroot.conf 

// 以下を追加
ENROOT_RUNTIME_PATH /run/enroot/user-$(id -u)
ENROOT_DATA_PATH /tmp/enroot-data/user-$(id -u)
```

```bash:ControllerNode
[opc@mgmt ~]$ sudo vi /mnt/shared/etc/slurm/prolog.sh 

#!/bin/sh
runtime_path="$(sudo -u "$SLURM_JOB_USER" sh -c 'echo "/run/enroot/user-$(id -u)"')"
mkdir -p "$runtime_path"
chown "$SLURM_JOB_UID:$(id -g "$SLURM_JOB_UID")" "$runtime_path"
chmod 0700 "$runtime_path"

[opc@mgmt ~]$ sudo chmod 755 /mnt/shared/etc/slurm/prolog.sh 

[opc@mgmt ~]$ sudo vi /etc/slurm/slurm.conf 

// 以下を追加
Prolog=/mnt/shared/etc/slurm/prolog.sh

[opc@mgmt ~]$ sudo systemctl restart slurmctld
```

再度、実行。

```
[opc@mgmt ~]$ srun --container-image=chuanwen/cowsay /usr/games/cowsay 'Hello Pyxis!'
slurmstepd: pyxis: importing docker image ...
slurmstepd: pyxis: creating container filesystem ...
slurmstepd: pyxis: starting container ...
 ______________
< Hello Pyxis! >
 --------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
```

っということで、Docker イメージをサクッと実行したい場合に Pyxis は便利ということが分かりました。


# 最後に
Enroot と似たようなものとしては Singularity になると思いますが、機会があればどういう場合にどちらを使った方が良いか、など確認できればと思います。