---
# System prepended metadata

title: '[調度] CRI'
tags: [k8s, Container Runtime Interface, CRI, Kubernetes, K8s]

---

[調度] CRI
===
###### tags: `K8s`
###### tags: `Kubernetes`, `k8s`, `CRI`, `Container Runtime Interface`

<br>

[TOC]

<br>

## 術語
- CRI: Container Runtime Interface

<br>

## 討論

### 🔍 Kubernetes 使用 image 時會呼叫 docker 嗎？
- ### gpt-4o (2025/04/24)
    這是一個常見但經常被誤解的問題，以下幫你詳細說明 Kubernetes 在使用 image 時到底是使用哪個工具處理的。

    ---

    ### ✅ 問題核心

    > **Kubernetes 在使用 image 時，是用自己的 OCI 工具，還是用 docker？**

    **簡短答案：**
    Kubernetes **不會直接使用 `docker` CLI**，而是透過一個叫做 **CRI（Container Runtime Interface）** 的介面，來呼叫底層的 container runtime，如：

    - `containerd`
    - `CRI-O`
    - （舊版）`docker`（透過 `docker-shim`，但已淘汰）

    ---

    ### 🧠 詳細說明

    #### 1. Kubernetes 並不綁定 docker

    Kubernetes 使用 CRI（Container Runtime Interface）與底層 container runtime 溝通，它本身不執行 `docker pull` 或 `docker run`。

    也就是說：

    - `kubectl apply`
    - `kubectl create`
    - `kubectl run`

    這些都**不會呼叫 docker CLI**，而是透過 CRI 去讓 container runtime 去處理 image 的拉取與容器啟動(image pull & create container)。

    ---

    #### 2. `docker-shim` 已於 Kubernetes v1.24 移除

    在舊版 Kubernetes（v1.23 以前），Kubelet 可以透過 `docker-shim` 呼叫 Docker Engine。

    > ✅ 但從 **v1.24 開始，官方已移除 `docker-shim`**

    所以從 v1.24 起，**Kubernetes 無法再使用 Docker 當作 container runtime。**

    現在主流的 container runtimes 是：
    - `containerd`（Docker 內部其實也是用它）
    - `CRI-O`（Red Hat 系列偏好）
    - `gVisor`（Google 用於高安全環境）

    ---

    #### 3. 那為什麼我還能在 node 上用 `docker`？

    你可能自己安裝了 Docker Engine，因此你在 K8s 的 master 或 node 上可以執行：

    ```
    docker ps
    docker run
    ```

    但這只是這台機器額外裝了 Docker Engine，**Kubernetes 並不會透過它來啟動 Pod。**

    ---

    ### ✅ 總結圖示：Kubernetes container 執行流程

    ```
    kubectl
       │
       ▼
    kubelet
       │
       ▼
    Container Runtime Interface (CRI)
       ├── containerd
       ├── CRI-O
       └── [X] docker-shim (v1.24+ 移除)
    ```

    ---

    ### 🔍 那 `docker` CLI 是做什麼的？

    `docker` CLI 只是你自己操作的命令列工具，跟 Kubernetes 沒有直接關聯。你能用 `docker ps`，只是因為你裝了 Docker Engine 而已。

    但：
    - Kubernetes 的 `Pod` 並不是由這個 `docker` CLI 啟動
    - Kubernetes 使用自己的 CRI 註冊好的 runtime

    ---

    ### ✅ 如何查出我的節點正在用哪個 runtime？

    可以執行以下指令：

    ```
    kubectl get node <your-node-name> -o json \\
      | jq '.status.nodeInfo.containerRuntimeVersion'
    ```

    可能會回傳：

    - `containerd://1.6.15`
    - `cri-o://1.23.2`
    - `docker://20.10.7`（如果你是舊版 Kubernetes）

    ---

    ### ✅ 結論整理

    | 問題 | 回答 |
    |------|------|
    | Kubernetes 會不會使用 `docker` CLI？ | ❌ 不會 |
    | Kubernetes 如何處理 image 與 container？ | ✅ 透過 CRI 與 container runtime（如 containerd） |
    | `docker` CLI 在 node 上還能用？ | ✅ 可以，因為 Docker Engine 仍可裝 |
    | Kubernetes 還支援 Docker 嗎？ | ❌ v1.24 起已移除 docker-shim |

    ---

    ### 💡 延伸應用

    若你要在安裝流程中依據 runtime 調整邏輯，例如：

    - containerd 就走 A 路徑
    - docker (若是舊版) 就警告
    - cri-o 用特定 image 轉換方式

    可以透過前述指令去動態偵測，並搭配條件判斷處理。

    需要我幫你寫一段判斷 runtime 的 Python 程式嗎？😄

    
<br>

