K8S 1.20 棄用 Docker 評估之 Docker CLI 的替代產品

2023-02-28 12:01:05

背景

2020 年 12 月初,Kubernetes 在其最新的 Changelog 中宣佈,自 Kubernetes 1.20 之後將棄用 Docker 作為容器執行時。

棄用 Docker 帶來的,可能是一系列的改變,包括不限於:

  • 容器映象構建工具
  • 容器 CLI
  • 容器映象倉庫
  • 容器執行時

專題文章《K8S 1.20 棄用 Docker 評估》會從多方面分析由此帶來的變動和影響,上一篇:《K8S 1.20 棄用 Docker 評估之 Docker 和 OCI 映象格式的差別》 主要介紹 映象格式的變化,今天來介紹 Docker CLI 的替代產品及個人推薦。

Docker 命令簡介

這裡通過簡單介紹 Docker CLI 的命令,來引出 Docker 作為一個容器的完整 all-in-one 工具箱,具體包括了這麼幾大類:容器、映象及映象倉庫、容器網路的能力。

容器類常用命令

  1. 重新命名:docker rename [CONTAINER_NAME] [NEW_CONTAINER_NAME]
  2. 執行:docker run [IMAGE] [COMMAND]
  3. 刪除:docker rm [CONTAINER]
  4. 啟動:docker start [CONTAINER]
  5. 停止:docker stop [CONTAINER]
  6. 重啟:docker restart [CONTAINER]
  7. Kill:docker kill [CONTAINER]
  8. Attach:docker attach [CONTAINER]
  9. 執行狀態:docker ps
  10. 紀錄檔:docker logs [CONTAINER]
  11. Inspect:docker inspect [OBJECT_NAME/ID]
  12. Events:docker events [CONTAINER]
  13. Top:docker top [CONTAINER]
  14. Stats:docker stats [CONTAINER]

映象類常用命令

  1. 構建:docker build [URL]
  2. 打 Tag:docker tag
  3. 登入 DockerHub:docker login
  4. Pull:docker pull [IMAGE]
  5. Push:docker push [IMAGE]
  6. 匯入映象:docker import [URL/FILE]
  7. 從容器建立映象:docker commit [CONTAINER] [NEW_IMAGE_NAME]
  8. 刪除映象:docker rmi [IMAGE]
  9. 載入映象:docker load [TAR_FILE/STDIN_FILE]
  10. 儲存映象到 tar 包:docker save [IMAGE] > [TAR_FILE]
  11. 列出映象:docke image ls
  12. 映象歷史:docker history [IMAGE]

Docker 設定類命令

docker config

容器網路類常用命令

  1. 列出網路:docker network ls
  2. 連線:docker network connect [NETWORK] [CONTAINER]
  3. 斷開連線:docker network disconnect [NETWORK] [CONTAINER]

容器卷類常用命令

  1. 列出卷:docker volume ls
  2. 建立卷:docker volume create
  3. 刪除卷:docker volume rm

小結

在 K8S 場景下,容器網路類操作以及容器卷類的操作基本上都由 kubelet 來實現了,我們日常不需要太過關注。

容器類操作、容器工具的設定,在 K8S 裡,也是由 kubelet 來實現了,但是如果我們需要在個人機器上測試及偵錯,且不用 Docker 的話,那麼是需要找一個替代品。

至於映象類常用命令,特別是構建過程,K8S 預設不會涉及這一塊,那麼不用 Docker 的話,容器構建工具也是需要找一個替代品的。

Docker 替代品

Docker 執行時替代品

runC 實現主要是2個:

目前主流的選擇是:containerd,包括 K8S 社群和 Rancher 等。CRI-O 主要被 RedHat 的 OpenShift 4 採用。

除此之前的還有其他非 runC 的執行時,如:KatagVisor 等,使用較少,但也在增長。

Docker CLI 替代

Docker 映象構建替代品

Docker 映象構建替代品可選項有:

替代品懶人方案 - RedHat 開源的 3 件套:Buildah、Podman 和 Skopeo

