Kubernetes容器運行時棄用Docker轉(zhuǎn)型Containerd

一面粮、背景

Kubernetes社區(qū)在2020年7月份發(fā)布的版本中已經(jīng)開始了dockershim的移除計劃,在1.20版本中將內(nèi)置的dockershim進行分離继低,這個版本依舊還可以使用dockershim熬苍,但是在1.24中被刪除。從1.24開始袁翁,大家需要使用其他受到支持的運行時選項(例如containerd或CRI-O)柴底;如果選擇Docker Engine作為運行時,則需要使用cri-dockerd

二粱胜、Docker

從 Docker 1.11 版本開始柄驻,Docker 容器運行就不是簡單通過 Docker Daemon 來啟動了,而是通過集成 containerd焙压、runc 等多個組件來完成的鸿脓。雖然 Docker Daemon 守護進程模塊在不停的重構(gòu)抑钟,但是基本功能和定位沒有太大的變化,一直都是 CS 架構(gòu)野哭,守護進程負(fù)責(zé)和 Docker Client 端交互味赃,并管理 Docker 鏡像和容器。現(xiàn)在的架構(gòu)中組件 containerd 就會負(fù)責(zé)集群節(jié)點上容器的生命周期管理虐拓,并向上為 Docker Daemon 提供 gRPC 接口。

Docker架構(gòu)

當(dāng)我們要創(chuàng)建一個容器的時候傲武,現(xiàn)在 Docker Daemon 并不能直接幫我們創(chuàng)建了蓉驹,而是請求 containerd 來創(chuàng)建一個容器,containerd 收到請求后揪利,也并不會直接去操作容器态兴,而是創(chuàng)建一個叫做 containerd-shim 的進程,讓這個進程去操作容器疟位,我們指定容器進程是需要一個父進程來做狀態(tài)收集瞻润、維持 stdin 等 fd 打開等工作的,假如這個父進程就是 containerd甜刻,那如果 containerd 掛掉的話绍撞,整個宿主機上所有的容器都得退出了,而引入 containerd-shim 這個墊片就可以來規(guī)避這個問題了得院。

然后創(chuàng)建容器需要做一些 namespaces 和 cgroups 的配置傻铣,以及掛載 root 文件系統(tǒng)等操作,這些操作其實已經(jīng)有了標(biāo)準(zhǔn)的規(guī)范祥绞,那就是 OCI(開放容器標(biāo)準(zhǔn))非洲,runc 就是它的一個參考實現(xiàn)(Docker 被逼無耐將 libcontainer 捐獻出來改名為 runc 的),這個標(biāo)準(zhǔn)其實就是一個文檔蜕径,主要規(guī)定了容器鏡像的結(jié)構(gòu)两踏、以及容器需要接收哪些操作指令,比如 create兜喻、start梦染、stop、delete 等這些命令虹统。runc 就可以按照這個 OCI 文檔來創(chuàng)建一個符合規(guī)范的容器弓坞,既然是標(biāo)準(zhǔn)肯定就有其他 OCI 實現(xiàn),比如 Kata车荔、gVisor 這些容器運行時都是符合 OCI 標(biāo)準(zhǔn)的渡冻。

所以真正啟動容器是通過 containerd-shim 去調(diào)用 runc 來啟動容器的,runc 啟動完容器后本身會直接退出忧便,containerd-shim 則會成為容器進程的父進程, 負(fù)責(zé)收集容器進程的狀態(tài), 上報給 containerd, 并在容器中 pid 為 1 的進程退出后接管容器中的子進程進行清理, 確保不會出現(xiàn)僵尸進程族吻。

而 Docker 將容器操作都遷移到 containerd 中去是因為當(dāng)前做 Swarm帽借,想要進軍 PaaS 市場,做了這個架構(gòu)切分超歌,讓 Docker Daemon 專門去負(fù)責(zé)上層的封裝編排砍艾,當(dāng)然后面的結(jié)果我們知道 Swarm 在 Kubernetes 面前是慘敗,然后 Docker 公司就把 containerd 項目捐獻給了 CNCF 基金會巍举,這個也是現(xiàn)在的 Docker 架構(gòu)脆荷。

三、CRI

我們知道 Kubernetes 提供了一個 CRI 的容器運行時接口懊悯,那么這個 CRI 到底是什么呢蜓谋?這個其實也和 Docker 的發(fā)展密切相關(guān)的。

在 Kubernetes 早期的時候炭分,當(dāng)時 Docker 實在是太火了桃焕,Kubernetes 當(dāng)然會先選擇支持 Docker,而且是通過硬編碼的方式直接調(diào)用 Docker API捧毛,后面隨著 Docker 的不斷發(fā)展以及 Google 的主導(dǎo)观堂,出現(xiàn)了更多容器運行時,Kubernetes 為了支持更多更精簡的容器運行時呀忧,Google 就和紅帽主導(dǎo)推出了 CRI 標(biāo)準(zhǔn)师痕,用于將 Kubernetes 平臺和特定的容器運行時(當(dāng)然主要是為了干掉 Docker)解耦。

