---
# System prepended metadata

title: '[建置] 安裝 K8s / 釐清 GPU Operator, NVIDIA Device Plugin, nvidia-container-runtime, containerd 的關係'
tags: [k8s, nvidia-container-runtime, GPU Operator, containerd, install, setup, gpu-operator, K8s / Setup, Kubernetes]

---

[建置] 安裝 K8s / 釐清 GPU Operator, NVIDIA Device Plugin, nvidia-container-runtime, containerd 的關係
===
###### tags: `K8s / Setup`
###### tags: `Kubernetes`, `k8s`, `setup`, `install`, `containerd`, `nvidia-container-runtime`, `GPU Operator`, `gpu-operator`

<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 %}