先不提 K8S CRI 的替代。要替換掉 Docker,典型有以下方案:

  • Docker 貢獻的:nerdctl + buildkit
  • RedHat 開源的:Buildah、Podman 和 Skopeo

我推薦的是:RedHat 開源的 3 件套:Buildah、Podman 和 Skopeo,理由如下:

  • 功能齊全、強大:Buildah、Podman 和 Skopeo 可以完全覆蓋 Docker 的功能,並且還額外提供一些 Docker 沒有但是非常實用的功能,比如 docker 格式映象轉換為 oci 格式等。
  • 穩定、安全:這 3 套工具,早在 2019 年就開始大規模的應用在 RedHat 的 OpenShift 4 上面了,歷經多個版本迭代,安全 bug 修復較快,穩定性和安全有保障。
  • 平滑繼承:目前主流的企業 Linux 就是 RHEL 和 CentOS,它們的高版本自帶這 3 個工具,甚至預設通過 alias 將 docker 命令對映為這些工具,可以平滑繼承。
  • 可以整合到現有的 K8S 或 CICD 系統中
  • 在無根(rootless)模式下執行 - 無根容器更安全,因為它們執行時無需新增許可權
  • 不需要守護行程 - 這些工具在閒置時資源要求要小得多,因為當您沒有執行容器時,Podman 沒有執行,而 Docker 的守護行程總是執行。
  • 原生 systemd 整合 - Podman 允許您建立 systemd unit 檔案,並執行容器作為系統服務

下面做一些簡單的介紹。

Buildah Podman Skopeo 3 件套介紹

RedHat 提供了一組在沒有容器引擎的情況下可以執行的命令列工具。它們是:

  • podman - 用於直接管理 pod 和容器映象(runstopstartpsattachexec 等)
  • Buildah - 用於構建、推播和簽名容器映象
  • Skopeo - 用於複製、檢查、刪除和簽名映象

由於這些工具與 Open Container Initiative(OCI) 相容,所以它們可以用來管理由 Docker 和其他與 OCI 相容的容器 。另外,它們特別適用於直接在 Red Hat Enterprise Linux 或 CentOS 中執行在單節點用例。

Buildah 、Podman、Skopeo 工具都更加輕量級,並專注於一組特性。

Podman 簡介

設定

通過組態檔:/etc/containers/registries.conf$HOME/.config/containers/registries.conf 設定。範例:

[registries.search]
registries = ['quay.io', 'docker.io']

[registries.insecure]
registries = ['insecure-registry.example.com']

[registries.block]
registries = []

映象操作

設定好了之後可以

  1. 登入映象倉庫:podman login docker.io
  2. 搜尋映象:podman search quay.io/postgresql-10
  3. Pull 映象:podman pull <registry>[:<port>]/[<namespace>/]<name>:<tag>
  4. Push 映象:podman push registry.example.com:5000/postgresql/postgresql
  5. 列出映象:podman images
  6. 檢視映象:podman inspect docker.io/postgresql
  7. 打 Tag:podman tag docker.io/postgresql:10 mypg:10
  8. Save 映象: podman save -o myrsyslog.tar registry.redhat.io/rhel8/rsyslog:latest
  9. Load 映象:podman load -i myrsyslog.tar
  10. 刪除映象:podman rmi registry.example.com:5000/postgresql/postgresql

容器操作

  1. 列出容器:podman ps -a
  2. 停止容器:podman stop mypg
  3. 執行容器:podman run [options] image [command [arg ...]]
  4. 啟動容器:podman start mypg
  5. Inspect 容器:podman inspect 64ad94586c74
  6. 容器中執行命令:podman exec -it mypg /bin/bash
  7. Attach:podman attach mypg
  8. 匯出容器:podman export -o mypg.tar 64ad94586c74
  9. 匯入容器:podman import mypg.tar mypg-imported
  10. Kill:podman kill --signal="SIGHUP" 64ad94586c74
  11. 刪除:podman rm peaceful_hopper
  12. Top:podman pod top mypod
  13. Stats:podman pod stats -a --no-stream
  14. Inspect:podman pod inspect mypod

