[應用] GPU Operator -- (Driver, NVIDIA Container Runtime, NVIDIA Device Plugin, node labels)
===
###### tags: `K8s / app`
###### tags: `Kubernetes`, `k8s`, `app`, `GPU Operator`, `NVIDIA GPU Feature Discovery`, `GFD`, `Driver`, `NVIDIA container runtime`, `NVIDIA device plugin`, `node labels`
<br>
[TOC]
<br>
## [總覽] 安裝 NVIDIA GPU Operator
- Install Helm
```bash
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 \
&& chmod 700 get_helm.sh \
&& ./get_helm.sh
# add the NVIDIA Helm repository
helm repo add nvidia https://helm.ngc.nvidia.com/nvidia \
&& helm repo update
```
- Install the GPU Operator
```
helm install --wait --generate-name \
-n gpu-operator --create-namespace \
nvidia/gpu-operator
```
<br>
## [詳解] 安裝 NVIDIA GPU Operator(依系統狀況動態決定參數)
NVIDIA GPU Operator 可協助在 Kubernetes 節點上自動部署以下 GPU 相關元件:
| 元件 | 說明 |
|-----------------------------|--------------------------------------------|
| **Driver** | 安裝 NVIDIA 驅動(選擇性) |
| **Container Toolkit** | 安裝 `nvidia-container-toolkit` 並設定 runtime |
| **Device Plugin** | 提供 GPU 資訊給 kubelet 進行排程與掛載 |
| **DCGM Exporter** | 匯出 GPU 健康狀況與使用率 metrics(Prometheus) |
| **GPU Feature Discovery** | 偵測節點上的 GPU 功能與型號 |
- ### [總覽] 使用 helm 安裝 gpu-operator,參數設定可依據「**系統狀態**」決定
```bash=
helm repo add nvidia https://nvidia.github.io/gpu-operator
helm repo update
kubectl create namespace gpu-operator
helm install --wait --generate-name \
nvidia/gpu-operator \
--namespace gpu-operator \
--set driver.enabled=false \
--set toolkit.enabled=true
```
| 狀況 | 參數設定 | 說明 |
|----------------------------------|--------|-----|
| ❌ GPU 驅動未裝 (`nvidia-smi`) | `--set driver.enabled=true` | 由 gpu-operator 幫忙裝 |
| ✅ GPU 驅動已裝 (`nvidia-smi`) | `--set driver.enabled=false` | 不用幫忙 |
| ❌ containerd 尚未設定支援 nvidia | `--set toolkit.enabled=true` | 由 gpu-operator 幫忙裝 |
| ✅ containerd 已經設定支援 nvidia | `--set toolkit.enabled=false` | 不用幫忙 |
- ### 📌 7.1 檢查當前系統狀態
> 情境:**(A)** K8s重建, **(B)** 全新安裝
>
使用下表逐項檢查主機狀態:
| 項目 | 指令範例 | 狀態評估 |
|------------------------------|----------------------------------------|-----------------------|
| ✅ GPU 驅動是否已安裝 | `nvidia-smi` | 有輸出表示已安裝 |
| ✅ containerd 是否已安裝 | `containerd --version` | 有版本輸出表示已安裝 |
| ✅ containerd 是否支援 nvidia | `cat /etc/containerd/config.toml \| grep nvidia` | 有 nvidia 條目表示已設定 |
---
- ### 📌 7.2 根據狀態選擇 Helm 安裝參數
請根據你的實際狀況選擇安裝方式:
- #### 🔧 **情境 A:已手動安裝 GPU 驅動,但尚未設定 container runtime**
> 適用於:K8s 重建
| 狀況 | 是否符合 |
|----------------------------------|----------|
| ✅ GPU 驅動已裝 (`nvidia-smi`) | 是 |
| ❌ containerd 尚未設定支援 nvidia | 是 |
👉 推薦設定:
```
--set driver.enabled=false \
--set toolkit.enabled=true
```
- 🟢 GPU 驅動由你自行管理,不讓 Operator 干預
- 🟢 讓 Operator 幫你設定 containerd 的 GPU runtime(自動加上 `nvidia` runtime 到 config.toml)
---
- #### 🔧 **情境 B:都還沒裝,完全交由 GPU Operator 處理**
> 適用於:全新安裝
| 狀況 | 是否符合 |
|------------------|----------|
| ❌ GPU 驅動未裝 | 是 |
| ❌ containerd 尚未設定 | 是 |
👉 推薦設定:
```
--set driver.enabled=true \
--set toolkit.enabled=true
```
- 🟢 由 GPU Operator 全權處理驅動與 runtime 安裝
- 📌 需注意需搭配支援的 OS(如 RHEL/CentOS/Ubuntu),否則驅動安裝可能失敗
---
- #### 🔧 **情境 C:你所有東西都已手動設定好**
> 適用於:有客製化需求的進階管理者
| 狀況 | 是否符合 |
|----------------------------------|----------|
| ✅ GPU 驅動 (`nvidia-smi`) 已裝 | 是 |
| ✅ containerd 已設定支援 nvidia | 是 |
👉 推薦設定:
```
--set driver.enabled=false \
--set toolkit.enabled=false
```
- 🟢 完全不讓 GPU Operator 修改系統
- 適用於企業/空氣隔離環境,已手動管理所有 runtime
- 手動註冊 nvidia runtime
- 向 containerd 註冊 nvidia runtime
```bash
# nvidia-ctk: Tools to configure the NVIDIA Container Toolkit
sudo nvidia-ctk runtime configure --runtime=containerd
```
- 驗證方式:
```
cat /etc/containerd/config.toml | grep nvidia
```

