0-容器引擎 Containerd&&Docker -- (Kubernetes 1.24 開始,刪除了對 Docker(Dockershim)的容器運行時接口(CRI)的支持)
Containerd已成Kubernetes“新寵”
Docker 曾經是最早廣泛使用的容器運行時,這也使用戶對 Docker 非常熟悉。Kubernetes 最初支持 Docker 是通過在項目中內置了一個組件稱為 "dockershim" 來實現的。隨著容器生態系統的發展,Kubernetes 逐漸增加了對其他容器運行時的支持,以提供更多選擇和靈活性。
Kubernetes 引入容器運行時接口(Container Runtime Interface,CRI),使 Kubernetes 的系統組件能夠與不同容器運行時進行通信。這一變化使 Kubernetes 更加靈活,能夠支持多個容器運行時,而不僅限于 Docker。隨著對 Docker 和 dockershim 的依賴逐漸減弱, Kubernetes 的用戶現在可以選擇其他容器運行時,如Containerd、 CRI-O 等。減少了對 Docker 的硬編碼依賴,降低了 Kubernetes 項目的復雜性,提升 Kubernetes 服務的運行速度。
從 Kubernetes 1.24 開始,刪除了對 Docker(Dockershim)的容器運行時接口(CRI)的支持。同時Amazon EKS 官方也將 Containerd 作為唯一的運行時。
那么 Containerd 是什么,怎么用?接下來我們將一一揭曉
Containerd 誕生
概述
Containerd 是一個用于管理容器的開源項目,它起源于 Docker 項目,是 Docker 引擎的一部分。下面是 Containerd 的前世今生[1]。
- Containerd 的前世
Docker 最初是一個獨立的開源項目,旨在提供容器化應用程序的解決方案。Docker 引擎是 Docker 項目的核心組件,負責容器的創建、運行和管理。然而,隨著時間的推移,Docker 項目不斷壯大,引入了許多新功能和組件,變得越來越復雜。這導致了 Docker 引擎的模塊化需求,以便更容易維護和擴展。
- Containerd 的誕生
應對 Docker 引擎的復雜性問題,Docker 項目決定將引擎中的一部分核心功能抽象出來并開源,這就是 Containerd 項目的誕生。Containerd 專注于容器的基本操作,如鏡像管理、容器運行時和容器生命周期管理等,它提供了一個統一的接口,供容器管理工具使用。
- Docker 和 Containerd 的關系
Docker 引擎與 Containerd 之間的關系可以被視為 “上游” 和 “下游” 的關系。Docker 引擎構建在 Containerd 之上,它使用 Containerd 來管理容器的基本功能。因此,Containerd 可以被認為是 Docker 引擎的核心部分之一。如下圖所示:
- CNCF 和 OCI 的支持
Containerd 項目在 2017 年 3 月加入了云原生計算基金會(CNCF)[2],這是一個開源項目的管理組織,旨在促進云原生技術的發展。此外,Containerd 也符合開放容器倡議(Open Container Initiative,OCI)的規范,這是一個定義容器標準的組織。
Containerd 與 Docker 差異
Containerd 架構
邏輯架構
Containerd 是一種注重簡單性、健壯性和可移植性的行業標準容器運行時。它可作為 Linux 和 Windows 的守護進程,可以管理其主機系統的完整容器生命周期,包括鏡像傳輸和存儲、容器執行和監督、底層存儲和網絡附加等功能[3]。
上圖展示了 Containerd 的主要組件:
1. Runtime:Containerd 負責容器的生命周期管理,包括容器的創建、運行和事件管理等。
2. Storage:Containerd 提供鏡像存儲管理。它負責容器鏡像的存儲、檢索和管理。
3. gRPC:Containerd 使用 gRPC 服務器來與上層應用程序通信,為上層提供容器管理服務的接口。gRPC 是一種遠程過程調用協議,使容器管理操作可以通過網絡進行。
4. Metrics:Containerd 提供了有關容器性能和資源使用的指標,主要涉及 cgroup(控制組)的性能指標。
5. Metadata:容器的元數據,如鏡像和容器的信息,以及與其相關的元數據,存儲在 bootfs 中。這些元數據用于容器的管理和操作。
6. Tasks:在 Containerd 中,容器結構被管理為任務(tasks)。這包括容器的運行狀態、進程信息和其他相關數據。
7. Events:Containerd 生成事件以通知上層應用程序容器的狀態變化。這使上層應用程序能夠訂閱這些事件,以獲知容器的狀態變化,以及采取相應的操作。
架構應用
Containerd 旨在嵌入到更大的系統中,而不是直接由開發人員或最終用戶使用,在 kubernetes 中應用最為廣泛。下圖由 Containerd 官方提供,從圖中可以看出,Containerd 為 C/S 架構,通過 gRPC 暴漏接口供不同的客戶端進行集成調用。
Containerd 使用
安裝
通過源安裝
containerd.io 包在 DEB 和 RPM 格式中的分發由 Docker 而不是 Containerd 項目本
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install containerd.io
也可通過二進制安裝[4]。
# containerd.io 中包含的組件
# rpm -ql containerd.io
/etc/containerd
/etc/containerd/config.toml
/usr/bin/containerd
/usr/bin/containerd-shim
/usr/bin/containerd-shim-runc-v1
/usr/bin/containerd-shim-runc-v2
/usr/bin/ctr
/usr/bin/runc
/usr/lib/systemd/system/containerd.service
/usr/share/doc/containerd.io-1.6.19
/usr/share/doc/containerd.io-1.6.19/README.md
/usr/share/licenses/containerd.io-1.6.19
/usr/share/licenses/containerd.io-1.6.19/LICENSE
/usr/share/man/man5/containerd-config.toml.5
/usr/share/man/man8/containerd-config.8
/usr/share/man/man8/containerd.8
/usr/share/man/man8/ctr.8
客戶端工具
ctr是 Containerd 的官方命令行客戶端工具。它提供了用于容器和鏡像操作的命令行接口。您可以使用 ctr來創建、管理和監視容器,以及處理容器鏡像。
# ctr
NAME:
ctr -
__
_____/ /______
/ ___/ __/ ___/
/ /__/ /_/ /
\___/\__/_/
Containerd CLI
USAGE:
ctr [global options] command [command options] [arguments...]
VERSION:
1.6.19
DESCRIPTION:
ctr is an unsupported debug and administrative client for interacting
with the Containerd daemon. Because it is unsupported, the commands,
options, and operations are not guaranteed to be backward compatible or
stable from release to release of the Containerd project.
COMMANDS:
plugins, plugin provides information about Containerd plugins
version print the client and server versions
containers, c, container manage containers
content manage content
events, event display Containerd events
images, image, i manage images
leases manage leases
namespaces, namespace, ns manage namespaces
pprof provide golang pprof outputs for Containerd
run run a container
snapshots, snapshot manage snapshots
tasks, t, task manage tasks
install install a new package
oci OCI tools
shim interact with a shim directly
help, h Shows a list of commands or help for one command
GLOBAL OPTIONS:
--debug enable debug output in logs
--address value, -a value address for Containerd's GRPC server (default: "/run/Containerd/Containerd.sock") [$Containerd_ADDRESS]
--timeout value total timeout for ctr commands (default: 0s)
--connect-timeout value timeout for connecting to Containerd (default: 0s)
--namespace value, -n value namespace to use with commands (default: "default") [$Containerd_NAMESPACE]
--help, -h show help
--version, -v print the version
命名空間
Containerd 提供完全隔離的 API,使多用戶能夠同時使用單個 containerd 實例而不會相互沖突。
命名空間允許在單個守護進程中實現多租戶功能。用戶可以擁有具有相同名稱但具有不同功能或配置的容器。例如,系統或基礎架構級容器可以隱藏在一個命名空間中,而用戶級容器可以保留在另一個命名空間中。底層鏡像內容仍然是通過內存地址共享的,但是image名稱和metadata在每個命名空間中是單獨的。
需要注意 Containerd 實現的命名空間是一種管理形式,不具有安全功能。客戶端可以輕松切換命名空間,不能提供安全隔離。
- 查看命名空間
# ctr ns ls
NAME LABELS
default
moby
- 創建命名空間
# ctr ns create test
# ctr ns ls
NAME LABELS
default
moby
test
- 刪除命名空間
# ctr ns rm test
test
鏡像操作
- 下載鏡像
# ctr image pull public.ecr.aws/nginx/nginx:1.25
public.ecr.aws/nginx/nginx:1.25: resolved |++++++++++++++++++++++++++++++++++++++|
index-sha256:56fae3726ce208394da92a3ac447caacfccd59d8325f700b8542e6faf614cc4a: done |++++++++++++++++++++++++++++++++++++++|
manifest-sha256:d2e65182b5fd330470eca9b8e23e8a1a0d87cc9b820eb1fb3f034bf8248d37ee: done |++++++++++++++++++++++++++++++++++++++|
layer-sha256:c1dfc7e1671e8340003503af03d067bae6846c12c30cbc1af3e589cb124fd45d: done |++++++++++++++++++++++++++++++++++++++|
config-sha256:c20060033e06f882b0fbe2db7d974d72e0887a3be5e554efdb0dcf8d53512647: done |++++++++++++++++++++++++++++++++++++++|
layer-sha256:578acb154839e9d0034432e8f53756d6f53ba62cf8c7ea5218a2476bf5b58fc9: done |++++++++++++++++++++++++++++++++++++++|
layer-sha256:e398db710407fbc310b4bc0b0db1c94161480ac9b44638c6655939f426529780: done |++++++++++++++++++++++++++++++++++++++|
layer-sha256:85c41ebe6d660b75d8e2e985314ebce75e602330cd325bc5cfbf9d9723c329a1: done |++++++++++++++++++++++++++++++++++++++|
layer-sha256:7170a263b582e6a7b5f650b7f1c146267f694961f837ffefc2505bb9148dd4b0: done |++++++++++++++++++++++++++++++++++++++|
layer-sha256:8f28d06e2e2ec58753e1acf21d96619aafeab87e63e06fb0590f56091db38014: done |++++++++++++++++++++++++++++++++++++++|
layer-sha256:6f837de2f88742f4e8083bff54bd1c64c1df04e6679c343d1a1c9a650078fd48: done |++++++++++++++++++++++++++++++++++++++|
elapsed: 12.7s total: 67.3 M (5.3 MiB/s)
unpacking linux/amd64 sha256:56fae3726ce208394da92a3ac447caacfccd59d8325f700b8542e6faf614cc4a...
done: 1.889424578s
- 查看鏡像
# ctr images ls
REF TYPE DIGEST SIZE PLATFORMS LABELS
public.ecr.aws/nginx/nginx:1.25 application/vnd.docker.distribution.manifest.list.v2+json sha256:56fae3726ce208394da92a3ac447caacfccd59d8325f700b8542e6faf614cc4a 67.3 MiB linux/amd64,linux/arm64/v8 -
- 刪除鏡像
# ctr images delete public.ecr.aws/nginx/nginx:1.25
public.ecr.aws/nginx/nginx:1.25
- 將鏡像掛載到主機目錄
將容器鏡像掛載到指定的目標路徑。這個命令允許你在主機上查看容器鏡像的文件系統,以便瀏覽、檢查或修改容器中的文件。
# ctr image mount public.ecr.aws/nginx/nginx:1.25 /mnt/
sha256:32cf0b3c70998330104acfc1a02f6aae2f8a728bc6ad91c2415fda501593fa81
/mnt/
# cd /mnt
# ls
bin dev docker-entrypoint.sh home lib32 libx32 mnt proc run srv tmp var
boot docker-entrypoint.d etc lib lib64 media opt root sbin sys usr
容器操作
- 創建容器
# ctr c create public.ecr.aws/nginx/nginx:1.25 nginx
# ctr c ls
CONTAINER IMAGE RUNTIME
nginx public.ecr.aws/nginx/nginx:1.25 io.Containerd.runc.v2
- 查看容器詳情
# ctr c info nginx
- 刪除容器
# ctr c del nginx
任務操作
在 Containerd 中,容器對象可以看作是一個配置和資源的抽象,它包含容器的各種設置、rootfs(容器的文件系統)等。容器對象本身并不運行,只是一個配置狀態。要實際運行容器,需要通過創建和啟動任務(Task)來執行容器內的進程。
任務(Task)是 Containerd 中的實體,它代表容器內的運行時環境。一個容器可以包含一個或多個任務,每個任務對應容器內的一個進程或進程組。任務用于管理容器內的進程,包括創建、啟動、停止和監控。
想要啟動容器,需要使用 ctr task 命令創建一個任務,并將其關聯到容器對象。任務會負責啟動容器內的主要進程,例如應用程序。此過程確保容器的進程以正確的方式在容器內執行。
- 啟動任務
# ctr c ls
CONTAINER IMAGE RUNTIME
nginx public.ecr.aws/nginx/nginx:1.25 io.containerd.runc.v2
# ctr task start -d nginx
# ctr task ls
TASK PID STATUS
nginx 67132 RUNNING
- 進入容器
# ctr t exec -t --exec-id 0 nginx bash
# ls
bin dev docker-entrypoint.sh home lib32 libx32 mnt proc run srv tmp var
boot docker-entrypoint.d etc lib lib64 media opt root sbin sys usr
- 停止任務
# ctr t ls
TASK PID STATUS
nginx 67132 RUNNING
# ctr t kill nginx
# ctr t ls
TASK PID STATUS
nginx 67132 STOPPED
- 刪除任務
# ctr t rm nginx
通過編寫podls和podenter命令, 簡化操作
從Kubernetes 1.24開始,用戶均須使用Containerd作為容器運行時。然而,由于Containerd與Docker在使用方式上有所差異,用戶在排查Kubernetes Node上將會遇到很大的挑戰。針對這個問題,聚云科技針對性給出簡化排查方案,通過編寫podls和podenter命令,用戶可以使用 Containerd 自帶ctr來快速列出容器和進入容器。這些自定義命令的輸出與Docker的樣式相似,使得用戶可以更加快速地上手使用,找到需要的容器,從而大大簡化了故障排除過程。
- 列出主機上容器
- 命令執行詳情
# podls
TaskID Namespace PodName ContainerName
884be98a85717f58eb348af1510dc0e83077f37bcc63a7f82980047c4d3a4b12 kubecost kubecost-network-costs-9ghdj kubecost-network-costs
0a92e5b7d9de06283d5de4fb96431b966dc3f23ec2604fdbf7ca9f37c015e29c monitoring alertmanager-main-2 config-reloader
a44029681a617d6721fdacf483e509bbf7bf0da0a006e4d768bc74338bfcc287 monitoring alertmanager-main-2 alertmanager
4c8be9a3c3fa828e1d1287e7f54e56e75a1f8abceaba0d5b44c0b7b8ce45adfb monitoring node-exporter-5hsr6 kube-rbac-proxy
734b3cdec3990f5b4176c27cf6b147f049546b750253cc813ddcda3977853347 monitoring node-exporter-5hsr6 node-exporter
e0971f27d8701a2099cdb22590b067f85b711f6b4e96acf7b9ee24624be77776 monitoring process-exporter-kxdxn process-exporter
4d6570e7cc7ede80eaf2ec7b23ea500def34b967b08a64653b2510328f37d448 monitoring prometheus-k8s-0 config-reloader
8249f57e1938f284b65259d44cb93c82e31542f98b1138b5e3bb086487221690 monitoring prometheus-k8s-0 prometheus
- 命令源碼
#!/bin/bash
# podls 列出主機上容器
# 屏蔽系統命名空間 kube-system
containerHeader=$(echo -e "TaskID\tNamespace\tPodName\tContainerName" )
# 獲取 task 列表
taskInfo=$(ctr -n k8s.io task ls -q |tr "\n" "|" | sed 's#|$##g')
# 獲取容器列表
taskData=$(
for i in `ctr -n k8s.io c ls -q`; do
ctr -n k8s.io c info $i |\
jq '.ID, .Labels."io.kubernetes.pod.namespace", .Labels."io.kubernetes.pod.name", .Labels."io.kubernetes.container.name" ' |\
tr -d \" | \
tr "\n" "\t";
echo ;
done | \
sort -t$'\t' -k2,2 -k3,3 |\
grep -Ev "kube-system|null" | \
grep -E "${taskInfo}"
)
# 格式化輸出
echo -e "${containerHeader}\n${taskData}" | column -t
- 進入容器
- 命令執行詳情
# 進入到某個容器中
# podenter 8249f57e1938f284b65259d44cb93c82e31542f98b1138b5e3bb086487221690 sh
/prometheus $ ps -ef
PID USER TIME COMMAND
1 1000 5d07 /bin/prometheus --web.console.templates=/etc/prometheus/consoles
23 1000 0:00 sh
29 1000 0:00 ps -ef
- 命令源碼
#!/bin/bash
# podenter 登錄 pod
# 需要先通過 podls 獲取到 pod 列表
podid=$1
podcmd=$2
function display_help() {
cat << "EOF"
Usage:
podenter TaskID CMD
EOF
}
if [ $# -ne 2 ]; then
display_help
exit 1
else
ctr -n k8s.io task exec -t --exec-id 1 ${podid} ${podcmd}
fi
總結
作為一個開源的容器運行時項目,Containerd的發展和應用對于容器化技術的生態系統具有重要意義。雖然Containerd在多個方面具有明顯的優勢,但也存在一些限制,特別是在高級容器功能方面需要額外的注意。Containerd的定位是為容器生態系統提供一個通用的、標準化的容器運行時,以支持容器化應用程序的生命周期管理,而不是為最終用戶提供一個完整的容器解決方案。

浙公網安備 33010602011771號