[建置] 安裝 K8s / 釐清 GPU Operator, NVIDIA Device Plugin, nvidia-container-runtime, containerd 的關係
===
###### tags: `K8s / Setup`
###### tags: `Kubernetes`, `k8s`, `setup`, `install`, `containerd`, `nvidia-container-runtime`
<br>
[TOC]
<br>
## 術語
| 術語 | 簡易說明 |
|------|--------|
| **containerd** | Kubernetes 的容器執行引擎,預設不支援 GPU |
| **`ctr` 指令** | containerd CLI<br>`$ sudo ctr images list`<br>`$ sudo ctr images pull docker.io/nvidia/cuda:12.2.0-base-ubuntu20.04`<br>`$ sudo ctr run --rm --gpus 1 docker.io/nvidia/cuda:12.2.0-base-ubuntu20.04 nvidia-test nvidia-smi`<br>(查 k8s image,需要 `-n k8s.io` ) |
|
| **NVIDIA Container Runtime** | 能跑 GPU 的容器。<br>是一個 plugin,讓 `containerd` 可以使用 NVIDIA GPU |
| **`nvidia-container-cli`指令** | NVIDIA Container CLI<br>(NVIDIA Container Toolkit CLI)<br>`$ nvidia-container-cli info`<br> - 確認 `nvidia-container-runtime` 是否正確安裝<br> - 應該會看到所有 GPU 被列出 |
|
| **NVIDIA Device Plugin** | 為 Kubernetes 提供 GPU 資源資訊<br>(自動註冊 `nvidia.com/gpu` 資源,讓 Pod 可以使用 `resources.limits.nvidia.com/gpu` 配置) |
| **NVIDIA GPU Operator** | 安裝 Driver, NVIDIA Device Plugin, NVIDIA Container Runtime 和監控工具等,並設定 containerd 。 |
<br>
## 參考資料
- [Kubernetes Container Runtimes](https://kubernetes.io/docs/setup/production-environment/container-runtimes/)
- [containerd](https://kubernetes.io/docs/setup/production-environment/container-runtimes/#containerd)
- [Docker Engine](https://kubernetes.io/docs/setup/production-environment/container-runtimes/#docker)
<br>
<hr>
<br>
## 討論
### Kubernetes 的 gpu operator ,用途為何?
- ### gpt-4o (2025/05/26)
> Kubernetes GPU Operator 功能與用途說明
Kubernetes 的 **GPU Operator** 是由 NVIDIA 提供的一套工具,讓你可以**自動安裝並管理 GPU 驅動、CUDA 工具鏈、Container Runtime 和監控工具**等,在 Kubernetes 中順利使用 GPU 執行 AI 或高效能計算工作負載。
---
## 🎯 GPU Operator 的用途與功能總覽
| 功能 | 說明 |
|------|------|
| **驅動安裝** | 自動為每個含 GPU 的節點安裝 NVIDIA 驅動(例如 `nvidia-smi` 所需) |
| **Container Runtime** | 安裝與設定 `nvidia-container-runtime`,讓容器能正確使用 GPU |
| **CUDA 支援** | 安裝 CUDA 驅動與對應的 libraries,供訓練或推論使用 |
| **DCGM Exporter** | 安裝 NVIDIA 的監控模組,可輸出 GPU 資訊供 Prometheus/Grafana 使用 |
| **Device Plugin** | 自動註冊 `nvidia.com/gpu` 資源,讓 Pod 可以使用 `resources.limits.nvidia.com/gpu` 配置 |
| **MIG 支援** | 支援 A100 GPU 的 Multi-Instance GPU 功能,實現更細粒度資源管理 |
| **可自動升級與健康檢查** | GPU Operator 提供版本控制、監控、重新安裝能力 |
---
## 🧩 為什麼需要 GPU Operator?
在原生的 K8s 中:
- **不會自動偵測或配置 GPU 驅動**
- 你得手動安裝驅動、設定 container runtime、配置 device plugin,很容易出錯
透過 GPU Operator,可以:
- 一鍵自動完成所有 GPU 節點的驅動、工具安裝與設定
- 節省人力時間,統一管理 GPU 資源
- 快速部署 AI 訓練/推論環境(如 PyTorch、TensorFlow)
---
## 🛠️ 運作方式(內部組件)
GPU Operator 是一個 Helm Chart,部署後會創建以下模組:
- `nvidia-driver-daemonset`
- `nvidia-container-toolkit-daemonset`
- `nvidia-device-plugin-daemonset`
- `nvidia-dcgm-exporter`
- `nvidia-fabricmanager`
- `nvidia-operator-validator`(確認安裝成功)
這些 DaemonSet 會自動在有 GPU 的節點啟動對應容器來安裝驅動與 runtime。
---
## 📌 補充:與 NFD (Node Feature Discovery) 配合
若搭配 NFD 使用,GPU Operator 可根據 GPU 特徵自動打上 label,如:
"""text
nvidia.com/gpu.present: "true"
"""
讓你可以使用 nodeSelector 或 affinity 做更靈活的 Pod 調度。
---
### 想要部署 GPU Operator 嗎?我可以給你具體的安裝指令與 YAML 範例。
<br>
<hr>
<br>
### GPU Operator 是否跟 containerd 有關係?
- ### gpt-4o (2025/05/26)
是的,**GPU Operator 和 containerd 有關係**,因為它需要正確地設定 containerd 才能讓容器使用 GPU。以下是兩者的關係與互動說明:
---
### 🧩 GPU Operator 與 containerd 的關係
#### 1. **containerd 需支援 NVIDIA GPU**
containerd 本身不支援 GPU,需要透過 **`nvidia-container-runtime`** 插件讓 containerd 可以使用 NVIDIA GPU。
#### 2. **GPU Operator 會安裝 nvidia-container-runtime**
GPU Operator 在部署時會:
- 檢查你是否使用 containerd(或 Docker)
- 若使用 containerd,就會安裝與設定 `nvidia-container-runtime` 插件
- 修改 `/etc/containerd/config.toml` 加入:
```toml
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.nvidia]
runtime_type = "io.containerd.runc.v2"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.nvidia.options]
BinaryName = "/usr/bin/nvidia-container-runtime"
```
#### 3. **GPU Pod 要求的 runtime 必須是 `nvidia`**
一旦 GPU Operator 設定好 containerd,你的 GPU Pod 就可以透過以下方式使用 GPU:
```yaml
resources:
limits:
nvidia.com/gpu: 1
```
Kubernetes 會自動選擇 `nvidia` runtime 來啟動該容器(只要 device plugin 有註冊)。
---
### 🚧 若 containerd 未正確設定,會出現哪些錯誤?
- Pod 永遠處於 `CreateContainerConfigError` 或 `RunContainerError`
- `nvidia-smi` 在容器內失敗,或找不到 GPU
- 查看節點的 kubelet log,會出現:
```
unknown runtime: nvidia
```
---
### ✅ 怎麼確認 containerd 已正確支援 GPU?
你可以執行以下檢查:
```
# 1. containerd 是否載入 nvidia runtime
cat /etc/containerd/config.toml | grep -A4 '\[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.nvidia\]'
# 2. 驗證 runtime 是否存在 (常見路徑:/usr/bin/nvidia-container-runtime)
which nvidia-container-runtime
# 3. 驗證 GPU pod 是否成功使用 GPU
kubectl exec -it <gpu-pod> -- nvidia-smi
```
---
### ✍️ 小結
| 組件 | 是否需要 | 用途 |
|---------------------|----------|------|
| containerd | ✅ | Pod 執行容器的核心 runtime |
| nvidia-container-runtime | ✅(GPU 必須) | 讓 containerd 支援 GPU 的關鍵 |
| GPU Operator | ✅ | 自動化安裝上述內容與配置 |
### 備註:
- ### containerd 是否載入 nvidia runtime
`/etc/containerd/config.toml` 完整上下文
```toml
[plugins."io.containerd.grpc.v1.cri".containerd]
default_runtime_name = "nvidia" <--
...
[plugins."io.containerd.grpc.v1.cri".containerd.default_runtime]
...
[plugins."io.containerd.grpc.v1.cri".containerd.default_runtime.options]
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes]
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
...
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
...
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.nvidia]
runtime_type = "io.containerd.runc.v2"
privileged_without_host_devices = false
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.nvidia.options]
BinaryName = "/usr/bin/nvidia-container-runtime"
```
- ### 驗證 runtime 是否存在
```
$ which nvidia-container-runtime
/usr/bin/nvidia-container-runtime
```
- ### 驗證 GPU pod 是否成功使用 GPU
```yaml=
# gpu-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: gpu-pod
spec:
containers:
- name: cuda-container
image: nvidia/cuda:12.2.0-base-ubuntu20.04
resources:
limits:
nvidia.com/gpu: 1
command: ["nvidia-smi"]
```
<br>
<hr>
<br>
### GPU Operator、NVIDIA Device Plugincontainerd 的關係總整理
- ### gpt-4o (2025/05/26)
這三個元件:**GPU Operator、NVIDIA Device Plugin、containerd**,在 Kubernetes 中扮演不同角色,但密切相關。搞不清楚很正常,因為它們的功能有交集但層次不同。下面我用一張圖和說明來幫你理清:
---
### 🧠 簡化理解:三者的角色分層
#### 🧱 底層:`containerd`
- Kubernetes 的容器執行引擎(runtime)
- 預設 **不支援 GPU**
- 需要整合 `nvidia-container-runtime` 才能讓容器跑出 GPU 功能
---
#### 🧩 中層:`nvidia-container-runtime`
- 是一個 plugin,讓 `containerd` 可以啟用 GPU
- 你要讓 containerd 知道「遇到 GPU 相關容器要用它來跑」
---
#### 🎯 上層:`NVIDIA Device Plugin`
- 為 Kubernetes 提供 **GPU 資源資訊**
- 自動在節點上註冊 `nvidia.com/gpu` 資源,Pod 才能宣告要 GPU
---
#### 🛠️ 自動化全家桶:`NVIDIA GPU Operator`
GPU Operator 是**上面所有東西的自動安裝工具**,幫你:
1. 安裝驅動(Driver)
2. 安裝 `nvidia-container-runtime` 並改 containerd 設定
3. 安裝 `nvidia-device-plugin`
4. 安裝監控工具(如 DCGM exporter)
5. 安裝 MIG 管理員(若使用 A100)
---
### 🧩 三者關係圖(由下而上)
```
+---------------------------+
| GPU Operator | ⬅️ 負責安裝下面所有元件
| - 安裝驅動 |
| - 安裝 device plugin |
| - 設定 containerd |
+-------------▲-------------+
|
+-------------|-------------+
| NVIDIA Device Plugin | ⬅️ 讓 K8s 認得 nvidia.com/gpu
+-------------▲-------------+
|
+-------------|-------------+
| nvidia-container-runtime | ⬅️ containerd 用這個來跑 GPU 容器
+-------------▲-------------+
|
+-------------|-------------+
| containerd | ⬅️ Pod 的容器真正由它執行
+---------------------------+
```
---
### ✅ 總結比較表
| 元件 | 類型 | 功能 | 誰安裝? | 與 GPU Operator 的關係 |
|------|------|------|-----------|--------------------------|
| containerd | Container Runtime | 執行容器 | 系統預先裝好 | 需要額外設定才能用 GPU |
| nvidia-container-runtime | plugin | 讓 containerd 支援 GPU | GPU Operator 幫你裝 | 必要,Operator 幫你處理 |
| NVIDIA Device Plugin | Kubernetes plugin | 對 K8s 暴露 GPU 資源 | GPU Operator 幫你裝 | Operator 自動安裝與配置 |
| GPU Operator | Operator | 一鍵部署所有 GPU 組件 | 手動裝 Operator | 管理其他所有組件 |
---
### 🔍 怎麼判斷你的環境有沒有設好?
你可以從節點、Pod、containerd 三層檢查:
#### A. 節點是否有 GPU 資源?
```
kubectl describe node <your-node> | grep -A5 "Capacity"
# 看有沒有 nvidia.com/gpu
```
#### B. Device Plugin 是否有註冊?
```
kubectl get pods -n nvidia-gpu-operator
kubectl logs <nvidia-device-plugin-pod> -n nvidia-gpu-operator
```
#### C. containerd 是否支援 GPU?
```
cat /etc/containerd/config.toml | grep nvidia
```
---
如需我幫你逐步確認你目前環境設定是否到位,也可以把你目前的節點 label、GPU operator namespace pods、containerd 設定貼上來,我幫你逐一看。
<br>
<hr>
<br>
### [containerd 資訊] containerd 談到的 cgroup driver 是指什麼?
- ### gpt-4o (2025/05/26)
> containerd 中的 cgroup driver 是什麼?
在 Kubernetes 和 containerd 等容器運行時(Container Runtime)中,**cgroup driver(控制群組驅動器)** 是指:**容器運行時用來與 Linux 的 cgroups(Control Groups)溝通與管理資源限制的方式**。
---
### 🧩 什麼是 cgroups?
**cgroups(Control Groups)** 是 Linux 的一項功能,用來:
- 限制(Limit):CPU、記憶體、IO 等資源
- 監控(Monitor):記錄使用量
- 隔離(Isolate):彼此獨立運作
- 優先權(Prioritize):設置不同等級的資源分配
Kubernetes 會透過 container runtime(如 containerd 或 Docker)來設定這些資源限制。
---
### 🔧 cgroup driver 的意義是?
Linux 上管理 cgroups 的方式有兩種主流:
| Driver | 說明 |
|--------|------|
| **cgroupfs** | 使用 Linux 上的 `/sys/fs/cgroup` 路徑直接操作 cgroups(較原始) |
| **systemd** | 使用 `systemd` 的 cgroup 控制介面來管理(較整合,推薦使用) |
---
#### containerd 的 cgroup driver
當你安裝 containerd 時,它的預設行為取決於 distro,例如 Ubuntu 常預設為 `systemd`。
設定檔位於 `/etc/containerd/config.toml` 中,相關欄位如下:
```toml
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
SystemdCgroup = true # ✅ true 表示使用 systemd,false 則是 cgroupfs
```
---
### ✅ 為什麼要關心這個設定?
Kubernetes 的 kubelet 也需要設定使用同一個 cgroup driver,例如:
```yaml
KUBELET_EXTRA_ARGS=--cgroup-driver=systemd
```
如果 containerd 用的是 `systemd`,而 kubelet 卻是 `cgroupfs`,就會出現這類錯誤:
```text
"failed to start container: systemd cgroup driver mismatch"
```
---
### 🛠️ 建議:**Kubernetes 與 containerd 一致使用 `systemd`**
- 這樣可以與現代 Linux distro(如 Ubuntu 20.04/22.04)系統管理一致
- 更穩定,錯誤較少,整合性佳
---
需要我幫你查你目前的 containerd 是用哪種 driver 嗎?還是幫你寫個自動檢查腳本?
<br>
<hr>
<br>
### [containerd 資訊] 目前的 containerd 是用哪種 driver
- ### gpt-4o (2025/05/26)
> 如何確認目前的 containerd 使用哪種 cgroup driver
你可以用下列方法來確認 **containerd 現在使用哪種 cgroup driver**:
---
### ✅ 方法 1:查看 containerd 設定檔
```bash
grep SystemdCgroup /etc/containerd/config.toml
```
#### 🔍 結果解讀:
- `SystemdCgroup = true` 👉 表示使用 **systemd**
- `SystemdCgroup = false` 👉 表示使用 **cgroupfs**
- 如果找不到,可能是預設值(通常為 false),建議用下一步確認實際狀況
---
### ✅ 方法 2:用 crictl 工具查看實際運作的 container runtime 設定
```bash
sudo crictl info | grep -i "systemdcgroup"
```
你會看到類似:
```json
"SystemdCgroup": true,
```
---
### ✅ 方法 3:完整看設定與版本(推薦)
```bash
containerd config dump | grep SystemdCgroup
```
如果你看到:
```toml
SystemdCgroup = true
```
就代表正在使用 `systemd`。
---
### 🧪 延伸確認(若你也用 kubelet)
你也可以確認 kubelet 使用的 driver 是否一致:
```bash
# example
$ ps aux | grep kubelet
root 2238894 4.9 0.0 5822864 120220 ? Ssl May26 63:58 \
/usr/bin/kubelet \
--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf \
--kubeconfig=/etc/kubernetes/kubelet.conf \
--config=/var/lib/kubelet/config.yaml \
--container-runtime-endpoint=unix:///var/run/containerd/containerd.sock \
--pod-infra-container-image=registry.k8s.io/pause:3.10
```
```bash
ps aux | grep kubelet | grep cgroup-driver
```
若顯示:
```bash
--cgroup-driver=systemd
```
就代表與 containerd 一致,✅ 無衝突。
<br>
{%hackmd vaaMgNRPS4KGJDSFG0ZE0w %}