Kubernetes和Docker的關系是什么?
本文轉載自微信公眾號「無敵碼農」,作者無敵碼農 。轉載本文請聯系無敵碼農公眾號。
作為一名容器時代的程序員相信你已經或多或少接觸過Docker,但同時你也會發現Docker雖然流行了多年,但之前卻很少有公司直接將線上應用通過Docker容器進行大規模地部署。但最近三年,你會發現幾乎絕大多數有條件的公司都已經在使用Kubernetes部署和發布自己的線上業務了。對一名普通開發人員來說,這一切可能發生得太快,以至于你還沒有搞清楚它是怎么發生的,也會疑惑Docker和Kubernetes之間到底是個什么關系。
在今天的內容中,我們從Kubernetes的系統架構及容器編排核心概念兩個方面來簡單聊一聊這個問題,希望能幫助到你更好地理解Docker和Kubernetes之間因果關系。
Kubernetes介紹
在具體介紹Kubernetes之前不得不再提一下Docker,如果你用過Docker部署過程序,那么你一定會非常享受它帶給你的絲滑體驗,而聯想到在此之前發布一個程序需要寫各種腳本、進行各種環境匹配的糟糕體驗,那么相信你的這種感覺會更加強烈。
而Docker之所以能做到這一點,就在于它以“Docker鏡像”的方式一舉解決了應用打包和發布這一困擾業界多年的技術難題,并且大大降低了普通開發人員運維部署應用的門檻。正是因為解決了應用打包這個根本性的問題,才使得Docker很快就被廣大開發/運維人員所接受,迅速成為炙手可熱的技術,并在一定時間內引領了容器化技術發展的浪潮。
那么Docker這么好用為什么還會出現Kubernetes呢?事實是Docker作為單一的容器技術工具并不能很好地定義容器的“組織方式”和“管理規范”,難以獨立地支撐起生產級大規模容器化部署的要求。因此容器技術的發展就迅速走向了以Kubernetes為代表的“容器編排”的技術路線,而這也是為什么Docker容器沒有直接在生產環境中大規模部署的關鍵原因。
上面我們提到了“容器編排”的概念,了解到相對于Docker單一容器技術而言,Kubernetes容器編排技術可以很好地實現大規模容器的組織和管理,從而使容器技術實現了從“容器”到“容器云”的飛躍!那么Kubernetes技術是從何而來?而又真正解決了什么問題呢?
從背景上說,Kubernetes是由Google與RedHat公司共同主導的開源“容器編排”項目,它起源于Google公司的Borg系統。所以它在超大規模集群管理方面的經驗要明顯優于其他容器編排技術,加上Kubernetes在社區管理方面的民主化,使得它很快打敗了Docker公司推出的容器編排解決方案(Compose+Swarm),從而成為了容器編排領域事實上的標準。
而在功能上Kubernetes是一種綜合的基于容器構建分布式系統的基礎架構環境,它不僅能夠實現基本的拉取用戶鏡像、運行容器,還可以提供路由網關、水平擴展、監控、備份、災難恢復等一系列運維能力,而更重要的是Kubernetes可以按照用戶的意愿和整個系統的規則,高度自動化的處理好容器之間的各種關系實現“編排”能力。
此外Kubernetes的出現也重新定義了微服務架構的技術方向,目前通常所說的“云原生”及“Service Mesh(服務網格)”等概念,很大程度上也是依賴于Kubernetes所提供的基礎能力。由于篇幅和作者知識水平有限,這里就不展開去聊了,感興趣的讀者可以參考其他專業書籍或技術資料。
Kubernetes整體系統架構
前面我們簡單介紹了Kubernetes的起源和背景,接下來看看Kubernetes的整體系統架構,如下圖所示:

