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