はじめに
こんにちは、(株)日立製作所 研究開発グループ サービスコンピューティング研究部の小林です。
本日のアドベントカレンダーは、HPCジョブスケジューラSlurm
とコンテナオーケストレータKubernetes
の同居クラスタを構築する投稿の後編です。Singularity
ベースのワークロードを双方から実行可能な環境を構築しきり、サンプルプログラムを実行してみます。
アドベントカレンダーではHPCジョブスケジューラの一つであるPBS
に関する記事もあるので興味がある方は要チェックです。
手順
概要
構築手順の概要を示します。本日は手順2
以降を紹介します。前回の投稿はこちらです。
- Slurmクラスタを構築する
- マスタ/ワーカ共通準備
- Slurmマスタの構築
- Slurmワーカの構築
- Singularityを導入する (本日はここから)
- K8sクラスタを構築する
2. Singularityを導入する(マスタ/ワーカ共通)
ここではコンテナランタイムのSingularity
を導入します。コンテナランタイムと一口に言っても、高レイヤと低レイヤの2つがあります。Singularity
はコンテナ自体の操作を提供する低レイヤのランタイムを指しますが、ここではKubernetes
などとのコンテナオーケストレータ向けにAPIを提供する高レイヤのランタイムとしてSingularity-CRI
も含めます。
2.1. Singularityの導入
基本的には公式のインストールページを参考にします。執筆当時の最新バージョンはv3.4.0
です。
執筆当時のGO最新版はv1.14ですが、さしあたり筆者が使い慣れたv1.13をGOの公式を参考にインストールしています。
# 依存するツール・ライブラリのインストール
sudo apt-get install -y \
build-essential \
libssl-dev \
uuid-dev \
libgpgme11-dev \
squashfs-tools \
libseccomp-dev \
wget \
pkg-config \
git \
cryptsetup-bin
# GO1.13のインストール
sudo add-apt-repository ppa:longsleep/golang-backports && \
sudo apt-get update && \
sudo apt-get install -y golang-go
次にSingularity
をインストールします。
git clone https://github.com/sylabs/singularity.git && \
cd singularity && \
git checkout v3.4.0
./mconfig && \
make -C ./builddir && \
sudo make -C ./builddir install
sudo apt-get install -y socat
2.2. Singularity-CRI(Sycri)の導入
続いてSycri
を公式のGitHubを参考にインストールします。
git clone https://github.com/sylabs/singularity-cri.git && \
cd singularity-cri && \
git checkout tags/v1.0.0-beta.5 -b v1.0.0-beta.5 && \
make && \
sudo make install
Sycri
サービスはデーモンとして起動させるので公式ページを参考にサービスファイルを/etc/systemd/system/sycri.service
に追加します。
[Unit]
Description=Singularity-CRI
After=network.target
StartLimitIntervalSec=0
[Service]
Type=simple
Restart=always
RestartSec=1
ExecStart=/usr/local/bin/sycri
Environment="PATH=/usr/local/libexec/singularity/bin:/bin:/sbin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin"
[Install]
WantedBy=multi-user.target
サービスを起動します。
sudo systemctl start sycri && sudo systemctl enable sycri
実行後、sycri
サービスが正常起動しているか確認します。
sudo systemctl status sycri
3. K8sクラスタを構築する
最後にKubernetesクラスタを構築します。手順はUbuntuへのK8sインストール記事のStep. 3-6
を参考にしています。
ただしこの記事ではコンテナランタイムがDocker
になっているのでSingularityの公式ページを参考に修正します。
3.1. マスタ/ワーカ共通準備
Kubernetes
レポジトリをapt
に追加します。
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add
sudo apt-add-repository "deb http://apt.kubernetes.io/ kubernetes-xenial main"
sudo apt-get install -y kubeadm kubelet kubectl
Kubernetes
の実行に必要なサーバ設定を施します。
下記のSwapの停止
に関してはサーバ再起動後も設定が維持するために/etc/fstabを修正する方法もあります。
# Swapの停止
sudo swapoff -a
# NW周りの設定. lsmodの結果が何も表示されなければmodprobe以下を実行
lsmod | grep br_netfilter
sudo modprobe br_netfilter
sudo cat /proc/sys/net/bridge/bridge-nf-call-iptables # 1が出力されることを確認
sudo cat /proc/sys/net/bridge/bridge-nf-call-ip6tables # 1が出力されることを確認
sudo sysctl net.ipv4.ip_forward=1
コンテナランタイム変更設定を/var/default/kubelet
に追加します。
KUBELET_EXTRA_ARGS=--container-runtime=remote \
--container-runtime-endpoint=unix:///var/run/singularity.sock \
--image-service-endpoint=unix:///var/run/singularity.sock
3.2. K8sマスタの構築
Kubernetesマスタサーバ関連のサービスを起動します。執筆者環境ではCRI
とPodネットワークのCidr
を指定をする必要がありました。また、Sycri
サービスが正常に起動していることを確認してください。
sudo kubeadm init --cri-socket unix:///var/run/singularity.sock --pod-network-cidr=10.92.0.0/16
コマンドが正常に終了すればワーカで実行すべきコマンド例が出るのでメモします。
> kubeadm join 192.168.X.Y:6443 --token 111aaa.9999xxxxxxx \
--discovery-token-ca-cert-hash sha256:XXXXXXXXXXXXXXX
Kubectlを利用するためのコンフィグを整備します。これもkubeadm
が正常終了すると出力されます。
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
試しにkubectl get svc
などを叩いてエラー以外が帰って来ることを確認します。
3.3. K8sワーカの構築
マスタで得られたkubeadm join hogehoge
コマンドに--cri-socket unix:///var/run/singularity.sock
を加えて実行します。
kubeadm join 192.168.X.Y:6443 --token 111aaa.9999xxxxxxx \
--discovery-token-ca-cert-hash sha256:XXXXXXXXXXXXXXX \
--cri-socket unix:///var/run/singularity.sock
3.4. CNIの設定
K8s
ではL2 over L3
ネットワーク構築のためにCNI(今回はCalico)を導入する必要があります。CNIを導入することで、現状はkubectl get pod --all-namespaces
を実行するとpending
状態のcoredns
も有効になります。
通常はCNI導入はkubectl
コマンド一発で入る場合が多いのですが、今回の環境ではCNIが利用するいくつかのパスがインストールに伴い作成されずCNIが立ち上がりませんでした。そこで以下のコマンドを先にマスタ
とワーカ
の両方で実行しておきます。
sudo mkdir -p /var/lib/cni/networks && \
sudo mkdir -p /ect/cni/net.d && \
sudo mkdir -p /var/lib/calico && \
sudo mkdir -p /run/calico && \
sudo touch /var/lib/calico/nodename
また、マスタとワーカの両方でHostname
の設定も/etc/hostname
と/etc/hosts
でなされているか確認します。
特に/etc/hosts
では以下のようにします。
127.0.0.1 localhost.localdomain localhost
127.0.1.1 YOUR_HOSTNAME # 適宜ホスト名に変更
最後にCalico
をインストールします。
kubectl apply -f https://docs.projectcalico.org/v3.8/manifests/calico.yaml
Calico
やCoreDNS
コンテナが起動しない場合は、kubectl logs SOME_POD_NAME
やkubectl describe pod SOME_POD_NAME
で原因を追求して対応します。コンテナイメージがPull
できない場合にはCalico
コンテナやCoreDNS
のlogや各ノードのJournal
を参照してコンテナ利用するパスの有無や権限を適宜変更します。
以上の手順を実行すると、Slurm
コマンドであるsinfo
と、kubernetes
コマンドであるkubectl
が同居した環境を構築できます。
使ってみる
Slurm with Singularity
このサイトを参考にSingularityコンテナをSlurmから実行してみましょう。コマンドはマスタサーバから実行しています。
まずは利用可能なSlurmのパーティションを確認します。
sinfo
> PARTITION AVAIL TIMELIMIT NODES STATE NODELIST
debug* up infinite 1 idle koba-slurm2
debug
という名前のidle
状態のパーティションがワーカノードに割り当てられていることがわかります。次にSlurmのジョブスクリプトsingularity.sbatch
を定義します。上の参考サイトのスクリプトについて、パーティション#SBATCH -p
と実行するsingularityコマンド
を改変しています。
#!/bin/bash
#SBATCH -J singularity_test
#SBATCH -o singularity_test.out
#SBATCH -e singularity_test.err
#SBATCH -p shared
#SBATCH -t 0-00:30
#SBATCH -N 1
#SBATCH -c 1
#SBATCH --mem=4000
# Singularity command line options
singularity pull --name hello-world.sif shub://vsoch/hello-world
singularity exec hello-world.sif cat /etc/os-release
実行してみます。
sbatch singularity.sbatch
結果をNFSなどに出していない場合、ジョブが実行されたノード上に出るのでワーカノードにログインしてホームディレクトリを見るとsingularity_test.out
とsingularity_test.err
があります。
Slurm
によるジョブ制御とSingularity
のコンテナ実行が連携できていることがわかります。
Kubernetes with Singularity
K8sについてはSycri
のユーザドキュメント 7.1.を参考にしてみましょう。
こちらもマスタノードで実行します。
これまでの手順を行うとサーバ上にSycri
のGitレポジトリクローンがあると思います。リポジトリのexample/k8s/hello-kubernetes.yaml
を利用します。
kubectl apply -f examples/k8s/hello-kuberentes.yaml
kubectl get pod
# > hello-kubernetes-8764bc78f-86t2x 1/1 Running 0 2m10s
# > hello-kubernetes-8764bc78f-nq2pb 1/1 Running 0 2m10s
# > hello-kubernetes-8764bc78f-xjrxx 1/1 Running 0 2m9s
kubectl get svc
でサービス公開されたポートを確認し叩いてみるとサービスが提供できていることがわかります。
curl koba-slurm2:SOME_PORT
# > Hello, World!
まとめ
以上の手順でSlurm
とKubernetes
がSingularity
のワークロード実行可能な環境を構築できました。
現状はこのような実行環境のユースケースは少ないと思いますが、将来的にHPCWireの記事で期待されているような新しいAIワークロード
のニーズが生まれるかもしれませんし、
その際には単なる同居ではなくHPCジョブスケジューラとKubernetes双方のジョブスケジューリングを統合する機能
が必要になる可能性があります。
Sylabs
のGitHub/WLM Operatorとみなすこともできるかもしれませんね。
今後の関連動向についても引き続き情報発信をしていきたいと思います。