一文帶你了解Docker與Containerd的區(qū)別
容器運(yùn)行時(shí)
容器運(yùn)行時(shí)(Container Runtime)是一種負(fù)責(zé)在操作系統(tǒng)層面創(chuàng)建和管理容器的軟件工具或組件。它是容器化技術(shù)的核心組件之一,用于在容器內(nèi)部運(yùn)行應(yīng)用程序,并提供隔離、資源管理和安全等功能。 在Kubernetes中,容器運(yùn)行時(shí)是負(fù)責(zé)管理和運(yùn)行容器的組件。在過去,Docker是最常用的容器運(yùn)行時(shí),但隨著時(shí)間的推移,containerd成為Kubernetes的另一個(gè)受歡迎的容器運(yùn)行時(shí)選擇。
說明:自 kubernetes 1.24 版起,Dockershim 已從 Kubernetes 項(xiàng)目中移除。
容器運(yùn)行時(shí)的主要任務(wù)包括:
- 容器創(chuàng)建和啟動(dòng):容器運(yùn)行時(shí)負(fù)責(zé)根據(jù)預(yù)定義的容器配置信息(如鏡像、命令、環(huán)境變量等),創(chuàng)建并啟動(dòng)容器實(shí)例。
- 容器文件系統(tǒng)管理:容器運(yùn)行時(shí)處理容器的文件系統(tǒng),負(fù)責(zé)將鏡像的內(nèi)容掛載到容器的文件系統(tǒng),并在容器之間提供隔離。
- 資源限制和管理:容器運(yùn)行時(shí)可以根據(jù)用戶或管理員定義的資源限制,管理容器對(duì)CPU、內(nèi)存、磁盤等資源的使用。
- 容器網(wǎng)絡(luò):容器運(yùn)行時(shí)協(xié)助配置容器的網(wǎng)絡(luò),使得容器可以與其他容器或外部網(wǎng)絡(luò)進(jìn)行通信。
- 安全性:容器運(yùn)行時(shí)實(shí)施安全機(jī)制,確保容器之間和宿主機(jī)之間的隔離,并防止容器中的惡意行為影響其他容器或宿主機(jī)。
在當(dāng)今云原生技術(shù)的潮流中,容器化技術(shù)已經(jīng)成為現(xiàn)代應(yīng)用部署的主流選擇。Kubernetes (K8s) 作為一種流行的容器編排系統(tǒng),廣泛應(yīng)用于大規(guī)模的容器集群管理。而在K8s中,容器運(yùn)行時(shí)的選擇對(duì)于性能、可靠性和安全性都起著至關(guān)重要的作用。本文將對(duì)比兩種常見的K8s容器運(yùn)行時(shí):Containerd和Docker,并探討它們的異同點(diǎn)。
Docker:原先的翹楚
Docker作為一種早期的容器技術(shù),它的出現(xiàn)顛覆了傳統(tǒng)虛擬化方式,通過輕量級(jí)容器化的方式實(shí)現(xiàn)了應(yīng)用的打包、交付和運(yùn)行。Docker在容器技術(shù)的普及過程中發(fā)揮了關(guān)鍵作用,其用戶友好的命令行工具和圖形化界面讓容器技術(shù)對(duì)廣大開發(fā)者變得更加友好和易用。一度,Docker幾乎成為容器化的代名詞。 然而,隨著Kubernetes的興起,Docker在K8s中的地位逐漸受到挑戰(zhàn)。一方面,Docker作為一個(gè)完整的容器平臺(tái),包含了許多K8s并不需要的功能,導(dǎo)致資源浪費(fèi)。另一方面,K8s本身提供了容器編排和調(diào)度的功能,與Docker重疊,造成了一定程度上的沖突。 為了防止docker一家獨(dú)大,docker當(dāng)年的實(shí)現(xiàn)被拆分出了幾個(gè)標(biāo)準(zhǔn)化的模塊,標(biāo)準(zhǔn)化的目的是模塊是可被其他實(shí)現(xiàn)替換的,不由任何一個(gè)廠商控制。 Docker 由
- docker-client
- dockerd
- containerd
- docker-shim
- runc
組成,所以containerd是docker的基礎(chǔ)組件之一,docker 對(duì)容器的管理和操作基本都是通過 containerd 完成的。 那么,containerd 是什么呢?
Containerd:K8s生態(tài)系統(tǒng)的標(biāo)配
Containerd是由Docker團(tuán)隊(duì)開源的容器運(yùn)行時(shí),它專注于提供輕量級(jí)、高性能的容器運(yùn)行環(huán)境。作為一個(gè)純粹的容器運(yùn)行時(shí),Containerd被設(shè)計(jì)為更加符合K8s的架構(gòu)和需求。它具有更小的資源占用,更快的啟動(dòng)時(shí)間,以及更好的性能表現(xiàn)。 K8s社區(qū)認(rèn)可了Containerd的優(yōu)勢,并將其作為K8s生態(tài)系統(tǒng)的標(biāo)配容器運(yùn)行時(shí)。 Containerd 可以在宿主機(jī)中管理完整的容器生命周期:容器鏡像的傳輸和存儲(chǔ)、容器的執(zhí)行和管理、存儲(chǔ)和網(wǎng)絡(luò)等。詳細(xì)點(diǎn)說,Containerd 負(fù)責(zé)干下面這些事情:
- 管理容器的生命周期(從創(chuàng)建容器到銷毀容器)
- 拉取/推送容器鏡像
- 存儲(chǔ)管理(管理鏡像及容器數(shù)據(jù)的存儲(chǔ))
- 調(diào)用 runC 運(yùn)行容器(與 runC 等容器運(yùn)行時(shí)交互)
- 管理容器網(wǎng)絡(luò)接口及網(wǎng)絡(luò)
容器運(yùn)行時(shí)接口(CRI)
容器運(yùn)行時(shí)接口(Container Runtime Interface),簡稱 CRI。 CRI 是一個(gè)插件接口,它使 kubelet 能夠使用各種容器運(yùn)行時(shí),無需重新編譯集群組件。 你需要在集群中的每個(gè)節(jié)點(diǎn)上都有一個(gè)可以正常工作的容器運(yùn)行時(shí), 這樣 kubelet 能啟動(dòng) Pod 及其容器。 容器運(yùn)行時(shí)接口(CRI)是 kubelet 和容器運(yùn)行時(shí)之間通信的主要協(xié)議。
Kubernetes 與 dockershim
從Kubernetes的架構(gòu)圖中,可以看到 Kubelet 下面還有一層Contianer runtime (容器運(yùn)行時(shí))是作為真正和OS去交互的,這個(gè)容器運(yùn)行時(shí)是真正地管理容器的整個(gè)生命周期的以及拉取鏡像等操作的。
當(dāng)前支持的 CRI 后端
我們最初在使用 Kubernetes 時(shí)通常會(huì)默認(rèn)使用 Docker 作為容器運(yùn)行時(shí),其實(shí)從 Kubernetes 1.5 開始已經(jīng)支持 CRI,通過 CRI 接口可以指定使用其它容器運(yùn)行時(shí)作為 Pod 的后端,目前支持 CRI 的后端有:
- cri-o:cri-o 是 Kubernetes 的 CRI 標(biāo)準(zhǔn)的實(shí)現(xiàn),并且允許 Kubernetes 間接使用 OCI 兼容的容器運(yùn)行時(shí),可以把 cri-o 看成 Kubernetes 使用 OCI 兼容的容器運(yùn)行時(shí)的中間層。
- cri-containerd:基于 Containerd 的 Kubernetes CRI 實(shí)現(xiàn),Containerd是一個(gè)進(jìn)程,是CRI-Containerd的實(shí)現(xiàn)
- rkt:由 CoreOS 主推的用來跟 docker 抗衡的容器運(yùn)行時(shí)
- frakti:基于 hypervisor 的 CRI
- docker:Kuberentes 最初就開始支持的容器運(yùn)行時(shí),目前還沒完全從 kubelet 中解耦,Docker 公司同時(shí)推廣了 OCI 標(biāo)準(zhǔn)
Dockershim
在 Kubernetes 提出 CRI 操作規(guī)范時(shí),Docker剛拆出 containerd,并不支持 CRI 標(biāo)準(zhǔn)。由于當(dāng)時(shí)Docker是容器技術(shù)最主流也是最權(quán)威的存在,Kuberentes雖然提出了CRI接口規(guī)范,但仍然需要去適配CRI與Docker的對(duì)接,因此它需要一個(gè)中間層或 shim 來對(duì)接 Kubelet 和 Docker 的 contianer runtime。 于是 kubelet 中加入了 Dockershim (shim為臨時(shí)、兼容的意思)。使用 docker 作為 runtime 時(shí),實(shí)際啟動(dòng)一個(gè)容器的過程是:在這個(gè)階段 dockershim組件在Kubelet 的代碼中,這也就意味著Dockershim是由K8S組織進(jìn)行開發(fā)和維護(hù)!由于Docker公司的版本發(fā)布K8S組織是無法控制和管理,所以每次Docker發(fā)布新的Release,K8S組織都要集中精力去快速地更新維護(hù)Dockershim。 Kubernetes1.24版本正式刪除和棄用dockershim。這件事情的本質(zhì)是廢棄了內(nèi)置的 dockershim 功能,直接對(duì)接Containerd(后續(xù)已經(jīng)支持 CRI)。這種方式更加標(biāo)準(zhǔn),調(diào)用的鏈路更加的簡潔。
調(diào)用關(guān)系對(duì)比
runtime 是 docker 時(shí)的調(diào)用鏈:調(diào)用關(guān)系為:kubelet --> dockershim (在 kubelet 進(jìn)程中) --> dockerd --> containerd runtime 是 containerd 時(shí)的調(diào)用鏈:調(diào)用關(guān)系為:kubelet --> cri plugin(在 containerd 進(jìn)程中) --> containerd 總結(jié):從k8s的角度看,選擇 Containerd 作為運(yùn)行時(shí)組件更勝一籌,因?yàn)?Containerd 調(diào)用鏈更短,組件更少,更穩(wěn)定,占用節(jié)點(diǎn)資源更少調(diào)用鏈
常用命令
ctr 是 containerd 的一個(gè)客戶端工具。 crictl 是 CRI 兼容的容器運(yùn)行時(shí)命令行接口,可以使用它來檢查和調(diào)試 k8s 節(jié)點(diǎn)上的容器運(yùn)行時(shí)和應(yīng)用程序。 ctr -v 輸出的是 containerd 的版本,crictl -v 輸出的是當(dāng)前 k8s 的版本,從結(jié)果顯而易見你可以認(rèn)為 crictl 是用于 k8s 的。
docker | ctr(containerd) | crictl(kubernetes) | |
查看運(yùn)行的容器 | docker ps | ctr task ls/ctr container ls | crictl ps |
查看鏡像 | docker images | ctr image ls | crictl images |
查看容器日志 | docker logs | 無 | crictl logs |
查看容器數(shù)據(jù)信息 | docker inspect | ctr container info | crictl inspect |
查看容器資源 | docker stats | 無 | crictl stats |
啟動(dòng)/關(guān)閉已有的容器 | docker start/stop | ctr task start/kill | crictl start/stop |
運(yùn)行一個(gè)新的容器 | docker run | ctr run | 無(最小單元為 pod) |
修改鏡像標(biāo)簽 | docker tag | ctr image tag | 無 |
創(chuàng)建一個(gè)新的容器 | docker create | ctr container create | crictl create |
導(dǎo)入鏡像 | docker load | ctr image import | 無 |
導(dǎo)出鏡像 | docker save | ctr image export | 無 |
刪除容器 | docker rm | ctr container rm | crictl rm |
刪除鏡像 | docker rmi | ctr image rm | crictl rmi |
拉取鏡像 | docker pull | ctr image pull | ctictl pull |
推送鏡像 | docker push | ctr image push | 無 |
在容器內(nèi)部執(zhí)行命令 | docker exec | 無 | crictl exec |