卷操作

  1. 建立:podman volume create hostvolume
  2. Inspect:podman volume inspect hostvolume
  3. 掛載:podman run -it --name myubi1 -v hostvolume:/containervolume1 registry.access.redhat.com/ubi8/ubi /bin/bash

Buildah 操作

  1. 構建映象:buildah bud -t caseycui/webserver .
  2. 多階段構建:buildah bud -t multi -f ~/Containerfile.multifrom .

Skopeo 簡介

Skepeo 非常強大,其中的一些功能非常使用,特別是在 Docker 向 OCI 轉變的階段。舉例說明:

在映象拉取到本地前,Inspect 遠端映象的資訊:

# skopeo inspect docker://registry.redhat.io/ubi8/ubi-init
{
    "Name": "registry.redhat.io/ubi8/ubi8-init",
    "Digest": "sha256:c6d1e50ab...",
    "RepoTags": [
        "8.2-13-source",
        "8.0-15",
        "8.1-28",
        ...
        "latest"
    ],
   "Created": "2020-12-10T07:16:37.250312Z",
    "DockerVersion": "1.13.1",
    "Labels": {
        "architecture": "x86_64",
        "build-date": "2020-12-10T07:16:11.378348",
        "com.redhat.build-host": "cpt-1007.osbs.prod.upshift.rdu2.redhat.com",
        "com.redhat.component": "ubi8-init-container",
        "com.redhat.license_terms": "https://www.redhat.com/en/about/red-hat-end-user-license-agreements#UBI",
        "description": "The Universal Base Image Init is designed to run an init system as PID 1 for running multi-services inside a container
        ...

映象複製,除了本地和映象倉庫之間的複製外,還支援複製到更多場景(如:S3 等):

$ skopeo copy \
docker://registry.access.redhat.com/ubi8:8.1-397-source \
dir:$HOME/TEST
...
Copying blob 477bc8106765 done
Copying blob c438818481d3 done
Copying blob 26fe858c966c done
Copying blob ba4b5f020b99 done
Copying blob f7d970ccd456 done
Copying blob ade06f94b556 done
Copying blob cc56c782b513 done
Copying blob dcf9396fdada done
Copying blob feb6d2ae2524 done
Copying config dd4cd669a4 done
Writing manifest to image destination
Storing signatures

使用認證檔案進行操作:skopeo inspect --creds=./auth.json docker://$IMAGE

❗️ 實用功能: docker 格式映象和 oci 格式映象相互轉換:

skopeo copy oci:/tmp/myimage docker://registry.example.com/myimage
podman run docker://registry.example.com/myimage

skopeo copy docker://registry.example.com/myimage oci:/tmp/myimage 
podman run oci:/tmp/myimage  

❗️ 實用功能: 打成 docker 格式的 tar 包或 oci 格式的 tar 包:

skopeo copy docker://registry.fedoraproject.org/fedora:latest docker-archive:/tmp/fedora.img
podman run docker-archive:/tmp/fedora.img echo hello

skopeo copy docker-archive:/tmp/fedora.img oci-archive:/tmp/fedora-oci.img
podman run oci-archive:/tmp/fedora-oci.img echo hello

小結

通過上面也能看到,podman 基本上能替換 docker 的所有命令,而且命令的引數、格式等基本上和 docker cli 是一致的,替換和學習成本都不高。

總結

其實說實話,Docker CLI 的替換得分情況:

  1. K8S Node 上,CRI 已經從 Docker 替換為 containerd 或 CRI-O,那麼這時候 K8S Node 上已經沒有 docker cli 了,那麼我推薦你使用:nerdctl + buildkit (Node 上一般也不會進行映象構建操作吧?映象構建操作一般在 CICD 機器上或容器中)或 Buildah + Podman + Skopeo 三件套。其中 Skopeo 在 Docker 替換為其他的過程中用途還是挺大的;
  2. 個人電腦、開發測試機、CICD 節點等非 K8S Node 上:建議還是使用 Docker。省心省力和熟悉。打出來的映象 K8S 也能用。