---
- ### 📦 7.3 安裝 GPU Operator(以情境 A 為例)(K8s重建)
```bash=
helm repo add nvidia https://nvidia.github.io/gpu-operator
helm repo update
kubectl create namespace gpu-operator
helm install --wait --generate-name \
nvidia/gpu-operator \
--namespace gpu-operator \
--set driver.enabled=false \
--set toolkit.enabled=true
```
---
- ### ✅ 7.4 驗證 GPU Operator 運作
```
kubectl get pods -n gpu-operator
```
應看到以下元件皆為 `Running`:
| 元件 Pod 名稱 | 說明 |
|-----------------------------|-------------------------|
| `nvidia-device-plugin-*` | 掛載 GPU 給 Pod 使用 |
| `nvidia-container-toolkit-*` | 設定 containerd runtime |
| `gpu-feature-discovery-*` | 掃描 GPU 特性 |
| `nvidia-dcgm-exporter-*` | 匯出 metrics(Prometheus)|

---
- ### 🔬 7.5 測試 GPU 是否可用
- #### 測試能否要到指定的 GPU 張數
```yaml=
# gpu-test.yaml
apiVersion: v1
kind: Pod
metadata:
name: gpu-test
spec:
restartPolicy: OnFailure
containers:
- name: cuda-container
image: nvidia/cuda:12.2.0-base-ubuntu22.04
resources:
limits:
nvidia.com/gpu: 1
command: ["nvidia-smi"]
```
```
kubectl apply -f gpu-test.yaml
kubectl logs gpu-test
```
- #### 測試能否能跑 cuda 程式 (執行向量相加)
```yaml=
# cuda-sample-vectoradd.yaml
apiVersion: v1
kind: Pod
metadata:
name: cuda-sample-vectoradd
spec:
restartPolicy: Never
containers:
- name: cuda-container
image: nvcr.io/nvidia/k8s/cuda-sample:vectoradd-cuda11.7.1-ubuntu20.04
resources:
limits:
nvidia.com/gpu: 1 # requesting 1 GPU
```
---
- ### ✅ 7.6 小結
| 項目 | 狀態 |
|---------------------------|------|
| GPU 驅動 (`nvidia-smi`) | ✅ 已安裝 |
| Containerd + systemd | ✅ 已安裝 |
| containerd 設定 nvidia runtime | ✅ 已由 Operator 自動完成 |
| GPU Operator 安裝 | ✅ 成功部署 |
| 測試 Pod 使用 GPU | ✅ 成功執行 |
<br>
---
<br>
## 手動安裝 `nvidia-container-runtime`
### 安裝 NVIDIA Container Toolkit 方式
```bash
# 加入套件庫金鑰與來源
distribution=$(. /etc/os-release;echo $ID$VERSION_ID) # 例如 ubuntu20.04
curl -s -L https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
curl -s -L https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.list | \
sed 's#https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#' | \
sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
# 安裝 runtime
sudo apt update
sudo apt install -y nvidia-container-toolkit
```
接著修改 containerd 設定來啟用 NVIDIA runtime:
```
sudo nvidia-ctk runtime configure --runtime=containerd
```
重啟 containerd:
```
sudo systemctl restart containerd
```
**驗證方式**:可執行底下 image 測試 container 是否能成功使用 GPU。
```
$ sudo ctr image pull docker.io/nvidia/cuda:12.2.0-base-ubuntu22.04
$ sudo ctr run --rm --gpus 0 docker.io/nvidia/cuda:12.2.0-base-ubuntu22.04 test-nvidia nvidia-smi
Mon Jun 9 03:22:08 2025
+---------------------------------------------------------------------------------------+
| NVIDIA-SMI 535.54.03 Driver Version: 535.54.03 CUDA Version: 12.2 |
|-----------------------------------------+----------------------+----------------------+
| 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 GeForce GTX 1080 Ti On | 00000000:02:00.0 Off | N/A |
| 27% 33C P8 9W / 250W | 6MiB / 11264MiB | 0% Default |
| | | N/A |
+-----------------------------------------+----------------------+----------------------+
+---------------------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=======================================================================================|
+---------------------------------------------------------------------------------------+
```
- containerd 使用 `ctr` 指令時,不會像 Docker CLI 那樣隱式地將 `nvidia/cuda` 解析為 `docker.io/nvidia/cuda`,因此你**必須自己加上完整路徑** `docker.io/`。
<br>
---
<br>
## NVIDIA GPU feature discovery
> https://github.com/NVIDIA/k8s-device-plugin/blob/main/docs/gpu-feature-discovery/README.md
- ### [Node Feature Discovery (NFD)](https://github.com/NVIDIA/k8s-device-plugin/blob/main/docs/gpu-feature-discovery/README.md#node-feature-discovery-nfd)
```
kubectl apply -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/v0.16.2/deployments/static/nfd.yaml
```
- ### k8s 正常狀態
```
$ kubectl get all -n node-feature-discovery
NAME READY STATUS RESTARTS AGE
pod/nfd-26fbg 2/2 Running 0 16m
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
daemonset.apps/nfd 1 1 1 1 1 <none> 16m
```
- ### node 資訊,新增差異如下:
```yaml
apiVersion: v1
kind: Node
metadata:
annotations:
nfd.node.kubernetes.io/feature-labels: cpu-cpuid.ADX,cpu-cpuid.AESNI,cpu-cpuid.AVX,cpu-cpuid.AVX2,cpu-cpuid.FMA3,cpu-cpuid.HLE,cpu-cpuid.IBPB,cpu-cpuid.RTM,cpu-cpuid.STIBP,cpu-cpuid.VMX,cpu-hardware_multithreading,cpu-pstate.turbo,cpu-rdt.RDTCMT,cpu-rdt.RDTL3CA,cpu-rdt.RDTMBM,cpu-rdt.RDTMON,iommu-enabled,kernel-config.NO_HZ,kernel-config.NO_HZ_IDLE,kernel-version.full,kernel-version.major,kernel-version.minor,kernel-version.revision,memory-numa,network-sriov.capable,pci-10de.present,pci-1a03.present,system-os_release.ID,system-os_release.VERSION_ID,system-os_release.VERSION_ID.major,system-os_release.VERSION_ID.minor
nfd.node.kubernetes.io/master.version: v0.6.0
nfd.node.kubernetes.io/worker.version: v0.6.0
node.alpha.kubernetes.io/ttl: "0"
labels:
feature.node.kubernetes.io/cpu-cpuid.ADX: "true"
feature.node.kubernetes.io/cpu-cpuid.AESNI: "true"
feature.node.kubernetes.io/cpu-cpuid.AVX: "true"
feature.node.kubernetes.io/cpu-cpuid.AVX2: "true"
feature.node.kubernetes.io/cpu-cpuid.FMA3: "true"
feature.node.kubernetes.io/cpu-cpuid.HLE: "true"
feature.node.kubernetes.io/cpu-cpuid.IBPB: "true"
feature.node.kubernetes.io/cpu-cpuid.RTM: "true"
feature.node.kubernetes.io/cpu-cpuid.STIBP: "true"
feature.node.kubernetes.io/cpu-cpuid.VMX: "true"
feature.node.kubernetes.io/cpu-hardware_multithreading: "true"
feature.node.kubernetes.io/cpu-pstate.turbo: "true"
feature.node.kubernetes.io/cpu-rdt.RDTCMT: "true"
feature.node.kubernetes.io/cpu-rdt.RDTL3CA: "true"
feature.node.kubernetes.io/cpu-rdt.RDTMBM: "true"
feature.node.kubernetes.io/cpu-rdt.RDTMON: "true"
feature.node.kubernetes.io/iommu-enabled: "true"
feature.node.kubernetes.io/kernel-config.NO_HZ: "true"
feature.node.kubernetes.io/kernel-config.NO_HZ_IDLE: "true"
feature.node.kubernetes.io/kernel-version.full: 5.4.0-137-generic
feature.node.kubernetes.io/kernel-version.major: "5"
feature.node.kubernetes.io/kernel-version.minor: "4"
feature.node.kubernetes.io/kernel-version.revision: "0"
feature.node.kubernetes.io/memory-numa: "true"
feature.node.kubernetes.io/network-sriov.capable: "true"
feature.node.kubernetes.io/pci-10de.present: "true"
feature.node.kubernetes.io/pci-1a03.present: "true"
feature.node.kubernetes.io/system-os_release.ID: ubuntu
feature.node.kubernetes.io/system-os_release.VERSION_ID: "20.04"
feature.node.kubernetes.io/system-os_release.VERSION_ID.major: "20"
feature.node.kubernetes.io/system-os_release.VERSION_ID.minor: "04"
status:
images:
- names:
- quay.io/kubernetes_incubator/node-feature-discovery@sha256:a1e72dbc35a16cbdcf0007fc4fb207bce723ff67c61853d2d8d8051558ce6de7
- quay.io/kubernetes_incubator/node-feature-discovery:v0.6.0
sizeBytes: 35343350
```
- ### [Deploy NVIDIA GPU Feature Discovery (GFD)](https://github.com/NVIDIA/k8s-device-plugin/blob/main/docs/gpu-feature-discovery/README.md#deploy-nvidia-gpu-feature-discovery-gfd)
> for staging
- ### 安裝方式
```
kubectl apply -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/v0.16.2/deployments/static/gpu-feature-discovery-daemonset.yaml
```
- [gpu-feature-discovery-daemonset.yaml](https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/v0.16.2/deployments/static/gpu-feature-discovery-daemonset.yaml)
- ### k8s 正常狀態
```
NAME READY STATUS RESTARTS AGE
pod/gpu-feature-discovery-qv6pn 1/1 Running 0 2m13s
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
daemonset.apps/gpu-feature-discovery 1 1 1 1 1 <none> 2m13s
```
- ### node 資訊,新增差異如下:
```yaml
apiVersion: v1
kind: Node
metadata:
labels:
nvidia.com/cuda.driver-version.full: 535.54.03
nvidia.com/cuda.driver-version.major: "535"
nvidia.com/cuda.driver-version.minor: "54"
nvidia.com/cuda.driver-version.revision: "03"
nvidia.com/cuda.driver.major: "535"
nvidia.com/cuda.driver.minor: "54"
nvidia.com/cuda.driver.rev: "03"
nvidia.com/cuda.runtime-version.full: "12.2"
nvidia.com/cuda.runtime-version.major: "12"
nvidia.com/cuda.runtime-version.minor: "2"
nvidia.com/cuda.runtime.major: "12"
nvidia.com/cuda.runtime.minor: "2"
nvidia.com/gfd.timestamp: "1748336208"
nvidia.com/gpu.compute.major: "6"
nvidia.com/gpu.compute.minor: "1"
nvidia.com/gpu.count: "4"
nvidia.com/gpu.family: pascal
nvidia.com/gpu.machine: ESC4000-G3-Series
nvidia.com/gpu.memory: "11264"
nvidia.com/gpu.mode: graphics
nvidia.com/gpu.product: NVIDIA-GeForce-GTX-1080-Ti
nvidia.com/gpu.replicas: "1"
nvidia.com/gpu.sharing-strategy: none
nvidia.com/mig.capable: "false"
nvidia.com/mps.capable: "false"
nvidia.com/vgpu.present: "false"
status:
images:
- names:
- nvcr.io/nvidia/k8s-device-plugin@sha256:ed39e22c8b71343fb996737741a99da88ce6c75dd83b5c520e0b3d8e8a884c47
- nvcr.io/nvidia/k8s-device-plugin:v0.16.2
sizeBytes: 126081487
```
- [Deployment via helm](https://github.com/NVIDIA/k8s-device-plugin/blob/main/docs/gpu-feature-discovery/README.md#deployment-via-helm)
- ### 安裝方式
```
$ helm repo add nvdp https://nvidia.github.io/k8s-device-plugin
$ helm repo update
```
```
$ helm search repo nvdp --devel
NAME CHART VERSION APP VERSION DESCRIPTION
nvdp/gpu-feature-discovery 0.17.1 0.17.1 A Helm chart for gpu-feature-discovery on Kuber...
nvdp/nvidia-device-plugin 0.17.1 0.17.1 A Helm chart for the nvidia-device-plugin on Ku...
```
```
helm upgrade -i nvdp nvdp/nvidia-device-plugin \
--namespace gpu-feature-discovery \
--create-namespace \
--set devicePlugin.enabled=false \
--set gfd.enabled=true
```
```
helm uninstall nvdp --namespace gpu-feature-discovery
```
- ### k8s 正常狀態
```
$ kubectl get all -n gpu-feature-discovery
NAME READY STATUS RESTARTS AGE
pod/nvdp-node-feature-discovery-master-77f5fd5bb-cnczb 1/1 Running 0 3m36s
pod/nvdp-node-feature-discovery-worker-xcbh6 1/1 Running 1 (3m15s ago) 3m36s
pod/nvdp-nvidia-device-plugin-gpu-feature-discovery-8jldw 1/1 Running 0 3m36s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/nvdp-node-feature-discovery-master ClusterIP 10.109.36.255 <none> 8080/TCP 3m37s
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
daemonset.apps/nvdp-node-feature-discovery-worker 1 1 1 1 1 <none> 3m37s
daemonset.apps/nvdp-nvidia-device-plugin-gpu-feature-discovery 1 1 1 1 1 <none> 3m37s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/nvdp-node-feature-discovery-master 1/1 1 1 3m37s
NAME DESIRED CURRENT READY AGE
replicaset.apps/nvdp-node-feature-discovery-master-77f5fd5bb 1 1 1 3m37s
```
<br>
## 討論
### 安裝 NVIDIA GPU Operator 步驟
- ### gpt-o4-mini-high (2025/05/21)
以下是在您的 Kubernetes 叢集(假設已安裝 NVIDIA 驅動與 container runtime)上安裝 NVIDIA GPU Operator 的步驟:
---
### 1. 環境與需求確認
1. **已安裝 NVIDIA 驅動**
您的節點上已透過 Docker 驗證 NVIDIA 驅動可用(`nvidia-smi` 正常顯示)。
2. **Container runtime 支援**
叢集需使用 containerd 或 CRI-O 作為 container runtime。
3. **(若啟用 Pod Security Admission)命名空間安全性策略**
如有啟用 PSA,建議將 GPU Operator 所在命名空間標記為 `privileged`。
---
### 2. 安裝 Helm(若尚未安裝)
```bash
# macOS (Homebrew)
brew install helm
# Linux (腳本方式)
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
```
---
### 3. 新增 NVIDIA Helm 倉庫並更新
```bash
helm repo add nvidia-ngc https://helm.ngc.nvidia.com/nvidia \
&& helm repo update
```
---
### 4. 建立並標記命名空間(可選)
```bash
kubectl create namespace gpu-operator
kubectl label --overwrite ns gpu-operator pod-security.kubernetes.io/enforce=privileged=privileged
```
---
### 5. 使用 Helm 安裝 GPU Operator
NVIDIA 官方最新版本為 v25.3.0(發佈於 2025 年 3 月):contentReference[oaicite:4]{index=4}。以下示範兩種情境:
### 5.1 預設安裝(包含驅動安裝)
```bash
helm install --wait --generate-name \
-n gpu-operator --create-namespace \
nvidia-ngc/gpu-operator \
--version=v25.3.0
```
### 5.2 節點已預先安裝 NVIDIA 驅動
```bash
helm install --wait --generate-name \
-n gpu-operator --create-namespace \
nvidia/gpu-operator \
--version=v25.3.0 \
--set driver.enabled=false
```
---
### 6. 檢查部署狀態
```bash
kubectl -n gpu-operator get pods
# 確認以下主要 Pod 都已就緒:
# - gpu-operator-xxxxxx (Operator 本身)
# - driver-daemonset-xxxx
# - toolkit-daemonset-xxxx
# - device-plugin-daemonset-xxxx
# - nfd-daemonset-xxxx
# - mig-manager-daemonset-xxxx
```
---
### 7. 驗證 GPU 功能
1. 於任一工作節點建立測試 Pod,使用 NVIDIA 提供的 CUDA 範例:
```bash
kubectl run cuda-vectoradd \
--image=nvidia/samples:vectoradd-cuda11.2-runtime \
--restart=Never \
--limits=nvidia.com/gpu=1 \
-- sleep 30
kubectl logs cuda-vectoradd
```
2. 若看到類似 `PASSED` 的訊息,即代表 GPU 已正常被叢集調度並能執行 CUDA 程式。:contentReference[oaicite:6]{index=6}
---
完成以上步驟後,您的 Kubernetes 叢集就已成功透過 NVIDIA GPU Operator 管理 GPU 驅動、device plugin、Container Toolkit、Node Feature Discovery (NFD) 與 MIG 管理等元件,並可直接在 Pod spec 中設定 `limits.nvidia.com/gpu` 來使用 GPU 資源。
<br>
---
<br>
### `--set toolkit.enabled=true` 用途為何? 怎麼判斷要帶 `true` 或 `false` ?
- ### gpt-4o (2025/06/08)
### ✅ `--set toolkit.enabled=true` 用途與使用時機
`--set toolkit.enabled=true` 是安裝 NVIDIA GPU Operator 時的一個關鍵選項,用來控制是否啟用 **NVIDIA Container Toolkit DaemonSet**,這個 DaemonSet 主要是:
---
### ✅ 什麼是 `toolkit.enabled`?
它會部署 `nvidia-container-toolkit` 的 DaemonSet 到每個節點,**讓容器能夠使用 GPU(例如能跑 `nvidia-smi`)**。
當你使用 containerd(或 Docker)做為 runtime,而節點上**尚未安裝 `nvidia-container-toolkit`** 時,你就必須讓 GPU Operator 幫你裝上這個 component,否則 GPU Pod 會出現錯誤(如找不到 GPU device)。
---
### 🔍 怎麼判斷要設 `true` 還是 `false`?
| 狀況 | toolkit.enabled 要設為? | 說明 |
|------|----------------------|------|
| 節點 **已安裝 `nvidia-container-toolkit`** | `false` | 避免與系統已有安裝衝突(自行安裝者常見) |
| 節點 **尚未安裝 `nvidia-container-toolkit`** | `true` | 讓 GPU Operator 自動安裝 |
| 節點使用 GPU Operator 自動安裝驅動、toolkit 全套 | `true`(且 driver.enabled=true) | 一般建議實驗環境這樣做 |
| 節點已有 GPU Driver、toolkit 全部手動安裝完 | `false` | 專業環境多半自己控管套件版本與相依性 |
---
### 🧪 怎麼檢查系統是否已有 toolkit?
你可以看是否存在 `/usr/bin/nvidia-container-runtime` 或查詢 `nvidia-container-cli`:
```bash
which nvidia-container-runtime
which nvidia-container-cli
dpkg -l | grep nvidia-container
```
或查 `/etc/containerd/config.toml` 裡是否設定了 `nvidia` runtime:
```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"
```
---
### ✅ 結論建議
- **你手動安裝過驅動與 toolkit?**
- → 設 `toolkit.enabled=false`(避免 GPU Operator 干預)
- **你只裝了驅動,但沒安裝 toolkit?**
- → 設 `toolkit.enabled=true`
- **你什麼都沒裝?**
- → 可以都交給 GPU Operator 自動裝(`driver.enabled=true`, `toolkit.enabled=true`)
如果你希望完全由 GPU Operator 管控所有 GPU 相依工具,則兩者都設為 `true`。但這種方式要特別注意驅動與主機內核是否相容。
<br>
---
<br>
### `--set driver.enabled=false` 用途為何? 怎麼判斷要帶 `true` 或 `false` ?
- ### gpt-4o (2025/06/08)
### ✅ 什麼是 `driver.enabled`?
它控制是否啟用 `nvidia-driver-daemonset`:
- 如果 `driver.enabled=true`:
- GPU Operator 會在每個節點部署 DaemonSet,自動安裝 NVIDIA 驅動(包含 kernel module、nvidia-smi、libnvidia 等)。
- 如果 `driver.enabled=false`:
- 表示你已在每個節點「**手動安裝好驅動**」,Operator 不會干預。
---
### 📌 什麼情況要設 `true`?什麼情況要設 `false`?
| 節點狀況 | driver.enabled 設定 | 原因/建議 |
|----------|----------------------|-------------|
| 節點未安裝任何驅動 | `true` | 讓 GPU Operator 自動裝驅動,快速部署 |
| 節點已手動安裝驅動(e.g. `.run` 安裝版、apt 安裝) | `false` | 避免 Operator 重裝或版本衝突 |
| 節點使用自行建構的客製驅動 | `false` | 通常這種情況需要精細控管驅動版本與 kernel 相容性 |
| 節點是裸機長期部署,驅動固定由系統維運裝 | `false` | 維運穩定性考量,不讓 GPU Operator 插手 |
---
### 🔍 如何判斷驅動已存在?
執行以下指令查看是否已安裝驅動:
```
nvidia-smi
```
- 有看到顯示卡與 driver version(如 CUDA Version, Driver Version) → 驅動已安裝
- 出現 `command not found` 或 `No devices were found` → 驅動可能沒裝好或裝錯
也可查看驅動模組是否已載入:
```
lsmod | grep nvidia
```
---
### 🧱 注意事項
如果你的環境是:
- 使用 **官方 NVIDIA Driver Installer (`.run`)**
- 驅動是公司政策內部套件管理安裝(e.g. 使用 Ansible 或自建 package)
建議設為:
```
--set driver.enabled=false
```
否則 GPU Operator 有可能會嘗試卸載你的版本、重裝它的驅動,導致不穩定。
---
### ✅ 總結建議
| 驅動安裝情況 | `driver.enabled` 設定 |
|--------------|------------------------|
| 沒有任何驅動 | `true` |
| 自行手動安裝驅動 | `false` |
| 使用特定內部套件管理驅動 | `false` |
| 測試機、快速部署開發環境 | `true` |
如仍不確定,也可以先設定為 `false`,並手動裝好驅動、確認 `nvidia-smi` 運作,再安裝 GPU Operator(只讓它裝 toolkit、plugin)。這樣穩定性較高。
<br>
---
<br>
### containerd 的 runtime 設定,增加 nvidia device,是由誰負責設定?
- ### gpt-4o (2025/06/08)
在使用 NVIDIA GPU Operator 搭配 containerd 時,containerd 的 runtime 設定中是否出現 `nvidia` runtime,**取決於誰負責安裝 `nvidia-container-toolkit`**。以下是詳細說明:
---
### ✅ 誰負責設定 containerd 的 `nvidia` runtime?
| 安裝方式 | 負責設定 containerd 的 runtime? | 備註 |
|----------|-------------------------------|------|
| **你手動安裝 `nvidia-container-toolkit`** | ✅ 你自己要設定 `/etc/containerd/config.toml` | 不會自動幫你加 `nvidia` runtime |
| **由 GPU Operator 安裝 toolkit (`toolkit.enabled=true`)** | ✅ GPU Operator 負責自動設定 | 它會 patch containerd 的 config 並 reload service |
| **使用 NVIDIA 官方的 `nvidia-container-runtime` 安裝腳本** | ✅ 安裝腳本會幫你設定 | 適用裸機/VM 自行部署的情境 |
| **你手動設定 containerd config.toml** | ✅ 自行新增 runtime 配置 | 通常你得自己手動 restart containerd |
---
### 🔧 containerd 的 `nvidia` 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"
```
這段設定是告訴 containerd:
- 當使用 runtimeClass 為 `nvidia` 時,要使用 `/usr/bin/nvidia-container-runtime` 來啟動容器。
- 搭配 GPU Operator 或 AI workloads(如 PyTorch/TensorFlow)才能正確掛載 GPU device。
---
### 📌 小提醒:這段設定什麼時候生效?
設定完 `/etc/containerd/config.toml` 後,**必須重啟 containerd** 才會生效:
```
sudo systemctl restart containerd
```
---
### ✅ 如何確認你有這段設定?
```
grep -A5 '\[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.nvidia\]' /etc/containerd/config.toml
```
若沒這段,就代表沒有設定成功(不論是你或 Operator 裝 toolkit 都會需要)。
---
### 🧭 結論
| 誰裝了 `nvidia-container-toolkit` | 是否自動設定 containerd? |
|------------------------|------------------------|
| 你自己手動 `apt install` | ❌ 否,需要手動編輯 config.toml |
| GPU Operator (`toolkit.enabled=true`) | ✅ 會自動 patch containerd 並設定 runtime |
| NVIDIA 官方安裝腳本 (`nvidia-container-toolkit`) | ✅ 多半會自動設定 |
因此:
> 📌 若你自己裝 toolkit,**你自己負責設定 containerd runtime**。
> 📌 若讓 GPU Operator 裝 toolkit(`toolkit.enabled=true`),**它會幫你自動加好 `nvidia` runtime。**
如需,我也可以幫你產生自動設定 `config.toml` 的 shell script。
<br>
### NVIDIA GPU Operator 是否會幫你裝 `nvidia-container-toolkit`?
- ### gpt-4o (2025/06/09)
#### ✅ 是,**GPU Operator 會自動安裝 `nvidia-container-toolkit`**
GPU Operator 包含多個 DaemonSet 與元件,其中的 `nvidia-container-toolkit-daemonset` 會:
- 在每個節點上安裝:
- `nvidia-container-toolkit`
- `nvidia-ctk`(新版本的 CLI 工具)
- 自動配置 containerd 的 runtime 設定(例如 `/etc/containerd/config.toml`)
- 搭配其他元件(如 `nvidia-device-plugin`)協助 GPU pod 啟動時掛載正確的 NVIDIA runtime
---
### 那為什麼還需要手動裝 `nvidia-container-toolkit`?
以下是 **什麼情況你「需要或建議」手動安裝的理由**:
#### 🔧 1. **你要在 GPU Operator 安裝前先驗證 containerd 能否正確執行 GPU container**
- 例如想先手動測試這個指令:
```
sudo ctr run --rm --gpus 0 nvidia/cuda:12.2.0-base-ubuntu22.04 test-nvidia nvidia-smi
```
- 這時你就需要先自行裝好 `nvidia-container-toolkit`。
---
#### 🔒 2. **你希望有更細節的控制權,不讓 GPU Operator 動態裝東西(安全/可預測性)**
- 一些企業環境會要求節點內容固定,不希望 DaemonSet 在背景修改 runtime 設定。
- 此時你可以在安裝 GPU Operator 時加上:
```
--set toolkit.enabled=false
```
- 然後 **手動安裝與設定 containerd 的 NVIDIA runtime**。
---
### 📌 總結:是否需要手動裝 `nvidia-container-toolkit`?
| 情境 | 需手動安裝 toolkit? | 說明 |
|------|----------------------|------|
| 使用 GPU Operator(toolkit.enabled = true) | ❌ 否 | Operator 會自動安裝與設定 |
| 使用 GPU Operator(toolkit.enabled = false) | ✅ 是 | 你要自己裝好 toolkit 並設定 containerd |
| 想在 Operator 安裝前先測試 GPU 功能 | ✅ 是 | 可先手動裝 toolkit 驗證 runtime 可用性 |
| 自定義環境(CI、安全性高要求) | ✅ 是 | 建議你手動控制 toolkit 的版本與行為 |
<br>
{%hackmd vaaMgNRPS4KGJDSFG0ZE0w %}