K8s 為什麼要棄用 Docker?

danny_2018發表於2022-10-12

  在寫“K8s”系列文章的過程中,很多讀者留言詢問 K8s 棄用 Docker 的事,擔心現在學習 Docker 是否還值得,是不是該切換到 containerd 或其他執行時。

  這些懷疑有一定的道理。兩年前,K8s 釋出“棄用 Docker”的訊息時,確實在社群引起了“軒然大波”,影響甚至蔓延到了社群之外,K8s 不得不寫了好幾篇部落格來重複解釋原因。

  兩年過去了,雖然 K8s 1.24 已經實現了“棄用 Docker”的目標,但很多人似乎對這一點還不是很清楚。所以本篇文章就來聊聊這個話題。

  CRI(容器執行時介面)

  要理解 K8s 為何“棄用 Docker”,我們得回顧一下 K8s 的發展史。

  2014 年,Docker 正處於鼎盛時期,而 K8s 剛剛誕生。雖然它得到了 Google 和 Borg 的支援,但它還是比較新的。

  因此,K8s 首先選擇支援 Docker 。

  快進到 2016 年,CNCF 成立一年,K8s 也釋出了 1.0 版本,可以正式用於生產環境。這些都表明 K8s 已經長大了。

  於是宣佈加入 CNCF,成為第一個 CNCF 託管專案。它想利用基金會的力量聯合其他廠商來“打倒”Docker。

  在 2016 年底的 1.5 版本中,K8s 引入了新的介面標準:CRI:Container Runtime Interface 容器執行時介面。

  CRI 使用ProtoBufferandgPRC來指定kubelet應該如何呼叫容器執行時來管理容器和映象,但這是一組與以前的 Docker 呼叫完全不相容的新介面。

  顯然它不想再和 Docker 繫結,在底層允許訪問其他容器技術(如 rkt、kata 等),可以隨時“踢開” Docker。

  但此時 Docker 已經非常成熟,市場的慣性也非常強。各大雲廠商不可能一下子全部替換掉 Docker。

  因此,K8s 只能同時提供一種“折中”的方案,在kubelet和 Docker 之間增加一個“介面卡”,將 Docker 的介面轉換為 CRI 相容的介面:

  因為這個“介面卡”夾在kubeletDocker 和 Docker 之間,所以形象地稱為“shim”,意思是“墊片”。

  有了 CRI 和 shim,雖然 K8s 仍然使用 Docker 作為底層執行時,但它也具備了與 Docker 解耦的條件,從而拉開了“棄用 Docker”大戲的帷幕。

   Containerd

  面對挑戰,Docker 採取了“斷臂求生”的策略,推動自身重構,將原有單一架構的 Docker Engine 拆分成多個模組,其中 Docker daemon 部分捐贈給 CNCF,containerd 形成。

  作為 CNCF 的託管專案,containerd 必須符合 CRI 標準。但是由於很多原因,Docker 只是 containerd 在 Docker Engine 中呼叫,對外的介面保持不變,也就是說不相容 CRI。

  由於 Docker 的“固執”,此時 K8s 中有兩條呼叫鏈:

  使用 CRI 介面呼叫 dockershim,然後 dockershim 呼叫 Docker,Docker 再去 containerd 操作容器。

  使用 CRI 介面直接呼叫 containerd 操作容器。

  顯然,因為 containerd 是用來管理容器的,所以這兩個呼叫鏈的最終效果是完全一樣的,但是第二種方法去掉了 dockershim 和 Docker Engine 這兩個環節,更加簡潔明瞭,效能也更好。

  2018 年 Kubernetes 1.10 釋出時,containerd 也更新到 1.1 版本,正式與 Kubernetes 整合,並發表[博文](https://kubernetes.io/blog/2018/05/24/kubernetes-containerd-integration- gos-ga/ "博文")顯示一些效能測試資料:

  從這些資料可以看出,相比當時的 Docker 18.03,containerd1.1Pod 啟動延遲降低了 20% 左右,CPU 使用率降低了 68%,記憶體使用率降低了 12%,這樣可觀的效能提升對雲廠商來說是非常有誘惑力的。

   棄用Docker

  2020 年,K8s 1.20 終於正式向 Docker “宣戰”:kubelet將棄用 Docker 支援,並將在未來的版本中完全移除。

  但由於 Docker 幾乎已經成為容器技術的代名詞,而且 K8s 已經使用 Docker 多年,該公告在傳播時很快“變味了”,“kubelet 將棄用 Docker 支援”被簡化為更吸人眼球的東西 “K8s 將棄用”Docker”。

  這自然引起了 IT 界的恐慌,“不明真相的群眾”紛紛表示震驚:

  用了這麼久的 Docker 突然不能用了。

  為什麼 K8s 會這樣對待 Docker?

  之前對 Docker 的投資會歸零嗎?現有的大量映象怎麼辦?

  其實,如果你瞭解了上面提到的這兩個專案CRI,containerd你就會知道,K8s 的這一舉動並不奇怪,一切都是“自然”的:其實只是“棄用 dockershim ”,也就是dockershim搬出kubelet,並不是“棄用 Docker”的軟體產品。

  因此,“棄用 Docker”對 K8s 和 Docker 的影響不大,因為它們都已經將底層改為開源containerd,原有的 Docker 映象和容器仍然可以正常執行。唯一的變化是K8s繞過了Docker,直接呼叫Docker內部的containerd。

  然而,還是會有一些影響。如果K8s直接使用containerd來操作容器,那麼它就是一個獨立於Docker的工作環境,兩者都無法訪問對方管理的容器和映象。換句話說,使用docker ps命令將不會看到K8s中執行的容器。

  這對一些人來說可能需要花一點時間來適應並使用新工具crictl,但用於檢視容器和映象的子命令仍然是相同的,例如ps,images等,不難適應(如果你一直在用kubectl管理K8s,這個沒有影響)。

  K8s 原本計劃用一年時間完成“棄用 Docker”的工作,但它確實低估了 Docker 的基礎。1.23版本還是沒能移除dockershim,只好延期半年。最後,1.24版本從kubelet中刪除了dockershim的程式碼。

  從此,Kubernetes 與 Docker 徹底“分道揚鑣”。

  Docker 的未來

  那麼,Docker 的未來會怎樣呢?雲原生時代就沒有它的立足之地嗎?這個問題的答案顯然是否定的。

  作為容器技術的奠基人,沒有人可以質疑 Docker 的歷史地位。雖然 K8s 預設不再繫結 Docker,但 Docker 仍然可以以其他形式的 K8s 共存。

  首先,由於容器映象格式已經標準化(OCI規範,Open Container Initiative),Docker映象在K8s中仍然可以正常使用,不需要改變原有的開發測試和CI/CD流程。我們仍然可以拉取 Docker Hub,或者編寫一個 Dockerfile 來打包應用程式。

  其次,Docker是一個完整的軟體產品線,不僅僅是containerd,它還包括映象構建、分發、測試等很多服務,甚至連K8s都內建於Docker Desktop中。

  就容器開發的便利性而言,Docker暫時還難以被取代。大多數雲原生開發人員可以繼續在這個熟悉的環境中工作,使用Docker來開發在K8s中執行的應用程式。

  同樣,雖然 K8s 不再包含dockershim,Docker 已經接管了這部分程式碼並構建了一個名為cri-dockerd的專案,該專案也同樣工作,將 Docker Engine 適配為 CRI 介面,這樣就kubelet可以透過它再次操作Docker,就好像它從來沒有發生過一樣。

  總的來說,Docker雖然在容器編排大戰中敗下陣來,被K8s擠到了牆角,但依然具有很強的生命力。多年積累的眾多忠實使用者和大量應用形象是其最大的資本和後盾。足以支援它在另一條不與 K8s 正面交鋒的道路上。

  對於初學者來說,Docker簡單易用,工具鏈完整,介面友好,市面上很難找到與之相媲美的軟體。應該說是入門級學習容器技術和雲原生的上上選擇。


來自 “ K8S中文社群 ”, 原文作者:Tony;原文連結:https://mp.weixin.qq.com/s/qEKyEseD370xWI-2yIyUzg,如有侵權,請聯絡管理員刪除。

相關文章