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