一篇文章學(xué)會(huì)什么是Kubernetes
什么是Kubernetes?
Borg系統(tǒng)是谷歌內(nèi)部使用很多的容器管理系統(tǒng),在早期是采用Chroot Jail實(shí)現(xiàn)安全隔離,后期采用Namespace,資源隔離是采用CGroup實(shí)現(xiàn)。
為什么谷歌要推出Kubernetes開(kāi)源版本呢?我個(gè)人的理解是:
- 使用開(kāi)源社區(qū)的力量來(lái)解決谷歌未解決的問(wèn)題
- 在云原生領(lǐng)域分一杯羹
- 推動(dòng)云原生的發(fā)展,畢竟谷歌在容器領(lǐng)域已經(jīng)玩了許多年了
Kubernetes具有以下特點(diǎn):
- ?便攜性: 無(wú)論公有云、私有云、混合云還是多云架構(gòu)都全面支持
- 可擴(kuò)展: 它是模塊化、可插拔、可掛載、可組合的,支持各種形式的擴(kuò)展
- 自修復(fù): 它可以自保持應(yīng)用狀態(tài)、可自重啟、自復(fù)制、自縮放的,通過(guò)聲明式語(yǔ)法提供了強(qiáng)大的自修復(fù)能力
使用 Kubernetes, 您可以快速高效地響應(yīng)客戶(hù)需求:
- 快速、可預(yù)測(cè)地部署您的應(yīng)用程序
- 擁有即時(shí)擴(kuò)展應(yīng)用程序的能力
- 不影響現(xiàn)有業(yè)務(wù)的情況下,無(wú)縫地發(fā)布新功能
- 優(yōu)化硬件資源,降低成本
Kubernetes是一個(gè)聲明式系統(tǒng),聲明式系統(tǒng)和命令式系統(tǒng)?是有本質(zhì)的區(qū)別。所謂聲明式系統(tǒng)?關(guān)注點(diǎn)是做什么,即告訴你將要達(dá)成什么樣的期望,至于怎么達(dá)到是你系統(tǒng)的事情。而命令式系統(tǒng)則是必須按照相應(yīng)的規(guī)定或者步驟達(dá)到某個(gè)目標(biāo)或者完成某個(gè)任務(wù),其關(guān)注點(diǎn)是在怎么做。
命令式強(qiáng)調(diào)的是How,它需要你通過(guò)step-by-step的方式告訴計(jì)算機(jī)如何完成一個(gè)任務(wù),在這種場(chǎng)景下,計(jì)算機(jī)是不具備“智能”,智能很機(jī)械的完成任務(wù),至于完成的結(jié)果如何,需要看編程者的水平了。
而聲明式強(qiáng)調(diào)的是What,你只需要告訴計(jì)算機(jī)你想要什么,然后由計(jì)算機(jī)自己去執(zhí)行,這時(shí)候的計(jì)算機(jī)是具備一定的“智能”。當(dāng)然,聲明式不一定會(huì)滿(mǎn)足你所有的需要。
在日常工作中,命令式編程比較普遍,這種編程實(shí)現(xiàn)比較方便,只需要按照一定的步驟開(kāi)發(fā)即可,但是在一些特定的場(chǎng)合,聲明式要比命令式方便,其實(shí)大多數(shù)聲明式語(yǔ)言都是針對(duì)特定任務(wù)的領(lǐng)域?qū)S谜Z(yǔ)言,即DSL。
最常見(jiàn)的聲明式語(yǔ)言就是SQL,只需要告訴計(jì)算機(jī)你想要的結(jié)果集,數(shù)據(jù)庫(kù)就會(huì)幫你設(shè)計(jì)獲取這個(gè)結(jié)果集的執(zhí)行路徑,并返回結(jié)果。
Kubernetes就是一個(gè)聲明式系統(tǒng),在使用Kubernetes的時(shí)候,用戶(hù)不需要去定義A->B->C這種Workflow,而是直接去描述一個(gè)期望狀態(tài),然后Kubernetes就會(huì)幫助用戶(hù)達(dá)到這個(gè)狀態(tài),至于如何達(dá)到這個(gè)狀態(tài),用戶(hù)不需要關(guān)心。這種設(shè)計(jì)使得Kubernetes更加易用和健壯,也更具彈性和擴(kuò)展性。
Kubernetes的架構(gòu)
Kubernetes整體是Master-Slave架構(gòu),如下:
其中:
- etcd 保存了整個(gè)集群的狀態(tài),就是一個(gè)數(shù)據(jù)庫(kù),只有API Server能與其通信;
- apiserver 提供了資源操作的唯一入口,并提供認(rèn)證、授權(quán)、訪問(wèn)控制、API 注冊(cè)和發(fā)現(xiàn)等機(jī)制;
- controller manager 負(fù)責(zé)維護(hù)集群的狀態(tài),比如故障檢測(cè)、自動(dòng)擴(kuò)展、滾動(dòng)更新等;
- scheduler 負(fù)責(zé)資源的調(diào)度,按照預(yù)定的調(diào)度策略將 Pod 調(diào)度到相應(yīng)的機(jī)器上;
- kubelet 負(fù)責(zé)維護(hù)容器的生命周期,同時(shí)也負(fù)責(zé) Volume(CSI)和網(wǎng)絡(luò)(CNI)的管理;
- container runtime 負(fù)責(zé)鏡像管理以及 Pod 和容器的真正運(yùn)行(CRI);
- kube-proxy 負(fù)責(zé)為 Service 提供 cluster 內(nèi)部的服務(wù)發(fā)現(xiàn)和負(fù)載均衡;
- registry是鏡像倉(cāng)庫(kù),負(fù)責(zé)存儲(chǔ)容器鏡像
- kubectl和dashboard都是客戶(hù)端工具
上面的架構(gòu)是邏輯架構(gòu),在實(shí)際的生產(chǎn)運(yùn)用中,為了達(dá)到高可用,會(huì)對(duì)架構(gòu)做對(duì)應(yīng)的調(diào)整,調(diào)整對(duì)象就是主節(jié)點(diǎn),如下:
主要做了以下改變:
(1)將Master節(jié)點(diǎn)從單節(jié)點(diǎn)變成了多節(jié)點(diǎn),在kube-apiserver前增加了load balancer用來(lái)負(fù)載,其他組件通信都是通過(guò)LB進(jìn)行
(2)將etcd和master節(jié)點(diǎn)獨(dú)立開(kāi),避免由于某個(gè)master節(jié)點(diǎn)故障導(dǎo)致ectd受影響
Kubernetes架構(gòu)的設(shè)計(jì)原則是:
- 只有APIServer可以直接訪問(wèn)Etcd存儲(chǔ),其他服務(wù)必須通過(guò)Kubernetes API來(lái)訪問(wèn)集群的狀態(tài)
- 單節(jié)點(diǎn)故障原則上不應(yīng)該影響集群的狀態(tài)
- 在沒(méi)有新請(qǐng)求的情況下,所有組件應(yīng)該在故障恢復(fù)后繼續(xù)執(zhí)行上次最后收到的請(qǐng)求
- 所有組件應(yīng)該在內(nèi)存中保持所需要的狀態(tài),APIServer將狀態(tài)寫(xiě)入Etcd存儲(chǔ),而其他組件則通過(guò)APIServer更新并監(jiān)聽(tīng)所有的變化,最終由Controller Manager去協(xié)調(diào)
- 優(yōu)先使用事件監(jiān)聽(tīng)而不是輪詢(xún)
Kubernetes的重要組件
上面介紹了Kubernetes的整體架構(gòu)以及簡(jiǎn)單介紹了各個(gè)組件的作用,但是它們之間的關(guān)系具體如何并沒(méi)有做過(guò)多的介紹,我們現(xiàn)在來(lái)看看各個(gè)組件以及它們之間是怎么協(xié)作的。
(1)kubectl 客戶(hù)端首先將CLI命令轉(zhuǎn)化為RESTful的API調(diào)用,然后發(fā)送到kube-apiserver。
(2)kube-apiserver 在認(rèn)證、授權(quán)、準(zhǔn)入驗(yàn)證過(guò)后,將任務(wù)元信息并存儲(chǔ)到etcd,然后kube-scheduler會(huì)對(duì)任務(wù)進(jìn)行調(diào)度,并將調(diào)度結(jié)果返回給kube-apiserver。
(3)一旦 kube-scheduler 返回一個(gè)適合調(diào)度的目標(biāo)節(jié)點(diǎn)后,kube-apiserver 就把任務(wù)的節(jié)點(diǎn)信息存入etcd,并創(chuàng)建任務(wù)。
(4)此時(shí)目標(biāo)節(jié)點(diǎn)中的 kubelet正監(jiān)聽(tīng)apiserver,當(dāng)監(jiān)聽(tīng)到有新任務(wù)需要調(diào)度到本節(jié)點(diǎn)后,kubelet通過(guò)本地runtime創(chuàng)建任務(wù)容器,執(zhí)行作業(yè)。
(5)接著kubelet將任務(wù)狀態(tài)等信息返回給apiserver存儲(chǔ)到etcd。
(6)kube-proxy也會(huì)監(jiān)聽(tīng)apiserver,如果有網(wǎng)絡(luò)策略相關(guān)的操作,就會(huì)在本機(jī)上創(chuàng)建對(duì)應(yīng)的iptables或者ipvs規(guī)則。
(7)這樣我們的任務(wù)已經(jīng)在運(yùn)行了,此時(shí)control-manager發(fā)揮作用保證任務(wù)一直是我們期望的狀態(tài)。
其主要組件如下:
- Etcd
- API Server
- Controller Manager
- Scheduler
- Kubelet
- Kube-proxy
Etcd
Etcd 是兼具一致性和高可用性的鍵值存儲(chǔ),可用于服務(wù)發(fā)現(xiàn)、共享配置以及一致性保障,在Kubernetes中,Etcd是作為唯一的存儲(chǔ),保存Kubernetes的所有API對(duì)象。
在生產(chǎn)級(jí)Kubernetes中etcd通常會(huì)以集群的方式存在,安全原因,它只能從 API 服務(wù)器訪問(wèn)。
API Server
API Server是Kubernetes最重要的核心組件之一,主要提供以下功能:
- 提供集群管理的REST API接口,包括:
- 認(rèn)證
- 授權(quán)
- 準(zhǔn)入
- 為其他模塊提供數(shù)據(jù)交互和通信的樞紐
- API Server提供Etcd的數(shù)據(jù)緩存,減少集群對(duì)Etcd的訪問(wèn)
Controller Manager
Kubernetes在后臺(tái)運(yùn)行許多不同的控制器進(jìn)程,當(dāng)服務(wù)配置發(fā)生更改時(shí)(例如,替換運(yùn)行 pod 的鏡像,或更改配置 yaml 文件中的參數(shù)),控制器會(huì)發(fā)現(xiàn)更改并開(kāi)始朝著新的期望狀態(tài)工作。
從邏輯上講,每個(gè)控制器都是一個(gè)單獨(dú)的進(jìn)程, 但是為了降低復(fù)雜性,它們都被編譯到同一個(gè)可執(zhí)行文件,并在一個(gè)進(jìn)程中運(yùn)行??刂破靼?
- 節(jié)點(diǎn)控制器(Node Controller): 負(fù)責(zé)在節(jié)點(diǎn)出現(xiàn)故障時(shí)進(jìn)行通知和響應(yīng)
- 任務(wù)控制器(Job controller): 監(jiān)測(cè)代表一次性任務(wù)的 Job 對(duì)象,然后創(chuàng)建 Pods 來(lái)運(yùn)行這些任務(wù)直至完成
- 端點(diǎn)控制器(Endpoints Controller): 填充端點(diǎn)(Endpoints)對(duì)象(即加入 Service 與 Pod)
- 服務(wù)帳戶(hù)和令牌控制器(Service Account & Token Controllers): 為新的命名空間創(chuàng)建默認(rèn)帳戶(hù)和 API 訪問(wèn)令牌
下面就是Deployment Controller和ReplicaSet Controller兩個(gè)控制器的工作流程。
Scheduler
kube-scheduler 負(fù)責(zé)監(jiān)視新創(chuàng)建、未指定運(yùn)行Node的 Pods,決策出一個(gè)讓pod運(yùn)行的節(jié)點(diǎn)。例如,如果應(yīng)用程序需要 1GB 內(nèi)存和 2 個(gè) CPU 內(nèi)核,那么該應(yīng)用程序的 pod 將被安排在至少具有這些資源的節(jié)點(diǎn)上。每次需要調(diào)度 pod 時(shí),調(diào)度程序都會(huì)運(yùn)行。調(diào)度程序必須知道可用的總資源以及分配給每個(gè)節(jié)點(diǎn)上現(xiàn)有工作負(fù)載的資源。調(diào)度決策考慮的因素包括單個(gè) Pod 和 Pod 集合的資源需求、硬件/軟件/策略約束、親和性和反親和性規(guī)范、數(shù)據(jù)位置、工作負(fù)載間的干擾和最后時(shí)限。
調(diào)度總共分為三個(gè)階段:
- Predict:預(yù)選階段,過(guò)濾不能滿(mǎn)足業(yè)務(wù)需求的節(jié)點(diǎn)
- Priority:優(yōu)選階段,選擇最優(yōu)的節(jié)點(diǎn)
- Bind:綁定階段,將最優(yōu)節(jié)點(diǎn)和Pod進(jìn)行綁定,完成調(diào)度
Kubelet
Kubelet是每個(gè)節(jié)點(diǎn)上的核心組件之一,負(fù)責(zé)管理節(jié)點(diǎn)的資源對(duì)象。
- 從不同源獲取Pod清單,并按需啟停Pod
Pod清單可以來(lái)自本地文件目錄、給定的Http Server、API Server等
Kubelet將Container Runtime、Network、Stroage抽象成CRI、CNI、CSI
- 負(fù)責(zé)匯報(bào)節(jié)點(diǎn)的健康狀態(tài)以及資源信息
- 負(fù)責(zé)Pod的健康檢查和狀態(tài)匯報(bào)
Kube-proxy
kube-proxy 是集群中每個(gè)節(jié)點(diǎn)上運(yùn)行的網(wǎng)絡(luò)代理, 實(shí)現(xiàn) Kubernetes 服務(wù)(Service) 概念的一部分。用于處理單個(gè)主機(jī)子網(wǎng)劃分并向外部世界公開(kāi)服務(wù)。它跨集群中的各種隔離網(wǎng)絡(luò)將請(qǐng)求轉(zhuǎn)發(fā)到正確的 pod/容器。kube-proxy 維護(hù)節(jié)點(diǎn)上的網(wǎng)絡(luò)規(guī)則。這些網(wǎng)絡(luò)規(guī)則允許從集群內(nèi)部或外部的網(wǎng)絡(luò)會(huì)話與 Pod 進(jìn)行網(wǎng)絡(luò)通信。如果操作系統(tǒng)提供了數(shù)據(jù)包過(guò)濾層并可用的話,kube-proxy 會(huì)通過(guò)它來(lái)實(shí)現(xiàn)網(wǎng)絡(luò)規(guī)則。否則, kube-proxy 僅轉(zhuǎn)發(fā)流量本身。
其他組件
上面介紹的這些組件是集群的架子,光有架子還不夠,還需要第三方的組件讓其更強(qiáng)大:
- kube-dns:負(fù)責(zé)為整個(gè)集群提供DNS服務(wù),常用的是CoreDNS
- Ingress Controller:為集群提供外網(wǎng)訪問(wèn)入口
- Metrics-Server:為集群提供監(jiān)控資源
- DashBoard:提供GUI,方便運(yùn)維
- Prometheus:收集并監(jiān)控集群資源
- Grafana:圖形化展示監(jiān)控?cái)?shù)據(jù)
- ELK:收集、存儲(chǔ)、查詢(xún)集群日志