CRI(Container Runtime Interface 容器運行時接口)本質(zhì)上就是 Kubernetes 定義的一組與容器運行時進行交互的接口荐虐,所以只要實現(xiàn)了這套接口的容器運行時都可以對接到 Kubernetes 平臺上來七兜。不過 Kubernetes 推出 CRI 這套標(biāo)準(zhǔn)的時候還沒有現(xiàn)在的統(tǒng)治地位,所以有一些容器運行時可能不會自身就去實現(xiàn) CRI 接口福扬,于是就有了 shim(墊片)腕铸, 一個 shim 的職責(zé)就是作為適配器將各種容器運行時本身的接口適配到 Kubernetes 的 CRI 接口上,其中 dockershim 就是 Kubernetes 對接 Docker 到 CRI 接口上的一個墊片實現(xiàn)铛碑。

CRI

Kubelet 通過 gRPC 框架與容器運行時或 shim 進行通信狠裹,其中 kubelet 作為客戶端,CRI shim(也可能是容器運行時本身)作為服務(wù)器汽烦。

CRI 定義的 API(https://github.com/kubernetes/kubernetes/blob/release-1.5/pkg/kubelet/api/v1alpha1/runtime/api.proto) 主要包括兩個 gRPC 服務(wù)涛菠,ImageServiceRuntimeServiceImageService 服務(wù)主要是拉取鏡像撇吞、查看和刪除鏡像等操作俗冻,RuntimeService 則是用來管理 Pod 和容器的生命周期,以及與容器交互的調(diào)用(exec/attach/port-forward)等操作牍颈,可以通過 kubelet 中的標(biāo)志 --container-runtime-endpoint--image-service-endpoint 來配置這兩個服務(wù)的套接字迄薄。

kubelet cri

不過這里同樣也有一個例外,那就是 Docker煮岁,由于 Docker 當(dāng)時的江湖地位很高讥蔽,Kubernetes 是直接內(nèi)置了 dockershim 在 kubelet 中的涣易,所以如果你使用的是 Docker 這種容器運行時的話是不需要單獨去安裝配置適配器之類的,當(dāng)然這個舉動似乎也麻痹了 Docker 公司冶伞。

dockershim

現(xiàn)在如果我們使用的是 Docker 的話新症,當(dāng)我們在 Kubernetes 中創(chuàng)建一個 Pod 的時候,首先就是 kubelet 通過 CRI 接口調(diào)用 dockershim响禽,請求創(chuàng)建一個容器徒爹,kubelet 可以視作一個簡單的 CRI Client, 而 dockershim 就是接收請求的 Server,不過他們都是在 kubelet 內(nèi)置的芋类。

dockershim 收到請求后, 轉(zhuǎn)化成 Docker Daemon 能識別的請求, 發(fā)到 Docker Daemon 上請求創(chuàng)建一個容器瀑焦,請求到了 Docker Daemon 后續(xù)就是 Docker 創(chuàng)建容器的流程了,去調(diào)用 containerd梗肝,然后創(chuàng)建 containerd-shim 進程,通過該進程去調(diào)用 runc 去真正創(chuàng)建容器铺董。

其實我們仔細(xì)觀察也不難發(fā)現(xiàn)使用 Docker 的話其實是調(diào)用鏈比較長的巫击,真正容器相關(guān)的操作其實 containerd 就完全足夠了,Docker 太過于復(fù)雜笨重了精续,當(dāng)然 Docker 深受歡迎的很大一個原因就是提供了很多對用戶操作比較友好的功能坝锰,但是對于 Kubernetes 來說壓根不需要這些功能,因為都是通過接口去操作容器的重付,所以自然也就可以將容器運行時切換到 containerd 來顷级。

切換到containerd

切換到 containerd 可以消除掉中間環(huán)節(jié),操作體驗也和以前一樣确垫,但是由于直接用容器運行時調(diào)度容器弓颈,所以它們對 Docker 來說是不可見的。 因此删掀,你以前用來檢查這些容器的 Docker 工具就不能使用了翔冀。

你不能再使用 docker ps 或 docker inspect 命令來獲取容器信息。由于不能列出容器披泪,因此也不能獲取日志纤子、停止容器,甚至不能通過 docker exec 在容器中執(zhí)行命令款票。

當(dāng)然我們?nèi)匀豢梢韵螺d鏡像控硼,或者用 docker build 命令構(gòu)建鏡像,但用 Docker 構(gòu)建艾少、下載的鏡像卡乾,對于容器運行時和 Kubernetes,均不可見姆钉。為了在 Kubernetes 中使用说订,需要把鏡像推送到鏡像倉庫中去抄瓦。

從上圖可以看出在 containerd 1.0 中,對 CRI 的適配是通過一個單獨的 CRI-Containerd 進程來完成的陶冷,這是因為最開始 containerd 還會去適配其他的系統(tǒng)(比如 swarm)钙姊,所以沒有直接實現(xiàn) CRI,所以這個對接工作就交給 CRI-Containerd 這個 shim 了埂伦。

