深入剖析Kubernetes:容器编排与 Kubernetes 核心特性剖析
容器本質(zhì)
一個“容器”,實(shí)際上是一個由 Linux Namespace、Linux Cgroups 和 rootfs 三種技術(shù)構(gòu)建出來的進(jìn)程的隔離環(huán)境。
從這個結(jié)構(gòu)中我們不難看出,一個正在運(yùn)行的 Linux 容器,其實(shí)可以被“一分為二”地看待:
一組聯(lián)合掛載在 /var/lib/docker/aufs/mnt 上的 rootfs,這一部分我們稱為“容器鏡像”(Container Image),是容器的靜態(tài)視圖;
一個由 Namespace+Cgroups 構(gòu)成的隔離環(huán)境,這一部分我們稱為“容器運(yùn)行時”(Container Runtime),是容器的動態(tài)視圖。
更進(jìn)一步地說,作為一名開發(fā)者,我并不關(guān)心容器運(yùn)行時的差異。因?yàn)?#xff0c;在整個“開發(fā) - 測試 - 發(fā)布”的流程中,真正承載著容器信息進(jìn)行傳遞的,是容器鏡像,而不是容器運(yùn)行時。
Kubernetes 項(xiàng)目要解決的問題是什么?
編排?調(diào)度?容器云?還是集群管理?
實(shí)際上,這個問題到目前為止都沒有固定的答案。因?yàn)樵诓煌陌l(fā)展階段,Kubernetes 需要著重解決的問題是不同的。
但是,對于大多數(shù)用戶來說,他們希望 Kubernetes 項(xiàng)目帶來的體驗(yàn)是確定的:現(xiàn)在我有了應(yīng)用的容器鏡像,請幫我在一個給定的集群上把這個應(yīng)用運(yùn)行起來。
更進(jìn)一步地說,我還希望 Kubernetes 能給我提供路由網(wǎng)關(guān)、水平擴(kuò)展、監(jiān)控、備份、災(zāi)難恢復(fù)等一系列運(yùn)維能力。
Kubernetes 項(xiàng)目的架構(gòu)?
我們可以看到,Kubernetes 項(xiàng)目的架構(gòu),跟它的原型項(xiàng)目 Borg 非常類似,都由 Master 和 Node 兩種節(jié)點(diǎn)組成,而這兩種角色分別對應(yīng)著控制節(jié)點(diǎn)和計算節(jié)點(diǎn)。
其中,控制節(jié)點(diǎn),即 Master 節(jié)點(diǎn),由三個緊密協(xié)作的獨(dú)立組件組合而成,它們分別是
負(fù)責(zé) API 服務(wù)的 kube-apiserver、
負(fù)責(zé)調(diào)度的 kube-scheduler,
以及負(fù)責(zé)容器編排的 kube-controller-manager。
整個集群的持久化數(shù)據(jù),則由 kube-apiserver 處理后保存在 Ectd 中。
而計算節(jié)點(diǎn)上最核心的部分,則是一個叫作 kubelet 的組件。
在 Kubernetes 項(xiàng)目中,kubelet 主要負(fù)責(zé)同容器運(yùn)行時(比如 Docker 項(xiàng)目)打交道。而這個交互所依賴的,是一個稱作 CRI(Container Runtime Interface)的遠(yuǎn)程調(diào)用接口,這個接口定義了容器運(yùn)行時的各項(xiàng)核心操作,比如:啟動一個容器需要的所有參數(shù)。
這也是為何,Kubernetes 項(xiàng)目并不關(guān)心你部署的是什么容器運(yùn)行時、使用的什么技術(shù)實(shí)現(xiàn),只要你的這個容器運(yùn)行時能夠運(yùn)行標(biāo)準(zhǔn)的容器鏡像,它就可以通過實(shí)現(xiàn) CRI 接入到 Kubernetes 項(xiàng)目當(dāng)中。
而具體的容器運(yùn)行時,比如 Docker 項(xiàng)目,則一般通過 OCI 這個容器運(yùn)行時規(guī)范同底層的 Linux 操作系統(tǒng)進(jìn)行交互,即:把 CRI 請求翻譯成對 Linux 操作系統(tǒng)的調(diào)用(操作 Linux Namespace 和 Cgroups 等)。
此外,kubelet 還通過 gRPC 協(xié)議同一個叫作 Device Plugin 的插件進(jìn)行交互。這個插件,是 Kubernetes 項(xiàng)目用來管理 GPU 等宿主機(jī)物理設(shè)備的主要組件,也是基于 Kubernetes 項(xiàng)目進(jìn)行機(jī)器學(xué)習(xí)訓(xùn)練、高性能作業(yè)支持等工作必須關(guān)注的功能。
而kubelet 的另一個重要功能,則是調(diào)用網(wǎng)絡(luò)插件和存儲插件為容器配置網(wǎng)絡(luò)和持久化存儲。這兩個插件與 kubelet 進(jìn)行交互的接口,分別是 CNI(Container Networking Interface)和 CSI(Container Storage Interface)。
可以說,kubelet 完全就是為了實(shí)現(xiàn) Kubernetes 項(xiàng)目對容器的管理能力而重新實(shí)現(xiàn)的一個組件
Borg 對于 Kubernetes 項(xiàng)目的指導(dǎo)作用又體現(xiàn)在哪里呢?
答案是,Master 節(jié)點(diǎn)。
雖然在 Master 節(jié)點(diǎn)的實(shí)現(xiàn)細(xì)節(jié)上 Borg 項(xiàng)目與 Kubernetes 項(xiàng)目不盡相同,但它們的出發(fā)點(diǎn)卻高度一致,即:如何編排、管理、調(diào)度用戶提交的作業(yè)?
所以,Borg 項(xiàng)目完全可以把 Docker 鏡像看做是一種新的應(yīng)用打包方式。這樣,Borg 團(tuán)隊過去在大規(guī)模作業(yè)管理與編排上的經(jīng)驗(yàn)就可以直接“套”在 Kubernetes 項(xiàng)目上了。
這些經(jīng)驗(yàn)最主要的表現(xiàn)就是,從一開始,Kubernetes 項(xiàng)目就沒有像同時期的各種“容器云”項(xiàng)目那樣,把 Docker 作為整個架構(gòu)的核心,而僅僅把它作為最底層的一個容器運(yùn)行時實(shí)現(xiàn)。
而 Kubernetes 項(xiàng)目要著重解決的問題,則來自于 Borg 的研究人員在論文中提到的一個非常重要的觀點(diǎn):
運(yùn)行在大規(guī)模集群中的各種任務(wù)之間,實(shí)際上存在著各種各樣的關(guān)系。這些關(guān)系的處理,才是作業(yè)編排和管理系統(tǒng)最困難的地方。
事實(shí)也正是如此。
其實(shí),這種任務(wù)與任務(wù)之間的關(guān)系,在我們平常的各種技術(shù)場景中隨處可見。比如,一個 Web 應(yīng)用與數(shù)據(jù)庫之間的訪問關(guān)系,一個負(fù)載均衡器和它的后端服務(wù)之間的代理關(guān)系,一個門戶應(yīng)用與授權(quán)組件之間的調(diào)用關(guān)系。
更進(jìn)一步地說,同屬于一個服務(wù)單位的不同功能之間,也完全可能存在這樣的關(guān)系。比如,一個 Web 應(yīng)用與日志搜集組件之間的文件交換關(guān)系。
而在容器技術(shù)普及之前,傳統(tǒng)虛擬機(jī)環(huán)境對這種關(guān)系的處理方法都是比較“粗粒度”的。你會經(jīng)常發(fā)現(xiàn)很多功能并不相關(guān)的應(yīng)用被一股腦兒地部署在同一臺虛擬機(jī)中,只是因?yàn)樗鼈冎g偶爾會互相發(fā)起幾個 HTTP 請求。
更常見的情況則是,一個應(yīng)用被部署在虛擬機(jī)里之后,你還得手動維護(hù)很多跟它協(xié)作的守護(hù)進(jìn)程(Daemon),用來處理它的日志搜集、災(zāi)難恢復(fù)、數(shù)據(jù)備份等輔助工作。
但容器技術(shù)出現(xiàn)以后,你就不難發(fā)現(xiàn),在“功能單位”的劃分上,容器有著獨(dú)一無二的“細(xì)粒度”優(yōu)勢:畢竟容器的本質(zhì),只是一個進(jìn)程而已。
也就是說,只要你愿意,那些原先擁擠在同一個虛擬機(jī)里的各個應(yīng)用、組件、守護(hù)進(jìn)程,都可以被分別做成鏡像,然后運(yùn)行在一個個專屬的容器中。它們之間互不干涉,擁有各自的資源配額,可以被調(diào)度在整個集群里的任何一臺機(jī)器上。而這,正是一個 PaaS 系統(tǒng)最理想的工作狀態(tài),也是所謂“微服務(wù)”思想得以落地的先決條件。
當(dāng)然,如果只做到“封裝微服務(wù)、調(diào)度單容器”這一層次,Docker Swarm 項(xiàng)目就已經(jīng)綽綽有余了。如果再加上 Compose 項(xiàng)目,你甚至還具備了處理一些簡單依賴關(guān)系的能力,比如:一個“Web 容器”和它要訪問的數(shù)據(jù)庫“DB 容器”。
在 Compose 項(xiàng)目中,你可以為這樣的兩個容器定義一個“l(fā)ink”,而 Docker 項(xiàng)目則會負(fù)責(zé)維護(hù)這個“l(fā)ink”關(guān)系,其具體做法是:Docker 會在 Web 容器中,將 DB 容器的 IP 地址、端口等信息以環(huán)境變量的方式注入進(jìn)去,供應(yīng)用進(jìn)程使用,
DB_NAME=/web/dbDB_PORT=tcp://172.17.0.5:5432DB_PORT_5432_TCP=tcp://172.17.0.5:5432DB_PORT_5432_TCP_PROTO=tcpDB_PORT_5432_TCP_PORT=5432DB_PORT_5432_TCP_ADDR=172.17.0.5而當(dāng) DB 容器發(fā)生變化時(比如,鏡像更新,被遷移到其他宿主機(jī)上等等),這些環(huán)境變量的值會由 Docker 項(xiàng)目自動更新。這就是平臺項(xiàng)目自動地處理容器間關(guān)系的典型例子。
可是,如果我們現(xiàn)在的需求是,要求這個項(xiàng)目能夠處理前面提到的所有類型的關(guān)系,甚至還要能夠支持未來可能出現(xiàn)的更多種類的關(guān)系呢?
這時,“l(fā)ink”這種單獨(dú)針對一種案例設(shè)計的解決方案就太過簡單了。如果你做過架構(gòu)方面的工作,就會深有感觸:一旦要追求項(xiàng)目的普適性,那就一定要從頂層開始做好設(shè)計。
所以,Kubernetes 項(xiàng)目最主要的設(shè)計思想是,從更宏觀的角度,以統(tǒng)一的方式來定義任務(wù)之間的各種關(guān)系,并且為將來支持更多種類的關(guān)系留有余地。
比如,Kubernetes 項(xiàng)目對容器間的“訪問”進(jìn)行了分類,首先總結(jié)出了一類非常常見的“緊密交互”的關(guān)系,即:這些應(yīng)用之間需要非常頻繁的交互和訪問;又或者,它們會直接通過本地文件進(jìn)行信息交換。
圍繞著容器和 Pod 不斷向真實(shí)的技術(shù)場景擴(kuò)展,我們就能夠摸索出一幅如下所示的 Kubernetes 項(xiàng)目核心功能的“全景圖”。
Kubernetes 項(xiàng)目核心功能的“全景圖”?
在 Kubernetes 項(xiàng)目中,我們所推崇的使用方法是:
- 首先,通過一個“編排對象”,比如 Pod、Job、CronJob 等,來描述你試圖管理的應(yīng)用;
- 然后,再為它定義一些“服務(wù)對象”,比如 Service、Secret、Horizontal Pod Autoscaler(自動水平擴(kuò)展器)等。這些對象,會負(fù)責(zé)具體的平臺級功能。
這種使用方法,就是所謂的“聲明式 API”。這種 API 對應(yīng)的“編排對象”和“服務(wù)對象”,都是 Kubernetes 項(xiàng)目中的 API 對象(API Object)。
過去很多的集群管理項(xiàng)目(比如 Yarn、Mesos,以及 Swarm)所擅長的,都是把一個容器,按照某種規(guī)則,放置在某個最佳節(jié)點(diǎn)上運(yùn)行起來。這種功能,我們稱為“調(diào)度”。
而 Kubernetes 項(xiàng)目所擅長的,是按照用戶的意愿和整個系統(tǒng)的規(guī)則,完全自動化地處理好容器之間的各種關(guān)系。這種功能,就是我們經(jīng)常聽到的一個概念:編排。
所以說,Kubernetes 項(xiàng)目的本質(zhì),是為用戶提供一個具有普遍意義的容器編排工具。
總結(jié)
以上是生活随笔為你收集整理的深入剖析Kubernetes:容器编排与 Kubernetes 核心特性剖析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【系统架构】三大主流软件负载均衡器(LV
- 下一篇: 昨日比赛心得