如上圖所示,Kubernetes在架構上主要由Master和Node兩種類型的節點組成,這兩種節點分別對應著控制節點和計算節點。其中Master即控制節點,是整個Kubernetes集群的大腦,主要負責編排、管理和調度用戶提交的作業,并能根據集群系統資源的整體使用情況將作業任務自動分發到可用Node計算節點。具體看Master節點主要由三個緊密協作的獨立組件組合而成,它們分別是:
- kube-apiserver:是Kubernetes集群API服務的入口,主要提供資源訪問操作、認證、授權、訪問控制及API注冊和發現等功能機制。
- kube-scheduler:負責Kubernetes的資源調度,能按照預定的調度策略將Pod調度到相應的機器上。
- kube-controller-manager:負責容器編排及Kubernetes集群狀態的維護,例如故障檢測、自動擴展、滾動更新等。
需要說明的是,上述組件在工作狀態下還會產生許多需要進行持久化的數據,這些數據會通過kube-apiserver處理后統一保存到Etcd存儲服務中。所以從這個角度看kube-apiserver不僅是外部訪問Kubernetes集群的入口,也是維護整個Kubernetes集群狀態的信息中樞。
而在Kubernetes計算節點中,除了上述3個系統組件外,其他基本與Master節點相同,而其中最核心的部分就是kubelet組件。它的核心功能具如下:
- 通過CRI(Container Runtime Interface)遠程接口同容器運行時(如Docker)進行交互,對容器生命周期進行維護。其中CRI接口會定義了容器運行時的各項核心操作,例如啟動容器所需的命令及參數等。
- 通過GRPC協議同Device Plugin插件交互,實現Kubernetes對宿主機物理設備的管理。
- 此外kubelet另一個重要的功能則是通過CNI(Container Networking Interface)來調用網絡插件為容器配置網絡,以及通過CSI(Container Storage Interface)和存儲插件交互為容器配置持久化存儲。
在Kubernetes中kubelet會通過CRI接口同容器運行時進行交互,而容器運行時則通過叫做OCI容器運行時規范與底層Linux操作系統進行交互(涉及對Namespace、Cgroups等資源的操作,具體可以了解下Docker的技術原理)。需要強調的是,這里所說的容器運行時并不僅僅指Docker,而是所有實現了CRI接口規范的容器項目都可以作為Kubernetes的容器運行時存在。這是因為Kubernetes從設計之初就沒有把Docker作為整個架構的核心,而只是將其作為最底層的一個容器運行時來實現。
但這并不是說Kubernetes就完全拋棄Docker了,要知道Docker最大的成功并不是它的容器運行時技術,而是它定義的“容器鏡像”開創性地解決了困擾業界多年的應用打包難題,所以雖然Kubernetes并不完全依賴于Docker的容器運行時技術,但容器鏡像的定義標準卻是所有容器技術都繞不開的存在。
況且從Kubernetes架構設計上看,Kubernetes并沒有打算重復造輪子而對已有的容器技術進行替代,它更關注的是對運行在大規模集群中的各種任務根據其關系進行作業編排及管理,所以任何實現了CRI、CNI、CSI等協議標準的容器技術都可以無縫地與Kubernetes集成。從這個角度看,Docker與Kubernetes的關系并不是替代的關系,而是平臺與組件的關系,Kubernetes可以利用現有的Docker容器運行時技術,但卻并不完全依賴Docker。而這也正是Kubernetes為什么被稱作容器編排技術而不僅僅只是容器技術的原因。
Kubernetes容器編排概述
我們說處理任務之間的各種關系,實現容器編排是Kubernetes的核心技術能力,也是其大規模流行的關鍵原因。那么容器編排到底是個什么概念?在Kubernetes中是如何實現容器編排的呢?
其實所謂容器編排,通俗點舉例就是如果兩個應用調用關系比較緊密,那么我們希望運行時將它們部署在同一臺機器上,從而提升服務之間的通信效率。而能夠支持自動將具有此類關系的應用,以容器的方式部署在同一臺機器上的技術就是容器編排。
當然,這里所說的緊密關系只是一種形象的說法,實際的技術場景中這種緊密關系可以被劃分為很多類型,例如Web應用與數據庫之間的訪問關系、負載均衡和它后端服務之間的代理關系、門戶應用與授權組件之間的調用關系等。
而對于Kubernetes來說,這樣的關系描述顯然還是過于具體,因為Kubernetes的設計目標不僅僅是能夠處理前面提到的所有類型的關系,還要能夠支持未來可能出現的更多種類的關系。這就要求Kubernetes要從更宏觀地角度來定義任務之間的各種關系,并且能為將來支持更多種類的關系留有余地。
具體來說,Kubernetes是對容器間的訪問進行了分類,如果這些應用之間需要非常頻繁的交互和訪問,或者它們之間存在直接通過本地文件進行信息交換的情況,那么在Kubernetes中可以將這些容器劃分為一個“Pod”,而Pod中的容器將共享同一個Network Namespace、同一組數據卷,從而實現高效率通信。
Pod是Kubernetes中最基礎的編排對象,是Kubernetes最小的調度單元,也是Kubernetes實現容器編排的載體,其本質上是一組共享了某些系統資源的容器集合。在Kubernetes中圍繞Pod可以延伸出其他核心概念,具體如下圖所示:
如上圖所示,在Kubernetes中Pod解決了容器間緊密協作(即編排)的問題,而Pod要實現一次啟動多個Pod副本就需要Deployment這個Pod多實例管理器;而有了這樣一組Pod后,我們又需要通過一個固定網絡地址以負載均衡的方式訪問它,于是又有了Service。
而根據不同的編排場景Pod又衍生出描述一次性運行任務的Job編排對象、描述每個宿主機上必須且只能運行一個副本的守護進程服務DaemonSet、描述定義任務的CronJob編排對象、以及針對有狀態應用的StatefulSet等多種編排對象。而這些編排對象正是Kubernetes定義容器間關系和形態的主要方法。