はじめに
こんにちは、(株)日立製作所 研究開発グループ サービスコンピューティング研究部の小林です。
本日のアドベントカレンダーは、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とみなすこともできるかもしれませんね。
今後の関連動向についても引き続き情報発信をしていきたいと思います。