[Kubecon EU 2024: Cloud Native AI Day] Pods Everywhere! InterLink: A Virtual Kubelet Abstraction Streamlining HPC Resource Exploitation の紹介
はじめに
INFNというイタリア国立核物理学研究所のメンバーであるディエゴさんが、「パブリッククラウド、オンプレミスの異種シミュレーション環境において、インターフェースの統一を目的としたプロジェクト」の紹介をするセッションになります。要素技術として、Kubernetes、Virtual Kubelet が登場します。
本ブログではセッションの中身とそこで紹介されるオープンソースのソフトウェアを少し深掘りたいと思います。
対象読者はHPCなどの文脈でジョブコントローラー (ex: Slurm, OpenPBS, HPCPacks) 等を利用されている方、Virtual Kubelet に興味がある方等におすすめしたいセッションになります。
自己紹介
3-shake Sreake 事業部の tozastation です。業務では Kubernetes を中心とした技術支援をしており、CNCF Projects への貢献を個人的目標としております。Kubecon in Paris では現地参加していました!
Github: https://github.com/tozastation
Linkedin: https://www.linkedin.com/in/tozastation/
セッション概要
セッション名
[Kubecon EU 2024: Cloud Native AI Day] Pods Everywhere! InterLink: A Virtual Kubelet Abstraction Streamlining HPC Resource Exploitation(※ Co-located Events の Cloud Native AI Day のセッションになります)
スピーカー
Diego Ciangottiniさん, INFN所属
Sched (イベントページ) リンク
概要訳
Kubernetes APIは宣言型プリミティブの柔軟性により幅広い環境でのワークフローを可能にし、多くの科学的分野で重要な資産となっています。同じAPIを使いながら、外部のハードウェアアクセラレータ搭載マシンにシームレスにアクセスできたらどうでしょうか?これはまさにゲームチェンジャーになるでしょう。interLinkプロジェクトはまさにそのもので、Virtual-Kubeletという概念のオープンソース拡張です。これは、EUが資金提供する科学のためのデジタルツインプラットフォーム構築を目指すプロジェクトinterTwinと、イタリアにある国立高等性能計算、ビッグデータ、量子コンピューティング研究センターであるICSCによって開発されました。ここでは、Kubernetesベースのコンピューティングプラットフォームが、異種プロバイダー上で計算能力を拡張できるという、その主要機能と初期ユースケースについて説明します。具体的には、EuroHPC Vegaのような世界クラスのスーパーコンピュータとの統合が紹介される予定です。
セッション内容へのアクセス
https://static.sched.com/hosted_files/colocatedeventseu2024/8b/Kubecon-AI-day-24.pdf
Youtube Archive
セッション解説
用語補足
スライドに登場する専門用語の補足になります。適宜ご参照ください。
用語 | 説明 |
INFN | 国立核物理研究所 (INFN) は、イタリアの研究機関であり、文部科学研究省 (MIUR) の監督の下、物質の基礎構造要素とその法則の研究に専念しています。素核、原子核、宇宙素粒子物理学の分野で理論と実験の研究を行っています。 ref: https://home.infn.it/en/the-institute |
ICSC (Centro Nazionale di Recerca in HPC, Big Data and Quantum Computing) | このセンターは、ハイパフォーマンスコンピューティング、シミュレーション、ビッグデータ分析の革新に向けた、国内外の研究開発を行っています。この目的は、既存のリソースを活用し新興技術を統合した最先端のハイパフォーマンスコンピューティングとビッグデータ管理のためのインフラ、そしてハブアンドスポークモデルに基づいた活動の組織化と分配を通じて追求されます。 ref: https://www.supercomputing-icsc.it/en/icsc-home/ |
interTwin | interTwinは、学際的なデジタルツインエンジン (DTE) のプロトタイプを共同設計・実装します。DTE はオープンソースのプラットフォームで、オープンスタンダードを採用しており、アプリケーション固有のデジタルツイン (DT) との統合機能を提供します。その機能仕様と実装は、共同設計された相互運用フレームワークと研究用 DT の概念モデル、つまり DTE ブループリントアーキテクチャに基づいています。interTwin の野望は、DT の実装に関する共通アプローチについて科学分野全体で合意を形成することであり、異なる DT 間の開発と相互運用を促進することです。 ref: https://www.intertwin.eu/about-intertwin/ |
DigitalTwin | デジタルツインは、サイバーフィジカルシステム(CPS:Cyber Physical System)の一つの形態であり、高度な計測・観測により現実世界の中から収集されたデジタルデータを基に物理的な製品やサービスをサイバー空間上で仮想的に複製し、将来起こり得る様々な事象を予測可能にするシミュレーション技術である。 ref: https://www.jst.go.jp/crds/pdf/2021/RR/CRDS-FY2021-RR-09.pdf |
interLink | InterLinkは、コンテナ実行ライフサイクルを管理できる任意のリモートリソース上で、Kubernetes Pod の実行を抽象化する機能を提供します。プロバイダー固有のプラグイン開発を容易にし、リソースプロバイダーは、Kubernetes 内部構造のエキスパートでなくても、仮想 kubelet のパワーを活用できるようにすることを目指しています。 プロジェクトは主に以下の2つから構成されます。 – Kubernetes 仮想ノード: VirtualKubelet テクノロジーを採用しており、Kubernetes Pod 実行要求を、interLink API サーバーへのリモートコールに変換します。 – interLink API サーバー: モジュール式でプラグイン可能な REST サーバーであり、独自のコンテナマネージャー プラグイン (サイドカーと呼ばれる) を作成したり、既存のもの (リモートホストでのリモート Docker 実行、リモート Slurm バッチシステムでの Singularity コンテナなど) を使用できます。 このプロジェクトは、KNoC と Liqo プロジェクトに触発され、仮想 kubelet コンポーネントとプロバイダー側のコントナーライフサイクル管理ロジック間の汎用 API レイヤーを実装することで、機能を強化しています。 ref: https://github.com/interTwin-eu/interLink |
Slurm (Simple Linux Utility for Resource Management) | Slurm は、大規模・小規模の Linux クラスター向けのオープンソースで、フォールトトレラント (耐障害性) で、スケーラビリティが高いクラスター管理およびジョブスケジューリングシステムです。Slurm は動作にカーネル修正を必要とせず、比較的独立しています。クラスターワークロードマネージャーとして、Slurm には 3 つの主要な機能があります。 – リソースの割り当て: ユーザーが作業を実行できるように、一定時間リソース (計算ノード) への排他的または非排他的アクセスを割り当てます。 – ジョブの実行: 割り当てられたノードセットで作業 (通常は並列ジョブ) を開始、実行、監視するためのフレームワークを提供します。 – リソース競合の調停: 保留中の作業のキューを管理することにより、リソースの競合を調停します。 ref: https://slurm.schedmd.com/overview.html |
HTCondor | HTCondorは、計算集約型ジョブのための専用のワークロード管理システムです。他のフル機能バッチシステムと同様に、HTCondorはジョブキューイングメカニズム、スケジューリングポリシー、優先順位スキーム、リソース監視、リソース管理を提供します。 ref: https://htcondor.org/description.html |
Virtual Kubelet | Virtual Kubelet は、Kubernetes クラスタを他の API に接続させる目的で、Kubernetes の kubelet として振る舞う実装です。これにより、Kubernetes ノードは、従来の仮想マシンではなく、サーバーレスコンテナプラットフォームなどの別のサービスによって裏付けられるようになります。 対応する Providers 一部例: – Admiralty Multi-Cluster Scheduler – Alibaba Cloud Elastic Container Instance (ECI) – AWS Fargate – Azure Batch – Azure Container Instances (ACI) – Kubernetes Container Runtime Interface (CRI) ref: https://virtual-kubelet.io/docs/ |
Apptainer (昔の名前→Singularity) | Apptainer はコンテナプラットフォームです。Apptainer は、HPC クラスター上で複雑なアプリケーションをシンプルかつ移植性・再現性をもって実行できるようにするために開発されました。当初はローレンス・バークレー国立研究所で開発されましたが、その後、他の HPC 施設や学術機関などにも急速に普及しました。 ref: https://apptainer.org/docs/user/latest/introduction.html |
導入
組織背景
INFN (イタリア国立核物理学研究所) や ICSC (高性能コンピューティング、ビッグデータ、量子コンピューティング研究センター) には異なる研究領域、数十から数千人規模のドメインが存在する。また地理的に分散された様々な環境(スパコン・クラウド等)があり、ハードウェアも異なる。
そのような中で interTwin が発足し、その目的は 「異なるDT間の開発および相互運用性を促進する、科学分野の全領域に適用可能なDT実装の共通アプローチに関するコンセンサスを形成することです」であり、クラウドネイティブフレームワークとデータセンター(HPC)との統合がより強く求められている。
目的
単一の API 仕様で、これらの異種環境を管理できるようにしたい。
課題
私たちの組織では、コンテナを採用している。コンテナを実行するインフラ (Docker, Apptainer (旧 Singularity), etc) も用意している。ほとんどの今後の科学フレームワークにとって、Kubernetes APIは優れた基盤となる可能性を秘めている。しかし、Slurm , HTCondor 等バッチシステムは Kubernetes に対応していないという課題がある。
解決策として、Virtual Kubelet の利用を検討。先行プロジェクトとして、KNoC (A Kubernetes Node to manage container lifecycle on HPC clusters) の利用を開始し以下の結果がわかりました。
Wows (良い点)
Singularity/Apptainer コンテナを使用し、Slurm ジョブで実行されたリモートホスト上で、コンテナ化された分析ワークフローの実行に成功
Mehs (課題)
Virtual Kubelet のプロバイダー管理者の必須スキルとして Kubernetes の高度な専門知識 (Kubernetes black belt) を要求してしまうこと
上記を踏まえての新たな目的
プロバイダーに依存せず、Kubernetes 関連ロジックを一度記述するだけで全てのプロバイダーに対応できるようにしつつ、Virtual Kubelet の作成プロセスを効率化し、あらゆるリモートリソースプロバイダーへのエコシステム拡張の障壁を下げることを目指したい。
interLinkプロジェクトの発足
構想
- バーチャルノード内部を管理するためのコアコンポーネントを定義
- リモートエンドポイントへの HTTPリクエストの実行によるコンテナ管理
- interLink プラグイン API 仕様に準拠すれば、どのプログラミング言語でも利用可能
現在の制約事項
- intra-cluster network (クラスタIP) への依存は避ける必要がある
- コンテナ同士は同じ Kubernetes クラスタ内に存在するとは限らないため、クラスタIP アドレスに依存した通信は機能しない
- 利用可能なボリュームは ConfigMap, Secrets, emptyDir のみ
https://github.com/interTwin-eu/interLink
interLink のアーキテクチャ
ref: https://intertwin-eu.github.io/interLink/docs/intro
コンポーネントは、「Virtual Kubelet」「interLink API Server」「Provider Plugins」の3つ Virtual Kubelet, InterLink API Server を利用し、Kubernetes のリソースと Remote Host (Docker, Slurm, HTCondor etc…) を紐付けている
裏側で Pod を Docker コンテナや Slurm / HTCondor のジョブに置き換えているイメージ
Virtual Kubelet
Virtual Kubelet (VK) は、あたかも実際のノードであるかのように Kubernetes クラスタを欺くコンポーネントです。
以下のインターフェースを満たすことで利用できます
// PodLifecycleHandler defines the interface used by the PodController to react
// to new and changed pods scheduled to the node that is being managed.
//
// Errors produced by these methods should implement an interface from
// github.com/virtual-kubelet/virtual-kubelet/errdefs package in order for the
// core logic to be able to understand the type of failure.
type PodLifecycleHandler interface {
// CreatePod takes a Kubernetes Pod and deploys it within the provider.
CreatePod(ctx context.Context, pod *corev1.Pod) error
// UpdatePod takes a Kubernetes Pod and updates it within the provider.
UpdatePod(ctx context.Context, pod *corev1.Pod) error
// DeletePod takes a Kubernetes Pod and deletes it from the provider.
DeletePod(ctx context.Context, pod *corev1.Pod) error
// GetPod retrieves a pod by name from the provider (can be cached).
// The Pod returned is expected to be immutable, and may be accessed
// concurrently outside of the calling goroutine. Therefore it is recommended
// to return a version after DeepCopy.
GetPod(ctx context.Context, namespace, name string) (*corev1.Pod, error)
// GetPodStatus retrieves the status of a pod by name from the provider.
// The PodStatus returned is expected to be immutable, and may be accessed
// concurrently outside of the calling goroutine. Therefore it is recommended
// to return a version after DeepCopy.
GetPodStatus(ctx context.Context, namespace, name string) (*corev1.PodStatus, error)
// GetPods retrieves a list of all pods running on the provider (can be cached).
// The Pods returned are expected to be immutable, and may be accessed
// concurrently outside of the calling goroutine. Therefore it is recommended
// to return a version after DeepCopy.
GetPods(context.Context) ([]*corev1.Pod, error)
}
ref: https://pkg.go.dev/github.com/virtual-kubelet/virtual-kubelet/node#PodLifecycleHandler
InterLink では、Virtual Kubelet はこのインターフェースで InterLink API Server にメッセージを送信し、実際のコンテナ実行をリモートリソースプロバイダーに依頼します。
InterLink API Server
Virtual Kubelet が求めるリモートでのコンテナ実行を実現するために、Virtual Kubelet とプロバイダープラグイン (ex: Docker, Slurm, HTCondor) の間に立ち連携するコンポーネントです。
Provider plugins
interLink API サーバーの指示に従ってリモートリソース上でコンテナを実行するコンポーネントです。
利用状況
EUROのHPC (HPC Vega, JSC (Jülich Supercomputing Centre (JSC))) で利用が開始されています。
両方のケース (HPC VegaとJSC) で、ジョブは HPC のエッジにある VM 上で動作する interLink プラグインによって Slurm に送信されます。 Quick Start もあり、Local 環境で interLink を試すこともできます。
Quick-start: local environment | interLink
まとめ
※ セッションのまとめでブログはまだ続きます
interLink は、Virtual Kubelet を利用し、Slurm のようなバッチシステムを Kubernetes で管理するプロジェクトです。特徴としては、チームが Kubernetes 本体に触れずにバッチシステムとの連携をできるよう interLink が Kubernetes と バッチシステムの仲介を行っていることです。これにより interLink の WebAPI 仕様を満たしていればどの言語でも実装可能にしています。
interLink は、コンテナベースのリソースプロビジョニングモデルをあらゆるユースケースに拡張できると考えています。 HPC は始まりに過ぎません。HPCはあくまでも一例であり、他にも様々なユースケースが想定されます。
INFNでは、既存のユーザーサービスを拡張するための interLink の活用が検討されています。
- CMS 実験解析施設での研究開発 (R&D)
- ICSC による Spoke2/3 向けの高速分析インフラ構築
- ICSC 量子コンピューティングリソースへのクラウドアクセス
興味がある場合はこちらの Slack に参加してねと最後に…!
Slack
interLink を深ぼってみる
番外編です。特にリモートリソース実行との繋ぎ込みについて、実際にどのように実装されているか気になります。せっかくGithub に公開されているので覗いてみましょう。
該当ソースはこちら
https://github.com/interTwin-eu/interLink
以下のような疑問が解消できたらなと思っています
- ConfigMap, Secrets 等は Slurm ではどのように扱っているのか。それ以外の選択肢はあるのか。
- pod.yaml はどう書けばいいのかまたどのようにして Slurm のインターフェースに変換されるのか
Provider plugins の仕様について
API 仕様
プロジェクト内では Provider Sidecar と定義されています。 (※ Sidecar は interLink 内では、コンテナ管理プラグインのことを指します) こちらに Provider plugins が満たすべき API 仕様が定義されています。
該当ソースはこちら
interLink/docs/openapi/openapi.json at main · interTwin-eu/interLink
以下は Swagger API のスクリーンショットですが、4つのエンドポイントがあります。Provider plugins はこれを満たしてあげれば良さそうです。
/create
/delete
/status
/getLogs
Provider plugins の実装
Github リポジトリの ./cmd/sidecars
を見ると、4つ確認できます。
- docker
- htcondor
- slurm
- unicore
サンプルの Kubernetes マニフェストを追う
interLink と Slurm の Example が提供されているので、実際にどのようなマニフェストを適用しているのかコードを読む前に見てみましょう。
該当ソースはこちら
interLink/examples/interlink-slurm at main · interTwin-eu/interLink
test_pod.yaml (./examples/interlink-slurm/test_pod.yaml)
特徴
- annotations
- Slurm コマンドの引数を渡しているかのような定義
- restartPolicy
- 1度きりの実行である Never を指定 Job(batch/v1) からの実行を想定していると思われる?Deployment (apps/v1) のサンプルもある模様)
- tolerations
- interLink 対応の Virtual Kubelet のいるノードにスケジュール許可を定義
apiVersion: v1
kind: Pod
metadata:
name: test-pod-cowsay
namespace: vk
annotations:
slurm-job.knoc.io/flags: "--job-name=test-pod-cfg -t 2800 --ntasks=8 --nodes=1 --mem-per-cpu=2000"
spec:
restartPolicy: Never
containers:
- image: docker://ghcr.io/grycap/cowsay
command: ["/bin/sh"]
args: ["-c", "\"touch /tmp/test.txt && sleep 60 && echo \\\"hello muu\\\" | /usr/games/cowsay \" " ]
imagePullPolicy: Always
name: cowsayo
dnsPolicy: ClusterFirst
nodeSelector:
kubernetes.io/hostname: test-vk
tolerations:
- key: virtual-node.interlink/no-schedule
operator: Exists
このマニフェストが Slurm で実際どのように実行されるのか
今回は Slurm (./cmd/sidecars/slurm/main.go
) を見ていきましょう。
該当ソースはこちら
interLink/cmd/sidecars/slurm/main.go at main · interTwin-eu/interLink
Provider plugins (Slurm) のエントリーポイントを追う
slurm.go でやっていること (※ 抜粋)
- InterLinkConfig の読み込み
- JobIDs の map 変数定義
- 先ほどの API 仕様をみたす HTTP サーバのルート設定
- Slurm 用ディレクトリの作成
- Slurm の JobID 読み込み
- HTTP サーバの起動
(1) InterLinkConfig の設定
以下の値が、Provider plugins の共通設定として定義されており、YAML ファイルから読み込めるそうです。
該当ソースはこちら
interLink/pkg/common/types.go at main · interTwin-eu/interLink
Slurm のサンプルディレクトリ (./examples/interlink-slurm/vk/InterLinkConfig.yaml
) では、以下の Config が実際に設定されていました。サンプルでは、このコンフィグは interLink と Virtual Kubelet、Provider Plugins で参照されています。
ここには、Slurm のコマンドのパスも設定されていそうです。
sbatch | ジョブ投入コマンド |
scancel | ジョブキャンセルコマンド |
squeue | ジョブ実行状況確認コマンド |
VKTokenFile: "$HOME/interLink/token"
InterlinkURL: "http://XXX.XXX.XXX.XXX"
SidecarURL: "http://docker-sidecar"
InterlinkPort: "3000"
SidecarPort: "4000"
SbatchPath: "/usr/bin/sbatch"
ScancelPath: "/usr/bin/scancel"
SqueuePath: "/usr/bin/squeue"
CommandPrefix: ""
ExportPodData: true
DataRootFolder: ".local/interlink/jobs/"
ServiceAccount: "interlink"
Namespace: "vk"
Tsocks: false
BashPath: /bin/bash
VerboseLogging: true
ErrorsOnlyLogging: false
(2) JobIDs の map 変数定義
「(2-d) Slurm ジョブの実行 (JobIDを格納するファイルとJobID を構造体に読み込み)」にて改めて登場しますが、ジョブ作成時に JobID をファイル書き込みしており、Provider Plugins の起動時にその情報を取得し、ジョブ のステータスを返すのに WebAPI 内で利用しています。
該当ソースはこちら
interLink/cmd/sidecars/slurm/main.go at main · interTwin-eu/interLink
(3) 先ほどの WebAPI 仕様をみたす HTTP サーバのルート設定
先ほど見た WebAPI 仕様の実装がありました。 中身の実装は
./pkg/sidecars/slurm
に集約されているようです。
mutex.HandleFunc("/status", SidecarAPIs.StatusHandler)
mutex.HandleFunc("/create", SidecarAPIs.SubmitHandler)
mutex.HandleFunc("/delete", SidecarAPIs.StopHandler)
mutex.HandleFunc("/getLogs", SidecarAPIs.GetLogsHandler)
(4) Slurm 用ディレクトリの作成
InterLinkConfig で指定した DataRootFolder
が存在するか確認し無ければ作成します。
該当ソースはこちら
interLink/pkg/sidecars/slurm/aux.go at main · interTwin-eu/interLink
InterLinkConfig では、 DataRootFolder:".local/interlink/jobs/"
と設定されていました。
このフォルダ配下では、Slurm で作成されたジョブの情報 (ID,タイムスタンプ) 、ログがファイルとして実際に作成されます。
root@b224e477c6be:~# ls -la .local/interlink/jobs/vk-82e6b027-f25e-4b63-8eca-af14c1b40782/
total 28
drwxr-xr-x 2 root root 4096 Apr 1 08:03 .
drwxr-xr-x 3 root root 4096 Apr 1 08:03 ..
-rw-r--r-- 1 root root 39 Apr 1 08:03 FinishedAt.time
-rw-r--r-- 1 root root 1 Apr 1 08:03 JobID.jid
-rw-r--r-- 1 root root 200 Apr 1 08:03 cowsayo.out
-rw-r--r-- 1 root root 4 Apr 1 08:03 cowsayo.status
-rw-r--r-- 1 root root 0 Apr 1 08:03 job.out
-rwxrwxr-- 1 root root 472 Apr 1 08:03 job.sh
Provider Plugins (Slurm) のログからも作成される様子が伺えます。
docker-sidecar-1 | time="2024-04-01T08:03:44-04:00" level=info msg="- Beginning script generation for container cowsayo"
docker-sidecar-1 | time="2024-04-01T08:03:44-04:00" level=info msg="-- Preparing mountpoints for cowsayo"
docker-sidecar-1 | time="2024-04-01T08:03:44-04:00" level=info msg="-- Created directory .local/interlink/jobs/vk-82e6b027-f25e-4b63-8eca-af14c1b40782"
docker-sidecar-1 | time="2024-04-01T08:03:44-04:00" level=debug msg="[]"
docker-sidecar-1 | time="2024-04-01T08:03:44-04:00" level=debug msg="-- Appending all commands together..."
docker-sidecar-1 | time="2024-04-01T08:03:44-04:00" level=info msg="-- Creating file for the Slurm script"
docker-sidecar-1 | time="2024-04-01T08:03:44-04:00" level=info msg="-- Created directory .local/interlink/jobs/vk-82e6b027-f25e-4b63-8eca-af14c1b40782"
docker-sidecar-1 | time="2024-04-01T08:03:44-04:00" level=debug msg="--- Created file .local/interlink/jobs/vk-82e6b027-f25e-4b63-8eca-af14c1b40782/job.sh"
docker-sidecar-1 | time="2024-04-01T08:03:44-04:00" level=debug msg="--- Writing file"
docker-sidecar-1 | time="2024-04-01T08:03:44-04:00" level=debug msg="---- Written file"
docker-sidecar-1 | time="2024-04-01T08:03:44-04:00" level=info msg="- Submitting Slurm job"
docker-sidecar-1 | time="2024-04-01T08:03:44-04:00" level=debug msg="Job submitted"
docker-sidecar-1 | time="2024-04-01T08:03:44-04:00" level=info msg="Submitted batch job 3"
docker-sidecar-1 | time="2024-04-01T08:03:44-04:00" level=info msg="Job ID is: 3"
(5) Slurm の JobID 読み込み
コメントアウトがありました。起動時に現在のジョブの状況を収集するようです。
ルートフォルダにあるファイルからジョブIDを読み込み、メインの JIDs 構造体に格納
ファイル読み込みしている箇所
- JobID の読み込み
- os.ReadFile(path + entry.Name() + “/” + “JobID.jid”)
- 起動時間の読み込み
- os.ReadFile(path + entry.Name() + “/” + “StartedAt.time”)
- 終了時間の読み込み
- os.ReadFile(path + entry.Name() + “/” + “FinishedAt.time”)
該当ソースはこちら
interLink/pkg/sidecars/slurm/aux.go at main · interTwin-eu/interLink
Provider plugins (Slurm) の Create.go を追う
せっかくなので、Provider plugins が Slurm とどのようにやり取りして、ジョブを実行しているか Create.go を例に見てみましょう。
該当ソースはこちら
interLink/pkg/sidecars/slurm/Create.go at main · interTwin-eu/interLink
ここで、少し読み込むと Slurm だけでなく、Singularity という用語も出てきますが、Singularity は HPC向けのコンテナランタイムで、Slurm は OCI 準拠のコンテナランタイムと連携することができます。
ref: https://slurm.schedmd.com/containers.html
SubmitHandler でやっていること
- HTTPリクエストの読み込み
- Slurm ジョブの実行
- singularity コマンドの組み立て
- Slurm Script の組み立て
- Slurm Batch の登録
- JobIDを格納するファイルとJobID を構造体に読み込み
(1) HTTPリクエストの読み込み
ここでは、Virtual Kubelet → interLink API を経由して /create
のリクエストでは以下を受け取ります。v1.Pod はお馴染みの Kubernetes の CoreAPI (k8s.io/api/core/v1
) を指します。
受け取るリクエストのソースはこちら
interLink/pkg/common/types.go at main · interTwin-eu/interLink
(2-a) Slurm ジョブの実行 (singularity コマンドの組み立て)
ここでは、singularity コマンドの組み立てとコンテナの実行に必要なボリュームの準備を行います。
Pod の Annotations からリモート環境固有のパラメータを渡す
job.vk.io/singularity-commands
(※ 定義はされるが利用されていない)job.vk.io/singularity-mounts
job.vk.io/singularity-options
最終的に以下のような apptainer (singularity) コマンドを組み立てる
ファイルマウントと Nvidia GPU の有効化を行い、先ほどのパラメータを追加しています。
[]string{
"singularity",
"exec",
"--containall",
"--nv",
singularityMounts,
singularityOptions,
}
Pod が利用する ConfigMaps, Secrets, EmptyDir の情報から、ディレクトリ、ファイルもしくは環境変数を作成 (prepareMounts)
該当ソースはこちら
interLink/pkg/sidecars/slurm/aux.go at main · interTwin-eu/interLink
- h.Config.DataRootFolder + data.Pod.Namespace + “-” + string(data.Pod.UID) を filesPath と定義
- ConfigMaps, Secrets, EmptyDir の指定があった場合は、フォルダを作成
- SHARED_FS が true の場合、ホストに直接ファイルを作成
- SHARED_FS が false に場合、実値を環境変数としてコンテナに渡す
- ConfigMap: ${コンテナ名}_CFG_${キー名}
- Secret: ${コンテナ名}_SECRET_${キー名}
- 環境変数の場合は、Singularity コマンドの Prefix として、特定パスに実値を書き込むコマンドが渡される
書き込まれる先の例: filesPath[0]/configMaps/vol.name/key
prefix += "\nmkdir -p " + dir
prefix += " && touch " + dirs[0]
prefix += " && echo $" + envs[i] + " > " + dirs[0]
このようなフローを経て、リモート環境のコンテナからファイルとして参照できるようになります。
(2-b) Slurm ジョブの実行 (Slurm Script の組み立て)
実際に Slurm の環境で実行するシェルスクリプトを組み立てます。 組み立てでは、先ほど作成した Singularity コマンド、Prefix (前処理) 等が記載されています。
該当ソースはこちら
interLink/pkg/sidecars/slurm/aux.go at main · interTwin-eu/interLink
Pod の Annotations から SBATCHのフラグや前処理のパラメータを渡す
slurm-job.vk.io/flags
- SBATCH コマンドのフラグを定義
slurm-job.vk.io/mpi-flags
- singularity コマンドに mpiexec を追加
job.vk.io/pre-exec
- singularity コマンド実行前の任意のスクリプトを定義
実際に組み立てられる Shell Script
root@b224e477c6be:~# cat .local/interlink/jobs/vk-82e6b027-f25e-4b63-8eca-af14c1b40782/job.sh
#!/bin/bash
#SBATCH --job-name=82e6b027-f25e-4b63-8eca-af14c1b40782
#SBATCH --output=.local/interlink/jobs/vk-82e6b027-f25e-4b63-8eca-af14c1b40782/job.out
singularity exec \
--containall \
--nv \
ghcr.io/grycap/cowsay /bin/sh -c "touch /tmp/test.txt && sleep 60 && echo \"hello muu\" | /usr/games/cowsay " &> .local/interlink/jobs/vk-82e6b027-f25e-4b63-8eca-af14c1b40782/cowsayo.out; echo $? > .local/interlink/jobs/vk-82e6b027-f25e-4b63-8eca-af14c1b40782/cowsayo.status &
(2-c) Slurm ジョブの実行 (Slurm Batch の登録)
先ほど作成した job.sh の実行します
sh -c "SBATCH ./job.sh"
該当ソースはこちら
interLink/pkg/sidecars/slurm/Create.go at main · interTwin-eu/interLink
(2-d) Slurm ジョブの実行 (JobIDを格納するファイルとJobID を構造体に読み込み)
$PATH/JobID.jid
に、Slurm で払い出される JobID が書き込まれます
ここでは詳しくあげませんが、 ./pkg/sidecars/slurm/Status.go
ではこのファイルから JobID を読み込み squeue コマンドを実行し情報を得るなどで利用されています。
該当ソースはこちら
interLink/pkg/sidecars/slurm/Status.go at main · interTwin-eu/interLink
以上になります。
まとめ
本セッションと調査を通して、interLink プロジェクトについて、Virtual Kubelet とは何か、interLinkでバッチスケジューラーと連携するには実際どのような実装になっているかなど一緒に追えましたでしょうか。
この他にも HPC や バッチスケジュールの分野にて、「volcano」「kueue」「Ray」等の Kubernetes 向けに機能が提供されているプロジェクトも紹介されていました。以下セッション名になります。
- Cloud Native AI Day – Scale Your Batch / Big Data / AI Workloads Beyond the Kubernetes Scheduler – Antonin Stefanutti & Anish Asthana, Red Hat
- Data on Kubernetes Day – Advanced CSI-FUSE Filesystem for AI/ML Data Management in Kubernetes – Lu Qiu, Alluxio
また、別枠ですが
- Introducing SUNK: A Slurm on Kubernetes Implementation for HPC and Large Scale AI
というタイトルで、SUNK = Slurm on Kubernetes という Slurm を Kubernetes スケジューラーとして統合するプロジェクトもあるそうです。2024年に OSS公開を検討中とのこと。
Kubecon EU 2024 では、LLM, AI/ML などがテーマとして多い印象を受けました。
今後も Kubernetes での HPC, バッチ領域 の情報をキャッチアップし発信をしていけたらと思います。