### shim 是什麼縮寫？實際意思是什麼？
- ### gpt-4o (2025/04/24)
    `shim` 並不是縮寫，而是一種「軟體設計概念」

    ### 👉 `shim` 的原始意義：
    > 在英文中，**shim** 是指「墊片、間隔片」，用來填補機械零件之間的空隙。  
    > 在 **軟體領域** 中，`shim` 通常指的是：
    > 
    > **「一個介於兩個系統之間，用來做兼容或轉接的小層程式碼。」**

    ---

    ### 🧠 軟體中的 shim 是什麼？

    | 特性     | 說明                                       |
    |----------|--------------------------------------------|
    | 類型     | 一種 adapter pattern（轉接器設計模式）     |
    | 功能     | 幫助「新系統」與「舊系統」之間做兼容       |
    | 常見用途 | API 相容層、底層切換、版本轉換、相依解耦等 |
    | 類似詞彙 | Adapter, Middleware, Proxy                 |

    ---

    ### 🔧 Kubernetes 中的 `docker-shim` 是什麼？

    早期 Kubernetes 支援的 container runtime 是 Docker，  
    但 Kubernetes 本身並不直接控制 Docker，而是透過 **CRI（Container Runtime Interface）**。

    因此，為了解耦 Kubernetes 和 Docker，官方就做了一個中間層 **`docker-shim`**：

    > `docker-shim` 的作用：  
    > **將 kubelet 的 CRI 請求轉換成 Docker Engine 可以理解的命令**

    流程圖簡化如下：
    ```
    Kubernetes → CRI → docker-shim → Docker Engine
    ```

    ---

    ### 🔥 為何 `docker-shim` 被移除？

    | 原因 | 說明 |
    |-----|------|
    | Docker 並非原生 CRI runtime  | 本質不符合 K8s 要求的 CRI 標準 |
    | Docker 本身就使用 containerd | 多一層轉接等於效率變差、維護成本變高 |
    | containerd/CRI-O 已成主流 | Kubernetes 官方推薦直接使用 containerd 或 CRI-O |

    > ✅ 自 **Kubernetes v1.24** 起，`docker-shim` 已完全 **移除**

    ---

    ### ✅ 總結說明

    | 問題                     | 答案                                                             |
    |--------------------------|------------------------------------------------------------------|
    | `shim` 是縮寫嗎？        | ❌ 不是，是代表一種「中介轉接層」的軟體設計概念                 |
    | `docker-shim` 是什麼？   | 將 CRI 呼叫轉成 Docker CLI 語法的轉接層                         |
    | 現在還需要 docker-shim？ | ❌ 不再需要，自 K8s v1.24 起被移除                             |
    | 替代方案                 | ✅ 使用 `containerd`、`CRI-O` 等原生支援 CRI 的 container runtime |

    ---

    如果你想了解 docker-shim 的原始碼架構，或需要流程圖解釋其運作原理，也可以提出，我可以補上 🔧

<br>

### 
- ### gpt-4o (2025/04/24)

<br>

### 🔍 CRI-O 使用 image 的方式與 Docker 有什麼不同？
- ### gpt-4o (2025/04/24)
    本文說明 CRI-O 在 Kubernetes 中處理 image 的方式、與 Docker 的差異，以及你提到的「特定 image 轉換方式」是什麼意思。

    ---

    ### ✅ CRI-O 是什麼？

    - **CRI-O** 是符合 Kubernetes CRI（Container Runtime Interface）的 container runtime。
    - 它不需要 Docker，且設計上是為了讓 K8s 可以直接透過它執行 container。
    - CRI-O **不需要 Docker**，它使用更底層的技術，如：
      - `runc`: 執行 container
      - `skopeo`, `podman`, `buildah`: 管理與轉換 image

    ---

    ### ✅ Docker 與 CRI-O 處理 image 的差異

    | 項目 | Docker | CRI-O |
    |------|--------|--------|
    | 支援格式        | 主要支援 Docker image 格式 | 支援 Docker image + OCI 格式 |
    | 拉取 image     | `docker pull` | `crictl pull` / `podman pull` |
    | 匯入 image tar | `docker load -i xxx.tar` | ❌ 無對應指令（需轉換） |
    | 管理工具        | `docker` CLI | `crictl`, `podman`, `skopeo` |

    ---

    ### ❗ 為何 CRI-O 不能用 `docker load`？

    - 在 Docker 裡可以用：
      ```
      docker load -i myimage.tar
      ```
    - 但在 CRI-O 中：
      - **沒有等效的 `crictl load`**，所以無法直接匯入 `.tar`
      - 必須透過轉換工具，如 `skopeo`, `podman`

    ---

    ### ✅ 如何讓 CRI-O 使用 image tar？

    #### 方法 1：使用 `skopeo` 轉換 image tar 到目標格式或 registry

    ```
    # Copy image tar into CRI-O compatible registry or storage
    skopeo copy docker-archive:myimage.tar \
             dir:/var/lib/containers/storage/converted-image
    # or
    skopeo copy docker-archive:myimage.tar \
                 docker://localhost:5000/myimage:tag
    ```
    這會將 image 推送到本地 registry，K8s 就可以從那裡拉。

    或者如果你有一個私有 registry：
    ```
    skopeo copy docker-archive:myimage.tar \
                 docker://localhost:5000/myimage:tag
    ```
    這樣就可以讓 CRI-O 從 registry 中 pull 這個 image。


    #### 方法 2：使用 `podman` 載入再推送

    因為 `podman` 與 CRI-O 使用相同儲存後端，你可以：

    ```bash
    # 先用 podman 載入
    podman load -i myimage.tar

    # 然後用 podman push 到本地 registry
    podman push localhost/myimage:tag \
                docker://localhost:5000/myimage:tag
    ```

    再由 Kubernetes 使用該 registry 來抓 image。

    ---

    ### ✅ 結論整理
    | 問題 | 回答 |
    |------|----|
    | CRI-O 支援 docker image 嗎？ | ✅ 可以，但更偏好 OCI 格式 |
    | 可以直接 docker load 嗎？ | ❌ 不行，要用 podman, skopeo 來轉換 |
    | K8s 如何讓 CRI-O 用到某個 image？ | 推 image 到 registry，再讓 Pod pull |
    | 有沒有直接從 tar 載入的做法？ | 用 skopeo copy 或 podman load + push |

    ### 📦 CRI-O image 處理流程與 Docker 對照

    ```text
    Docker:
      docker load → local image store → run

    CRI-O:
      tar image → (skopeo/podman push) → registry → kubelet/cri-o pull
    ```


<br>

{%hackmd vaaMgNRPS4KGJDSFG0ZE0w %}