Kueueの概要については、前編にまとめています。
Kubernetes GPU + Kueue セットアップ手順書(Kueue入門 + Workload Lifecycle)
このドキュメントは GPUを搭載したKubernetesクラスタでGPUを利用し、Kueueを使ってジョブの順番実行(キューイング)と admission 制御を試す最小構成を説明する入門ガイドです。
Kueueは色々な環境に組み込んで利用できますが、本資料ではまず Kubernetes + GPU + Kueue の最小構成を構築し、Kueueの基本動作を理解することを目的としています。
なお環境構築は管理者権限でという前提で構築しているため、sudoをつかわない手順でセットアップしています。
想定環境
今回は基本的にこの構成を前提としてますが、適切なGPU Driverがインストール済みであればOSやバージョンは問いません。
- Ubuntu Server 24.04
- NVIDIA GPU 1枚
- Kubernetes 1.29以上
- CRI: containerd runtime
- CNI: Flannel
なお、今回の記事の中編ではKubernetesとKueueを使うのを前提としています。後編ではKubeflowと連携した内容になる予定です。
Kueueのアーキテクチャ
重要なポイント
Kueueは Kubernetes Schedulerではありません。 Kueueの役割は「このJobを今実行してよいか?」を判断する Admission Controller です。
User Job
│
▼
Kueue LocalQueue
│
▼
ClusterQueue admission
│
▼
Workload admitted
│
▼
Pod created
│
▼
Kubernetes Scheduler
│
▼
GPU Node
│
▼
GPU Container
Kueueの基本概念
Kueueについて抑えておくべき基本概念は次の通りです。
| リソース | 役割 |
|---|---|
| ResourceFlavor | ノードラベルや taint に紐づくリソース種類 |
| ClusterQueue | クラスタ全体のリソース割当ポリシー |
| LocalQueue | namespace のユーザー入口 |
| Workload | Job の内部表現 |
内部処理の流れは次の通りです。
Job
↓
Workload
↓
ClusterQueue admission
↓
Pod作成
Kueueの内部アーキテクチャ(Workload Lifecycle)
Kueueでは Job を直接スケジュールしません。 Job を Workload オブジェクトに変換して管理します。
Job
│
▼
Workload 作成
│
▼
Queueing
│
▼
Admission 判定
│
▼
Resource Reservation
│
▼
Pod 作成
│
▼
Kubernetes Scheduler
│
▼
Node
何となくわかってきたと思うので、この後から環境を構築していきます。 事前にそれなりのスペックのNVIDIA GPUを実装したサーバーに、Ubuntu Server 24.04をインストールしておきます。
1 GPUドライバのインストール
GPU ノードに NVIDIA ドライバをインストールします。NVIDIAのGPUドライバーはnvidia-driverというパッケージがUbuntu Archivesで提供されています。 今回はそれをインストールします。
$ sudo su - # apt-get update && sudo apt-get install nvidia-driver-590-server-open # reboot
再起動後にコマンドを実行して、GPUとGPU Driverが正常に動作していることを確認します。
# nvidia-smi -L
例
GPU 0: NVIDIA RTX A4000 (UUID: GPU-xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxx)
2 Kubernetes クラスタ準備
すでに Kubernetes クラスタがある場合はスキップしてください。 クラスターはkubeadmを使ってインストールします。
コンテナランタイムはDockerのリポジトリーのcontainerd.ioパッケージを使ってインストールします。Ubuntu Archives版のcontainerdパッケージはバージョンが古く、NVIDIA Container Toolkitを介したGPUスケジューリング周りが思ったように動作しなかったためです。 CNIは何でも構いません。今回は主題ではなかったため、一番単純なFlannelを使いました。
今回はKueueだけを動かすことを前提としたため、Kubernetesはシングルノードで動かしています。いつか、Multikueueも試してみたいですね。
- https://kubernetes.io/ja/docs/setup/production-environment/container-runtimes/
- https://kubernetes.io/ja/docs/setup/production-environment/tools/kubeadm/install-kubeadm/
- https://kubernetes.io/ja/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/
最小構成
- kubeadm
- containerd.io
- kubernetes >= 1.29
構築したKubernetesクラスターの状態とバージョンを確認します。
# kubectl get node NAME STATUS ROLES AGE VERSION node1 Ready control-plane 4d23h v1.35.3
3 NVIDIA Container Toolkit
コンテナからGPUを使えるようにするために、NVIDIA Container Toolkitを導入します。
# apt-get update && sudo apt-get install -y --no-install-recommends \
ca-certificates \
curl \
gnupg2
# curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \
&& curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \
sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
# apt-get update
# export NVIDIA_CONTAINER_TOOLKIT_VERSION=1.19.0-1
# apt-get install -y \
nvidia-container-toolkit=${NVIDIA_CONTAINER_TOOLKIT_VERSION} \
nvidia-container-toolkit-base=${NVIDIA_CONTAINER_TOOLKIT_VERSION} \
libnvidia-container-tools=${NVIDIA_CONTAINER_TOOLKIT_VERSION} \
libnvidia-container1=${NVIDIA_CONTAINER_TOOLKIT_VERSION}
# nvidia-ctk runtime configure --runtime=containerd
# systemctl restart containerd
# systemctl enable containerd
4 NVIDIA Device Plugin
Kubernetes が GPU を認識するために NVIDIA Device Pluginを導入します。
- 公式プロジェクトからK8sのバージョンに適したバージョンを導入
# kubectl create -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/v0.19.0/deployments/static/nvidia-device-plugin.yml
NVIDIA Device Pluginの導入ができたかを確認します。
# kubectl get pods -n kube-system
GPU リソースを確認します。
# kubectl describe node | grep nvidia.com/gpu
NVIDIA Device PluginとNVIDIA GPU Operator
GPUアクセラレーションされたワークロードを実行するためにKubernetesに対してNVIDIA Device PluginとNVIDIA GPU Operatorが使われますが、両者の違いは何でしょうか?どちらか一方だけを使うべきでしょうか、それとも両方を併用できるのでしょうか?
端的に説明すると、Device Pluginはコンテナワークロードのスケジュール設定を可能にするデーモンセットであり、GPUをリソースとして管理するものであり、GPU OperatorはGPUドライバとコンテナランタイムを使用してノードを構成し、Device Pluginをデプロイをするためのものです。今回はGPUドライバーとNVIDIA Device Plugin、NVIDIA Container Toolkitを手動でセットアップしたため、NVIDIA GPU Operatorは使っていませんが、スムーズにセットアップしたいのであればNVIDIA GPU Operatorを使うと良いと思います。
5 GPU Pod テスト
Kueue を使う前に Kubernetes 単体で GPU Podを実行できるか確認します。
apiVersion: v1 kind: Pod metadata: name: gpu-test spec: runtimeClassName: nvidia restartPolicy: Never containers: - name: cuda image: nvidia/cuda:13.0.0-base-ubuntu22.04 command: ["bash","-c","nvidia-smi"] resources: limits: nvidia.com/gpu: 1
このマニフェストを使ってPodを作ってみます。
# kubectl apply -f gpu-test.yaml # kubectl logs gpu-test
GPU 情報が表示されれば成功です。
# kubectl logs gpu-test Wed Apr 1 06:07:51 2026 +-----------------------------------------------------------------------------------------+ | NVIDIA-SMI 590.48.01 Driver Version: 590.48.01 CUDA Version: 13.1 | +-----------------------------------------+------------------------+----------------------+ | GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. | | | | MIG M. | |=========================================+========================+======================| | 0 NVIDIA RTX A4000 Off | 00000000:37:00.0 Off | Off | | 41% 33C P8 10W / 140W | 0MiB / 16376MiB | 0% Default | | | | N/A | +-----------------------------------------+------------------------+----------------------+ +-----------------------------------------------------------------------------------------+ | Processes: | | GPU GI CI PID Type Process name GPU Memory | | ID ID Usage | |=========================================================================================| | No running processes found | +-----------------------------------------------------------------------------------------+
6 Kueue インストール
Kueue のドキュメントに従って、インストールします。いくつかの方法がありますが、今回はマニフェストファイルを使ってインストールします。
# kubectl apply --server-side -f https://github.com/kubernetes-sigs/kueue/releases/download/v0.16.4/manifests.yaml # kubectl wait deploy/kueue-controller-manager -nkueue-system --for=condition=available --timeout=5m
確認してみましょう。
# kubectl get pods -n kueue-system
7 Queue 設定
セットアップしたKueueを使ってQueueを定義してみましょう。
GPUラベルを設定する
ノードアクセラレーターとしてnvidiaを使う設定を加えます。
以下はノード名がnode1の場合の例です。
# kubectl label node node1 accelerator=nvidia
Namespace
ml-jobsという名前空間で作業します。
apiVersion: v1 kind: Namespace metadata: name: ml-jobs
ResourceFlavor
リソースフレーバーを設定します。
apiVersion: kueue.x-k8s.io/v1beta2 kind: ResourceFlavor metadata: name: gpu spec: nodeLabels: accelerator: nvidia
ClusterQueue
ClusterQueueを定義します。
apiVersion: kueue.x-k8s.io/v1beta2 kind: ClusterQueue metadata: name: gpu-clusterqueue spec: namespaceSelector: {} resourceGroups: - coveredResources: ["cpu","memory","nvidia.com/gpu"] flavors: - name: gpu resources: - name: cpu nominalQuota: 8 - name: memory nominalQuota: 32Gi - name: nvidia.com/gpu nominalQuota: 1
LocalQueue
LocalQueueを定義します。
apiVersion: kueue.x-k8s.io/v1beta2 kind: LocalQueue metadata: name: gpu-queue namespace: ml-jobs spec: clusterQueue: gpu-clusterqueue
Queue設定の適用
NamespaceからLocalQueueの設定までをクラスターに適用します。
# kubectl apply -f queue-conf-apply.yaml
8 GPU Job 実行
KueueでQueueを定義したら、GPU Jobを実行してみましょう。 metadata nameをcuda-job1とcuda-job2に変えただけのマニフェストを1つずつ作ってください。
apiVersion: batch/v1 kind: Job metadata: name: cuda-job1 namespace: ml-jobs labels: kueue.x-k8s.io/queue-name: gpu-queue spec: backoffLimit: 0 template: spec: restartPolicy: Never containers: - name: cuda image: nvidia/cuda:13.0.0-base-ubuntu22.04 command: ["bash","-lc","sleep 30; exit 0"] resources: requests: cpu: "1" memory: "1Gi" nvidia.com/gpu: "1" limits: cpu: "1" memory: "1Gi" nvidia.com/gpu: "1"
まずは一つだけ実行して、Jobが動作する事を確認します。
# kubectl apply -f job1.yaml
9 状態確認
JobステータスがCompleteになっていますので、このJobの実行が成功しています。
# kubectl get workloads -n ml-jobs NAME QUEUE RESERVED IN ADMITTED FINISHED AGE job-cuda-job1-581dd gpu-queue gpu-clusterqueue True 5s # kubectl get clusterqueues NAME COHORT PENDING WORKLOADS gpu-clusterqueue 0 # kubectl get localqueues -n ml-jobs NAME CLUSTERQUEUE PENDING WORKLOADS ADMITTED WORKLOADS gpu-queue gpu-clusterqueue 0 1 # kubectl get jobs -n ml-jobs NAME STATUS COMPLETIONS DURATION AGE cuda-job1 Complete 1/1 34s 42s
一度テストしたJobは消しておきます。
# kubectl delete -f job1.yaml job.batch "cuda-job1" deleted from ml-jobs namespace
10 Queue 動作確認
次が本番です。 GPU が1枚の環境で、Jobを2つ実行してみましょう。
# kubectl apply -f job1.yaml -f job2.yaml # kubectl get jobs -n ml-jobs -w
すると、次のように表示されるはずです。
job1 Running job2 Suspended
job1 が終了すると、次のように変化するはずです。
job1 Complete job2 Running
これで、Kueueを使ったKubernetesのQueue制御ができるようになりました。 最終的には次のようになります。
# kubectl get jobs -n ml-jobs -w NAME STATUS COMPLETIONS DURATION AGE cuda-job1 Complete 1/1 7m12s 15m cuda-job2 Running 0/1 4s 4s cuda-job2 Running 0/1 32s 32s cuda-job2 SuccessCriteriaMet 0/1 33s 33s cuda-job2 Complete 1/1 33s 33s # kubectl get jobs -n ml-jobs NAME STATUS COMPLETIONS DURATION AGE cuda-job1 Complete 1/1 7m12s 16m cuda-job2 Complete 1/1 33s 40s
ここまでのまとめ
今回は次の流れで環境構築しました。
- GPU driver
- Kubernetes cluster
- NVIDIA Container Toolkit
- NVIDIA Device Plugin
- GPU Pod テスト
- Kueue インストール
- Queue 設定
- Job 実行
これによりKueueを使って
- GPUジョブの順番待ち
- GPUリソース制御
- Admission 管理
を体験する環境が手元に現れました。 せっかく環境を作ったので、早速使ってみるしかないですね!
PyTorchを用いたMNIST画像分類モデルの訓練Jobの試行
少し実践的なJobをKueueで流してみます。 次のようなマニフェストを作成してJobを流してみましょう。
apiVersion: batch/v1
kind: Job
metadata:
name: pytorch-mnist-fast
namespace: ml-jobs
labels:
kueue.x-k8s.io/queue-name: gpu-queue
spec:
backoffLimit: 0
ttlSecondsAfterFinished: 3600
template:
spec:
restartPolicy: Never
runtimeClassName: nvidia # ここを追加
containers:
- name: pytorch
image: docker.io/kubeflowkatib/pytorch-mnist-gpu:latest
command: ["python", "mnist.py", "--epochs=1", "--batch-size=128"]
resources:
requests:
cpu: "4"
memory: "8Gi"
nvidia.com/gpu: "1"
limits:
cpu: "4"
memory: "8Gi"
nvidia.com/gpu: "1"
# kubectl apply -f pytorch-mnist-fast-test.yaml
- 大きめのイメージを使うため、めっちゃ時間がかかると思います
- GPU処理できる環境では、Train Epochの処理は一瞬で終わります
Using CUDAと出力されている場合は、GPUで処理されます
- Jobを適用後、
kubectl get pods -n ml-jobs -wでPodがRunningになるのを確認 kubectl logs -n ml-jobs -f <pod-name>で訓練ログ(loss/accuracy)を確認
実行例は次のような感じです。CPUモードで動かすと結構時間がかかりますが、Using CUDA(GPU)モードではあっという間でした。
MNISTは「手書き数字の画像データセット」です。機械学習、とくにディープラーニングの入門・動作確認用によく使われます。 今回使ったのはその派生版であるFashionMNISTで、MNISTは手書きの数字を学習させますが、FashionMNISTは服の画像を学習させるものです。
今回はこれをKubernetesとKueue環境で動かすのを試しています。
# kubectl logs -n ml-jobs -f pytorch-mnist-fast-tbtcf
Using CUDA
Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/train-images-idx3-ubyte.gz
Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/train-images-idx3-ubyte.gz to ./data/FashionMNIST/raw/train-images-idx3-ubyte.gz
100%|██████████| 26421880/26421880 [00:04<00:00, 6009176.59it/s]
Extracting ./data/FashionMNIST/raw/train-images-idx3-ubyte.gz to ./data/FashionMNIST/raw
Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/train-labels-idx1-ubyte.gz
Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/train-labels-idx1-ubyte.gz to ./data/FashionMNIST/raw/train-labels-idx1-ubyte.gz
100%|██████████| 29515/29515 [00:00<00:00, 111754.46it/s]
Extracting ./data/FashionMNIST/raw/train-labels-idx1-ubyte.gz to ./data/FashionMNIST/raw
Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/t10k-images-idx3-ubyte.gz
Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/t10k-images-idx3-ubyte.gz to ./data/FashionMNIST/raw/t10k-images-idx3-ubyte.gz
100%|██████████| 4422102/4422102 [00:02<00:00, 2055680.69it/s]
Extracting ./data/FashionMNIST/raw/t10k-images-idx3-ubyte.gz to ./data/FashionMNIST/raw
Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/t10k-labels-idx1-ubyte.gz
Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/t10k-labels-idx1-ubyte.gz to ./data/FashionMNIST/raw/t10k-labels-idx1-ubyte.gz
100%|██████████| 5148/5148 [00:00<00:00, 17163972.17it/s]
Extracting ./data/FashionMNIST/raw/t10k-labels-idx1-ubyte.gz to ./data/FashionMNIST/raw
2026-03-30T06:57:07Z INFO Train Epoch: 1 [0/60000 (0%)] loss=2.3015
2026-03-30T06:57:07Z INFO Train Epoch: 1 [1280/60000 (2%)] loss=2.2863
2026-03-30T06:57:07Z INFO Train Epoch: 1 [2560/60000 (4%)] loss=2.2854
2026-03-30T06:57:08Z INFO Train Epoch: 1 [3840/60000 (6%)] loss=2.2727
2026-03-30T06:57:08Z INFO Train Epoch: 1 [5120/60000 (9%)] loss=2.2693
2026-03-30T06:57:08Z INFO Train Epoch: 1 [6400/60000 (11%)] loss=2.2499
2026-03-30T06:57:08Z INFO Train Epoch: 1 [7680/60000 (13%)] loss=2.2421
2026-03-30T06:57:08Z INFO Train Epoch: 1 [8960/60000 (15%)] loss=2.2029
2026-03-30T06:57:08Z INFO Train Epoch: 1 [10240/60000 (17%)] loss=2.1879
2026-03-30T06:57:08Z INFO Train Epoch: 1 [11520/60000 (19%)] loss=2.1322
2026-03-30T06:57:08Z INFO Train Epoch: 1 [12800/60000 (21%)] loss=2.0497
2026-03-30T06:57:09Z INFO Train Epoch: 1 [14080/60000 (23%)] loss=1.9477
2026-03-30T06:57:09Z INFO Train Epoch: 1 [15360/60000 (26%)] loss=1.7657
2026-03-30T06:57:09Z INFO Train Epoch: 1 [16640/60000 (28%)] loss=1.5977
2026-03-30T06:57:09Z INFO Train Epoch: 1 [17920/60000 (30%)] loss=1.3737
2026-03-30T06:57:09Z INFO Train Epoch: 1 [19200/60000 (32%)] loss=1.3095
2026-03-30T06:57:09Z INFO Train Epoch: 1 [20480/60000 (34%)] loss=1.1860
2026-03-30T06:57:09Z INFO Train Epoch: 1 [21760/60000 (36%)] loss=1.0811
2026-03-30T06:57:09Z INFO Train Epoch: 1 [23040/60000 (38%)] loss=1.0569
2026-03-30T06:57:09Z INFO Train Epoch: 1 [24320/60000 (41%)] loss=1.0206
2026-03-30T06:57:10Z INFO Train Epoch: 1 [25600/60000 (43%)] loss=0.9029
2026-03-30T06:57:10Z INFO Train Epoch: 1 [26880/60000 (45%)] loss=1.0218
2026-03-30T06:57:10Z INFO Train Epoch: 1 [28160/60000 (47%)] loss=1.0534
2026-03-30T06:57:10Z INFO Train Epoch: 1 [29440/60000 (49%)] loss=0.9032
2026-03-30T06:57:10Z INFO Train Epoch: 1 [30720/60000 (51%)] loss=0.7920
2026-03-30T06:57:10Z INFO Train Epoch: 1 [32000/60000 (53%)] loss=1.1959
2026-03-30T06:57:10Z INFO Train Epoch: 1 [33280/60000 (55%)] loss=1.0278
2026-03-30T06:57:10Z INFO Train Epoch: 1 [34560/60000 (58%)] loss=0.9575
2026-03-30T06:57:10Z INFO Train Epoch: 1 [35840/60000 (60%)] loss=0.7868
2026-03-30T06:57:11Z INFO Train Epoch: 1 [37120/60000 (62%)] loss=0.9319
2026-03-30T06:57:11Z INFO Train Epoch: 1 [38400/60000 (64%)] loss=0.9490
2026-03-30T06:57:11Z INFO Train Epoch: 1 [39680/60000 (66%)] loss=0.8622
2026-03-30T06:57:11Z INFO Train Epoch: 1 [40960/60000 (68%)] loss=0.8083
2026-03-30T06:57:11Z INFO Train Epoch: 1 [42240/60000 (70%)] loss=0.8859
2026-03-30T06:57:11Z INFO Train Epoch: 1 [43520/60000 (72%)] loss=0.9461
2026-03-30T06:57:11Z INFO Train Epoch: 1 [44800/60000 (75%)] loss=0.9372
2026-03-30T06:57:11Z INFO Train Epoch: 1 [46080/60000 (77%)] loss=0.8243
2026-03-30T06:57:11Z INFO Train Epoch: 1 [47360/60000 (79%)] loss=0.7680
2026-03-30T06:57:12Z INFO Train Epoch: 1 [48640/60000 (81%)] loss=0.8689
2026-03-30T06:57:12Z INFO Train Epoch: 1 [49920/60000 (83%)] loss=0.8685
2026-03-30T06:57:12Z INFO Train Epoch: 1 [51200/60000 (85%)] loss=0.7834
2026-03-30T06:57:12Z INFO Train Epoch: 1 [52480/60000 (87%)] loss=0.6895
2026-03-30T06:57:12Z INFO Train Epoch: 1 [53760/60000 (90%)] loss=0.8083
2026-03-30T06:57:12Z INFO Train Epoch: 1 [55040/60000 (92%)] loss=0.8780
2026-03-30T06:57:12Z INFO Train Epoch: 1 [56320/60000 (94%)] loss=0.8591
2026-03-30T06:57:12Z INFO Train Epoch: 1 [57600/60000 (96%)] loss=0.9279
2026-03-30T06:57:12Z INFO Train Epoch: 1 [58880/60000 (98%)] loss=0.7688
2026-03-30T06:57:14Z INFO {metricName: accuracy, metricValue: 0.6871};{metricName: loss, metricValue: 0.8291}
GPUを使えるようになりましたので、ニューラルネットワークの学習の数を増やすため、epochsを1から増やしていきます。CPUモードでは時間がかかる処理も、GPUであればあっという間です。
--
Kueueのアップグレード
Kueueは現在活発に開発中のソフトウェアです。直近を見ると早ければ2週間から1ヶ月間隔でリリースが行われています。
実はこの記事を書くに当たり、書き始めた時点で最新のバージョンをインストールしたのですが、記事の下書きが終わって推敲している間に新しいマイナーバージョンとメジャーリリースがリリースされました。
現時点では上書きインストールすればKueueのアップグレードは可能のようです。 ただし開発が活発であること、当然ながらアップグレードにはAPI変更などの注意するべきことがあることを意識する必要があります。 実行する前にリリースノードの確認派しておく必要がありそうです。
マイナーバージョンの更新は破壊的変更を伴うことは無いとは思いますが、基本的にはリリースノートを見てから実行するというのが何度も言いますが重要です。
セットアップしたのは0.16.4なので、2026/04/01時点でリリースされたv0.16.5のアップグレードについてはkubectl applyで新しいマニフェストを流すだけで良いそうです。
# kubectl apply --server-side -f https://github.com/kubernetes-sigs/kueue/releases/download/v0.16.5/manifests.yaml # kubectl wait deploy/kueue-controller-manager -nkueue-system --for=condition=available --timeout=5m
今回の記事ではhelmを使ってKueueをセットアップしていませんが、仮にHelmを使ってKueueを導入した場合はhelm upgrade kueueをするだけで良いそうです。
# helm upgrade kueue oci://registry.k8s.io/kueue/charts/kueue \ --version 0.16.5 \ -n kueue-system
アップグレード後、kueue-controller-managerがRunningになっていることを確認します。
# kubectl get pods -n kueue-system NAME READY STATUS RESTARTS AGE kueue-controller-manager-9c5b76fb7-smvs2 1/1 Running 0 107s root@DL380G10-1:~# kubectl get all -n kueue-system NAME READY STATUS RESTARTS AGE pod/kueue-controller-manager-9c5b76fb7-smvs2 1/1 Running 0 2m47s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kueue-controller-manager-metrics-service ClusterIP 10.111.180.184 <none> 8443/TCP 2d service/kueue-visibility-server ClusterIP 10.104.204.232 <none> 443/TCP 2d service/kueue-webhook-service ClusterIP 10.110.150.8 <none> 443/TCP 2d NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/kueue-controller-manager 1/1 1 1 2d NAME DESIRED CURRENT READY AGE replicaset.apps/kueue-controller-manager-795b49676b 0 0 0 2d replicaset.apps/kueue-controller-manager-9c5b76fb7 1 1 1 2m47s
メジャーバージョンへのアップグレードについては、少し慎重になったほうが良さそうです。
APIバージョンの変更もあるため、Queue 定義ファイルのAPIバージョンを次のように変更する必要がありそうです。
apiVersion: kueue.x-k8s.io/v1beta2 kind: ResourceFlavor ... --- apiVersion: kueue.x-k8s.io/v1beta2 kind: ClusterQueue ... --- apiVersion: kueue.x-k8s.io/v1beta2 kind: LocalQueue ...
CRDのバージョンは次の方法で確認できるようです。これは0.16.4でKueueを動かした後、0.16.5にアップグレードした後のKueueのCRDのバージョンを出力したものです。0.16.xではAPIバージョンとしてv1beta2を指定するのを推奨していますが、v1beta1も利用できます。
0.17.xではv1beta1が廃止されるそうなので、Queue 定義ファイルはv1beta2に変更して適用する必要があるということです。
すでにQueue 定義ファイルが適用済みの場合は次のような変更を加えて、新しいバージョンのマニフェストをkubectl applyするだけで修正完了になります。
# diff -u queue-conf-apply.yaml queue-conf-apply-v1beta2.yaml
--- queue-conf-apply.yaml 2026-03-30 02:02:10.418323275 +0000
+++ queue-conf-apply-v1beta2.yaml 2026-04-01 03:09:37.985986127 +0000
@@ -4,7 +4,7 @@
metadata:
name: ml-jobs
---
-apiVersion: kueue.x-k8s.io/v1beta1
+apiVersion: kueue.x-k8s.io/v1beta2
kind: ResourceFlavor
metadata:
name: gpu
@@ -12,7 +12,7 @@
nodeLabels:
accelerator: nvidia
---
-apiVersion: kueue.x-k8s.io/v1beta1
+apiVersion: kueue.x-k8s.io/v1beta2
kind: ClusterQueue
metadata:
name: gpu-clusterqueue
@@ -30,7 +30,7 @@
- name: nvidia.com/gpu
nominalQuota: 1
---
-apiVersion: kueue.x-k8s.io/v1beta1
+apiVersion: kueue.x-k8s.io/v1beta2
kind: LocalQueue
metadata:
name: gpu-queue
Queue 定義に変更を適用
# kubectl apply -f queue-conf-apply-v1beta2.yaml
なおAPIバージョンの変更に伴い、マニフェストの書き方が変わると言うのがKubernetesあるあるですので、何か上手くいかない場合はそのあたりも公式のドキュメントなどを見て確認する必要があるかもしれません。
Kueueのメジャーアップグレード
メジャーアップグレードについても、一応まとめたものを書いておきます。 基本的にはこれだけで良いはずですが、実行前にリリースノートを確認してAPI変更やマニフェストの記述ルールに変更がないかを確認する事が重要です。
Kueueのメジャーアップグレードで重要なのは、対応するKubernetesのバージョンに変更がないかも確認が必要です。稼働中のクラスターバージョンよりも新しいバージョンを要求される場合もあります。その場合はまず、Kubernetesクラスターのバージョンアップグレードが必要になります。細かい話ですが、kubectl CLIのバージョンも場合によっては更新が必要になりますし、CNIアドオンやCRIランタイムの更新も必要になってくる場合があります。
//バックアップディレクトリーを作る
mkdir -p ~/kueue-backup
kubectl get resourceflavors.kueue.x-k8s.io -A -o yaml > ~/kueue-backup/resourceflavors.yaml
kubectl get clusterqueues.kueue.x-k8s.io -A -o yaml > ~/kueue-backup/clusterqueues.yaml
kubectl get localqueues.kueue.x-k8s.io -A -o yaml > ~/kueue-backup/localqueues.yaml
kubectl get workloads.kueue.x-k8s.io -A -o yaml > ~/kueue-backup/workloads.yaml
//アップグレード前のCRDを確認
for crd in $(kubectl get crd -o name | grep 'kueue.x-k8s.io'); do
echo "=== $crd ==="
kubectl get "$crd" -o jsonpath='{range .spec.versions[*]}{.name}{" served="}{.served}{" storage="}{.storage}{"\n"}{end}storedVersions={.status.storedVersions}{"\n\n"}'
done
//Kueueをアップグレードする
kubectl apply --server-side -f https://github.com/kubernetes-sigs/kueue/releases/download/v0.17.0/manifests.yaml
kubectl wait deploy/kueue-controller-manager -n kueue-system --for=condition=available --timeout=5m
//アップグレード後のCRDを確認
for crd in $(kubectl get crd -o name | grep 'kueue.x-k8s.io'); do
echo "=== $crd ==="
kubectl get "$crd" -o jsonpath='{range .spec.versions[*]}{.name}{" served="}{.served}{" storage="}{.storage}{"\n"}{end}storedVersions={.status.storedVersions}{"\n\n"}'
done
//Kueue リソースが普通に読めるか確認
kubectl get resourceflavors.kueue.x-k8s.io
kubectl get clusterqueues.kueue.x-k8s.io
kubectl get localqueues.kueue.x-k8s.io -A
kubectl get workloads.kueue.x-k8s.io -A
次回はこの環境にKubeflowを導入して、KubeflowとKueueの連携周りを試してみたいと思っています。