然后到了 containerd 1.1 版本后就去掉了 CRI-Containerd 這個 shim煞额,直接把適配邏輯作為插件的方式集成到了 containerd 主進程中,現(xiàn)在這樣的調(diào)用就更加簡潔了沾谜。

containerd cri

與此同時 Kubernetes 社區(qū)也做了一個專門用于 Kubernetes 的 CRI 運行時 CRI-O膊毁,直接兼容 CRI 和 OCI 規(guī)范。

cri-o

這個方案和 containerd 的方案顯然比默認(rèn)的 dockershim 簡潔很多基跑,不過由于大部分用戶都比較習(xí)慣使用 Docker婚温,所以大家還是更喜歡使用 dockershim 方案。

但是隨著 CRI 方案的發(fā)展媳否,以及其他容器運行時對 CRI 的支持越來越完善栅螟,Kubernetes 社區(qū)在2020年7月份就開始著手移除 dockershim 方案了:https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/2221-remove-dockershim,現(xiàn)在的移除計劃是在 1.20 版本中將 kubelet 中內(nèi)置的 dockershim 代碼分離篱竭,將內(nèi)置的 dockershim 標(biāo)記為維護模式力图,當(dāng)然這個時候仍然還可以使用 dockershim,目標(biāo)是在 1.23?1.24 版本發(fā)布沒有 dockershim 的版本(代碼還在掺逼,但是要默認(rèn)支持開箱即用的 docker 需要自己構(gòu)建 kubelet吃媒,會在某個寬限期過后從 kubelet 中刪除內(nèi)置的 dockershim 代碼)。

那么這是否就意味這 Kubernetes 不再支持 Docker 了呢吕喘?當(dāng)然不是的赘那,這只是廢棄了內(nèi)置的 dockershim 功能而已,Docker 和其他容器運行時將一視同仁氯质,不會單獨對待內(nèi)置支持漓概,如果我們還想直接使用 Docker 這種容器運行時應(yīng)該怎么辦呢?可以將 dockershim 的功能單獨提取出來獨立維護一個 cri-dockerd 即可病梢,就類似于 containerd 1.0 版本中提供的 CRI-Containerd胃珍,當(dāng)然還有一種辦法就是 Docker 官方社區(qū)將 CRI 接口內(nèi)置到 Dockerd 中去實現(xiàn)。

但是我們也清楚 Dockerd 也是去直接調(diào)用的 Containerd蜓陌,而 containerd 1.1 版本后就內(nèi)置實現(xiàn)了 CRI觅彰,所以 Docker 也沒必要再去單獨實現(xiàn) CRI 了,當(dāng) Kubernetes 不再內(nèi)置支持開箱即用的 Docker 的以后钮热,最好的方式當(dāng)然也就是直接使用 Containerd 這種容器運行時填抬,而且該容器運行時也已經(jīng)經(jīng)過了生產(chǎn)環(huán)境實踐的。

資料來源:

一文搞懂容器運行時 Containerd

Kubernetes容器運行時棄用Docker轉(zhuǎn)型Containerd

K8S Runtime CRI OCI contained dockershim 理解

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末隧期,一起剝皮案震驚了整個濱河市飒责,隨后出現(xiàn)的幾起案子赘娄,更是在濱河造成了極大的恐慌,老刑警劉巖宏蛉,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件遣臼,死亡現(xiàn)場離奇詭異,居然都是意外死亡拾并,警方通過查閱死者的電腦和手機揍堰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來嗅义,“玉大人屏歹,你說我怎么就攤上這事≈耄” “怎么了蝙眶?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長褪那。 經(jīng)常有香客問我械馆,道長,這世上最難降的妖魔是什么武通? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮珊搀,結(jié)果婚禮上冶忱,老公的妹妹穿的比我還像新娘。我一直安慰自己境析,他們只是感情好囚枪,可當(dāng)我...
    茶點故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著劳淆,像睡著了一般链沼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上沛鸵,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天括勺,我揣著相機與錄音,去河邊找鬼曲掰。 笑死疾捍,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的栏妖。 我是一名探鬼主播乱豆,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼吊趾!你這毒婦竟也來了宛裕?” 一聲冷哼從身側(cè)響起瑟啃,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎揩尸,沒想到半個月后蛹屿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡疲酌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年蜡峰,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片朗恳。...
    茶點故事閱讀 38,617評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡湿颅,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出粥诫,到底是詐尸還是另有隱情油航,我是刑警寧澤,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布怀浆,位于F島的核電站谊囚,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏执赡。R本人自食惡果不足惜镰踏,卻給世界環(huán)境...
    茶點故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望沙合。 院中可真熱鬧奠伪,春花似錦、人聲如沸首懈。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽究履。三九已至滤否,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間最仑,已是汗流浹背藐俺。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留泥彤,地道東北人紊搪。 一個月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像全景,于是被迫代替她去往敵國和親耀石。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,486評論 2 348

推薦閱讀更多精彩內(nèi)容