Kubernetes 是由谷歌開源的面向應(yīng)用的容器集群部署和管理的系統(tǒng),為容器化應(yīng)用提供了資源調(diào)度、部署運(yùn)行、服務(wù)發(fā)現(xiàn)、擴(kuò)縮容等一整套功能。Kubernetes 最初來源于谷歌內(nèi)部的 Borg。Kubernetes 的目標(biāo)旨在消除編排物理/虛擬計(jì)算,網(wǎng)絡(luò)和存儲(chǔ)基礎(chǔ)設(shè)施的負(fù)擔(dān),并使應(yīng)用程序運(yùn)營商和開發(fā)人員完全將重點(diǎn)放在以容器為中心的原語上進(jìn)行自助運(yùn)營。構(gòu)建在Kubernetes上的系統(tǒng)不僅可以獨(dú)立運(yùn)行在物理機(jī)、虛擬機(jī)集群或者企業(yè)私有云上,也可以被托管在公有云上。Kubernetes整體架構(gòu)的邏輯視圖如下所示:
可以看到Kubenetes架構(gòu)由Master和Node兩種節(jié)點(diǎn)組成,而這兩種角色分別對(duì)應(yīng)控制節(jié)點(diǎn)和計(jì)算節(jié)點(diǎn)。其中"控制節(jié)點(diǎn)",即Master節(jié)點(diǎn),由3個(gè)緊密協(xié)作的獨(dú)立組件組合而成,分別是負(fù)責(zé)API服務(wù)的API Server、負(fù)責(zé)調(diào)度的Scheduler以及負(fù)責(zé)容器編排的Controller Manager。整個(gè)集群的持久化數(shù)據(jù),則由API Server處理后保存在etcd中。
計(jì)算節(jié)點(diǎn),即Node節(jié)點(diǎn),由以下組件組成,分別管理Pod和同容器運(yùn)行時(shí)交互和監(jiān)控容器和節(jié)點(diǎn)資源的kubelet&、負(fù)責(zé)Service的透明代理兼負(fù)載均衡器,輔助將到達(dá)某個(gè)Service的訪問請(qǐng)求轉(zhuǎn)發(fā)到后端的多個(gè)Pod實(shí)例上的kube-proxy。此外,Kubernetes還支持通過插件的方式,來擴(kuò)展資功能。而這些插件通常都部署在計(jì)算節(jié)點(diǎn)上,如coreDNS等。
API Server簡(jiǎn)介
API Server的核心功能是提供Kubernetes各類資源對(duì)象(如Pod、RC、Service等)的增、刪、改、查及Watch等HTTP REST接口(資源對(duì)象的管理和監(jiān)聽),成為集群內(nèi)各個(gè)功能模塊之間數(shù)據(jù)交互和通信的中心樞紐,是整個(gè)系統(tǒng)的數(shù)據(jù)總線和數(shù)據(jù)中心。除此之外,它還是集群管理的API入口,是資源配額控制的入口,提供了完備的集群安全機(jī)制。
API Server通過一個(gè)名為kube-apiserver的進(jìn)程提供服務(wù),該進(jìn)程運(yùn)行在Master上。在默認(rèn)情況下,kube-apiserver進(jìn)程在本機(jī)的8080端口(對(duì)應(yīng)參數(shù)–insecure-port)提供REST服務(wù)。也可以啟動(dòng)HTTPS安全端口(–secure-port=6443)來啟動(dòng)安全機(jī)制,加強(qiáng) REST API訪問的安全性。通常通過命令行工具kubectl與Kubernetes API Server交互,它們之間的接口是RESTful API。由于API Server是Kubernetes集群數(shù)據(jù)的唯一訪問入口,因此安全性與高性能成為API Server設(shè)計(jì)和實(shí)現(xiàn)的兩大核心目標(biāo)。
API Server架構(gòu)從上到下可以分為以下幾層:
(1) API層:主要以REST方式提供各種API接口,除了有 Kubernetes資源對(duì)象的CRUD和Watch等主要API,還有健康檢查、UI、日志、性能指標(biāo)等運(yùn)維監(jiān)控相關(guān)的API。Kubernetes從1.11版本開始廢棄 Heapster監(jiān)控組件,轉(zhuǎn)而使用Metrics Server提供Metrics API接口,進(jìn)一步完善了自身的監(jiān)控能力。
(2) 訪問控制層:當(dāng)客戶端訪問API接口時(shí),訪問控制層負(fù)責(zé)對(duì)用戶身份鑒權(quán),驗(yàn)明用戶身份,核準(zhǔn)用戶對(duì)Kubernetes資源對(duì)象的訪問權(quán)限,然后根據(jù)配置的各種資源訪問許可邏輯(Admission Control),判斷是否允許訪問。
(3) 注冊(cè)表層:Kubernetes把所有資源對(duì)象都保存在注冊(cè)表(Registry)中,針對(duì)注冊(cè)表中的各種資源對(duì)象都定義了資源對(duì)象的類型、如何創(chuàng)建資源對(duì)象、如何轉(zhuǎn)換資源的不同版本,以及如何將資源編碼和解碼為JSON或ProtoBuf格式進(jìn)行存儲(chǔ)。
(4) etcd數(shù)據(jù)庫:用于持久化存儲(chǔ)Kubernetes資源對(duì)象的KV數(shù)據(jù)庫。etcd的Watch API接口對(duì)于API Server來說至關(guān)重要,因?yàn)橥ㄟ^這個(gè)接口,API Server創(chuàng)新性地設(shè)計(jì)了List-Watch這種高性能的資源對(duì)象實(shí)時(shí)同步機(jī)制,使Kubernetes可以管理超大規(guī)模的集群,及時(shí)響應(yīng)和快速處理集群中的各種事件。
集群內(nèi)功能模塊的通信樞紐
Kubernetes API Server作為集群的核心,負(fù)責(zé)集群各功能模塊之間的通信。集群內(nèi)的各個(gè)功能模塊通過API Server將信息存入etcd中,當(dāng)需要獲取和操作這些數(shù)據(jù)時(shí),則通過API Server提供的REST接口(用GET、LIST或WATCH方法)來實(shí)現(xiàn),從而實(shí)現(xiàn)各模塊之間的信息交互。
(1) Scheduler進(jìn)程與API Server的交互。Scheduler在通過API Server的Watch接口監(jiān)聽到新建Pod副本的信息后,會(huì)檢索并過濾所有符合該P(yáng)od要求的Node列表,開始執(zhí)行Pod調(diào)度邏輯,在調(diào)度成功后將Pod綁定到目標(biāo)節(jié)點(diǎn)上。
(2) Controller Manager進(jìn)程與API Server的交互。如Controller Manager中的Node Controller模塊通過API Server提供的Watch接口實(shí)時(shí)監(jiān)控Node的信息,并做相應(yīng)的處理。
(3) etcd進(jìn)程與API Server的交互。API Server通過etcd的Watch API接口實(shí)現(xiàn)了List-Watch這種高性能的資源對(duì)象實(shí)時(shí)同步機(jī)制,使Kubernetes可以管理超大規(guī)模的集群,及時(shí)響應(yīng)和快速處理集群中的各種事件。
(4) kubelet進(jìn)程與API Server的交互。每個(gè) Node 上的kubelet每隔一個(gè)時(shí)間周期就會(huì)調(diào)用一次API Server的REST接口報(bào)告自身狀態(tài),API Server在接收到這些信息后,會(huì)將節(jié)點(diǎn)狀態(tài)信息更新到 etcd中。此外,kubelet也通過API Server的Watch接口監(jiān)聽Pod信息,如果監(jiān)聽到新的Pod副本被調(diào)度綁定到本節(jié)點(diǎn),則執(zhí)行Pod對(duì)應(yīng)的容器創(chuàng)建和啟動(dòng)邏輯;如果監(jiān)聽到Pod對(duì)象被刪除,則刪除本節(jié)點(diǎn)上相應(yīng)的Pod容器;如果監(jiān)聽到修改Pod的信息,kubelet就會(huì)相應(yīng)地修改本節(jié)點(diǎn)的Pod容器。
(5) kube-proxy與API Server的交互。kube-proxy 通過 API Server的WATCH接口,監(jiān)聽Service、EndPoint、Node 等資源對(duì)象的變化情況。
Scheduler簡(jiǎn)介
Kubernetes Scheduler是負(fù)責(zé)Pod調(diào)度的組件,隨著Kubernetes功能的不斷增強(qiáng)和完善,Pod調(diào)度也變得越來越復(fù)雜,Kubernetes Scheduler內(nèi)部的實(shí)現(xiàn)機(jī)制也在不斷優(yōu)化,從最初的兩階段調(diào)度機(jī)制(Predicates&Priorities,謂詞(可理解為過濾)和優(yōu)先級(jí)(可理解為打分))發(fā)展到后來的升級(jí)版(從1.6版本開始)的調(diào)度框架(Scheduling Framework),以滿足越來越復(fù)雜的調(diào)度場(chǎng)景。
Scheduler調(diào)度流程簡(jiǎn)介
Kubernetes Scheduler的作用是將待調(diào)度的Pod(API新創(chuàng)建的Pod、Controller Manager為補(bǔ)足副本而創(chuàng)建的Pod等)按照特定的調(diào)度算法和調(diào)度策略綁定(Binding)到集群中某個(gè)合適的Node上,并將綁定信息寫入etcd中。簡(jiǎn)單地說,Kubernetes Scheduler的作用就是通過調(diào)度算法為待調(diào)度Pod列表中的每個(gè)Pod都從Node列表中選擇一個(gè)最適合的 Node,并將綁定信息同步到etcd。
Scheduler Framework簡(jiǎn)介
考慮到新的Scheduling Framework的代碼和功能大部分來自之前舊的兩階段調(diào)度流程,所以這里有必要先介紹一下舊版本的兩階段調(diào)度流程。舊版本的Kubernetes Scheduler的調(diào)度總體上包括兩個(gè)階段:過濾(Filtering) + 打分(Scoring),隨后就是綁定目標(biāo)節(jié)點(diǎn),完成調(diào)度。
(1) 過濾階段:遍歷所有目標(biāo)Node,篩選出符合要求的候選節(jié)點(diǎn)。在此階段,Scheduler會(huì)將不合適的所有Node節(jié)點(diǎn)全部過濾,只留下符合條件的候選節(jié)點(diǎn)。其具體方式是通過一系列特定的Filter(如磁盤Filter、節(jié)點(diǎn)上的可用端口Filter,等等)對(duì)每個(gè)Node都進(jìn)行篩選,篩選完成后通常會(huì)有多個(gè)候選節(jié)點(diǎn)供調(diào)度,從而進(jìn)入打分階段;如果結(jié)果集為空,則表示當(dāng)前還沒有符合條件的Node節(jié)點(diǎn),Pod會(huì)維持在Pending狀態(tài)。
(2) 打分階段:在過濾階段的基礎(chǔ)上,采用優(yōu)選策略(xxx Priorities,如選出資源消耗最小的節(jié)點(diǎn)、優(yōu)先選擇含有指定Label的節(jié)點(diǎn),等等)計(jì)算出每個(gè)候選節(jié)點(diǎn)的積分,積分最高者勝出,因?yàn)榉e分最高者表示最佳人選。挑選出最佳節(jié)點(diǎn)后,Scheduler會(huì)把目標(biāo)Pod安置到此節(jié)點(diǎn)上,調(diào)度完成。
考慮到舊版本的Kubernetes Scheduler不足以支持更復(fù)雜和靈活的調(diào)度場(chǎng)景,因此在Kubernetes 引入一個(gè)新的調(diào)度機(jī)制——Scheduler Framework。從整個(gè)調(diào)度流程來看,新的Scheduler Framework 是在舊流程的基礎(chǔ)上增加了一些擴(kuò)展點(diǎn)(基于調(diào)度Stage的擴(kuò)展點(diǎn)),同時(shí)支持用戶以插件的方式(Plugin)進(jìn)行擴(kuò)展。新的調(diào)度流程如下圖所示:
多調(diào)度器特性
Kubernetes自帶一個(gè)默認(rèn)調(diào)度器,從1.2版本開始引入自定義調(diào)度器的特性,支持使用用戶實(shí)現(xiàn)的自定義調(diào)度器,多個(gè)自定義調(diào)度器可以與默認(rèn)的調(diào)度器同時(shí)運(yùn)行,由Pod選擇是用默認(rèn)的調(diào)度器調(diào)度還是用某個(gè)自定義調(diào)度器調(diào)度。
Kubernetes通過一個(gè)Scheduler進(jìn)程加上多個(gè)配置文件的方式來實(shí)現(xiàn)多調(diào)度器特性。只要針對(duì)不同的調(diào)度規(guī)則編寫不同的Profile配置文件,并給它們起一個(gè)自定義Scheduler的名稱,然后把這個(gè)配置文件傳遞給Kubernetes Scheduler加載、生效,Kubernetes Scheduler就立即實(shí)現(xiàn)了多調(diào)度器支持的特性。
Controller Manager簡(jiǎn)介
一般來說,智能系統(tǒng)和自動(dòng)系統(tǒng)通常會(huì)通過一個(gè)"操作系統(tǒng)"不斷修正系統(tǒng)的工作狀態(tài)。在Kubernetes集群中,每個(gè)Controller都是這樣的一個(gè)"操作系統(tǒng)",它們通過API Server提供的(List-Watch)接口實(shí)時(shí)監(jiān)控集群中特定資源的狀態(tài)變化,當(dāng)發(fā)生各種故障導(dǎo)致某資源對(duì)象的狀態(tài)變化時(shí),Controller會(huì)嘗試將其狀態(tài)調(diào)整為期望的狀態(tài)。比如當(dāng)某個(gè)Node意外宕機(jī)時(shí),Node Controller會(huì)及時(shí)發(fā)現(xiàn)此故障并執(zhí)行自動(dòng)化修復(fù)流程,確保集群始終處于預(yù)期的工作狀態(tài)下。Controller Manager是 Kubernetes中各種操作系統(tǒng)的管理者,是集群內(nèi)部的管理控制中心,也是Kubernetes自動(dòng)化功能的核心。這里介紹常見的幾種Controller。
ResourceQuota Controller
作為完備的企業(yè)級(jí)的容器集群管理平臺(tái),Kubernetes也提供了 ResourceQuota Controller(資源配額管理)這一高級(jí)功能,資源配額管理確保指定的資源對(duì)象在任何時(shí)候都不會(huì)超量占用系統(tǒng)物理資源,避免由于某些業(yè)務(wù)進(jìn)程在設(shè)計(jì)或?qū)崿F(xiàn)上的缺陷導(dǎo)致整個(gè)系統(tǒng)運(yùn)行紊亂甚至意外宕機(jī),對(duì)整個(gè)集群的平穩(wěn)運(yùn)行和穩(wěn)定性都有非常重要的作用。
目前Kubernetes支持如下三個(gè)層次的資源配額管理:
(1) 容器級(jí)別,可以對(duì)一個(gè)容器的CPU和Memory的可用資源進(jìn)行限制。
(2) Pod級(jí)別,可以對(duì)一個(gè)Pod內(nèi)所有容器的可用資源進(jìn)行限制。
(3) Namespace級(jí)別,為Namespace(多租戶)級(jí)別的資源限制,包括:Pod數(shù)量、Replication Controller數(shù)量、Service數(shù)量、ResourceQuota數(shù)量、Secret數(shù)量和可持有的PV數(shù)量等。
Kubernetes的配額管理是通過Admission Control(準(zhǔn)入控制)來控制的,Admission Control當(dāng)前提供了兩種方式的配額約束,分別是 LimitRanger與ResourceQuota,其中LimitRanger作用于Pod和Container;ResourceQuota則作用于Namespace,限定一個(gè)Namespace里各類資源的使用總額。
Namespace Controller
Namespace Controller定時(shí)通過API Server讀取Namespace的信息。如果Namespace被API標(biāo)識(shí)為優(yōu)雅刪除(通過設(shè)置刪除期限實(shí)現(xiàn),即設(shè)置 DeletionTimestamp屬性),則將該NameSpace的狀態(tài)設(shè)置成Terminating并保存在etcd中。同時(shí),Namespace Controller刪除該Namespace下的 ServiceAccount、RC、Pod、Secret、PersistentVolume、ListRange、ResourceQuota和Event等資源對(duì)象。
在Namespace的狀態(tài)被設(shè)置成Terminating后,由Admission Controller的NamespaceLifecycle插件來阻止為該Namespace創(chuàng)建新的資源。同時(shí),在Namespace Controller刪除該Namespace中的所有資源對(duì)象后,Namespace Controller會(huì)對(duì)該Namespace執(zhí)行finalize操作,刪除 Namespace的spec.finalizers域中的信息。
如果Namespace Controller觀察到Namespace設(shè)置了刪除期限,同時(shí)Namespace的spec.finalizers域值是空的,那么Namespace Controller將通 過API Server刪除該Namespace資源。
Service Controller與Endpoints Controller
Endpoints表示一個(gè)Service對(duì)應(yīng)的所有Pod副本的訪問地址,Endpoints Controller就是負(fù)責(zé)生成和維護(hù)所有Endpoints對(duì)象的控制器。
Endpoints Controller負(fù)責(zé)監(jiān)聽Service和對(duì)應(yīng)的Pod副本的變化,如果監(jiān)測(cè)到Service被刪除,則刪除和該Service同名的Endpoints對(duì)象。如果監(jiān)測(cè)到新的Service被創(chuàng)建或者修改,則根據(jù)該Service信息獲得相關(guān)的Pod列表,然后創(chuàng)建或者更新Service對(duì)應(yīng)的Endpoints對(duì)象。如果監(jiān)測(cè)到Pod的事件,則更新它所對(duì)應(yīng)的Service的Endpoints對(duì)象(增加、刪除或者修改對(duì)應(yīng)的Endpoint條目)。
Service Controller則是Kubernetes集群與外部通信的一個(gè)接口控制器。Service Controller監(jiān)聽Service的變化,如果該Service是一個(gè)LoadBalancer類型的Service(externalLoadBalancers=true),則Service Controller確保該Service對(duì)應(yīng)的LoadBalancer實(shí)例在外部的云平臺(tái)上被相應(yīng)地創(chuàng)建、刪除及更新路由轉(zhuǎn)發(fā)表(根據(jù)Endpoints的條目)。
Service、Endpoints、Pod的關(guān)系
Service、Endpoints、Pod的關(guān)系如下圖所示:
可以看到,Endpoints記錄一個(gè)Service和多個(gè)Pod的對(duì)應(yīng)關(guān)系,幫助從Service路由到特定的Pod。
kubelet 簡(jiǎn)介
在Kubernetes集群中,在每個(gè)Node上都會(huì)啟動(dòng)一個(gè)kubelet服務(wù)進(jìn)程。在Node節(jié)點(diǎn)上,最核心的一個(gè)組件是kubelet。kubelet負(fù)責(zé)節(jié)點(diǎn)、Pod的管理,容器的健康檢查,資源監(jiān)控,與容器運(yùn)行時(shí)交互等職責(zé)。
在與容器運(yùn)行時(shí)交互時(shí),kubelet依賴的是—個(gè)稱作CRI(container runtime interface)的遠(yuǎn)程調(diào)用接口,該接口定義了容器運(yùn)行時(shí)的各項(xiàng)核心操作,比如啟動(dòng)一個(gè)容器需要的所有參數(shù)。kubelet的另—個(gè)重要功能,則是調(diào)用網(wǎng)絡(luò)插件和存儲(chǔ)插件為容器配置網(wǎng)絡(luò)和持久化存儲(chǔ)。這兩個(gè)插件與kubelet進(jìn)行交互的接口,分別是CNI(container networking interface)和CSI(container storage interface)。Kubectl通過接口標(biāo)準(zhǔn)化實(shí)現(xiàn)了對(duì)特定組件的解耦。
節(jié)點(diǎn)管理
節(jié)點(diǎn)通過設(shè)置kubelet的啟動(dòng)參數(shù)"–register-node",來決定是否向API Server注冊(cè)自己。如果在集群運(yùn)行過程中遇到集群資源不足的情況,用戶就很容易通過添加機(jī)器及運(yùn)用kubelet的自注冊(cè)模式來實(shí)現(xiàn)擴(kuò)容。在某些情況下,Kubernetes集群中的某些kubelet沒有選擇自注冊(cè)模式,用戶需要自己去配置Node的資源信息,同時(shí)告知Node上kubelet API Server的位置。
kubelet在啟動(dòng)時(shí)通過API Server注冊(cè)節(jié)點(diǎn)信息,并定時(shí)向API Server 發(fā)送節(jié)點(diǎn)的新消息,API Server在接收到這些信息后,會(huì)將其寫入etcd中。通過kubelet的啟動(dòng)參數(shù)–node-status-update-frequency可設(shè)置kubelet 每隔多長(zhǎng)時(shí)間向API Server報(bào)告節(jié)點(diǎn)的狀態(tài),默認(rèn)為10秒。
Pod管理
所有以非API Server方式創(chuàng)建的Pod都叫作靜態(tài)Pod(Static Pod)。反之,通過API Server方式創(chuàng)建的Pod叫做動(dòng)態(tài)Pod。
常見的靜態(tài)Pod創(chuàng)建方式有兩種:(1) 靜態(tài)Pod配置文件:kubelet通過啟動(dòng)參數(shù)–config指定目錄下的Pod YAML文件(默認(rèn)目錄為/etc/kubernetes/manifests/),kubelet會(huì)持續(xù)監(jiān)控指定目錄下的文件變化,以創(chuàng)建或刪除Pod。這種類型的Pod沒有通過kube-controller-manager管理。另外,可以 通過啟動(dòng)參數(shù)–file-check-frequency設(shè)置檢查該目錄的時(shí)間間隔,默認(rèn)為 20 秒。(2) HTTP端點(diǎn)(URL):通過–manifest-url參數(shù)設(shè)置,通過–http- check-frequency設(shè)置檢查該HTTP端點(diǎn)數(shù)據(jù)的時(shí)間間隔,默認(rèn)為 20 秒。
kubelet將靜態(tài)Pod的狀態(tài)匯報(bào)給API Server,API Server為該Static Pod創(chuàng)建一個(gè)鏡像Pod(Mirror Pod)與其匹配。鏡像Pod的狀態(tài)將真實(shí)反映靜態(tài)Pod的狀態(tài)。當(dāng)靜態(tài)Pod被刪除時(shí),與之相對(duì)應(yīng)的鏡像Pod也會(huì)被刪除。
每個(gè) Node 上的kubelet每隔一個(gè)時(shí)間周期就會(huì)調(diào)用一次API Server的REST接口報(bào)告自身狀態(tài),API Server在接收到這些信息后,會(huì)將節(jié)點(diǎn)狀態(tài)信息更新到etcd中。此外,kubelet也通過API Server的Watch接口監(jiān)聽Pod信息,如果監(jiān)聽到新的Pod副本被調(diào)度綁定到本節(jié)點(diǎn),則執(zhí)行Pod對(duì)應(yīng)的容器創(chuàng)建和啟動(dòng)邏輯;如果監(jiān)聽到Pod對(duì)象被刪除,則刪除本節(jié)點(diǎn)上相應(yīng)的Pod容器;如果監(jiān)聽到修改Pod的信息,kubelet就會(huì)相應(yīng)地修改本節(jié)點(diǎn)的Pod容器。
容器健康檢查
Kubernetes對(duì)Pod的健康狀態(tài)可以通過三類探針來檢查: LivenessProbe(存活探針)、ReadinessProbe(就緒探針)及StartupProbe(啟動(dòng)探針),其中最主要的探針為L(zhǎng)ivenessProbe與ReadinessProbe,kubelet會(huì)定期執(zhí)行這兩類探針來診斷容器的健康狀況。其中LivenessProbe探針,用于判斷容器是否健康并反饋給kubelet,如果LivenessProbe探針探測(cè)到容器不健康,則kubelet將刪除該容器,并根據(jù)容器的重啟策略做相應(yīng)的處理;如果一個(gè)容器不包含LivenessProbe探針,則kubelet會(huì)認(rèn)為該容器的LivenessProbe探針返回的值是Success。而ReadinessProbe探針,用于判斷容器是否啟動(dòng)完成,且準(zhǔn)備接收請(qǐng)求。如果ReadinessProbe探針檢測(cè)到容器啟動(dòng)失敗,則Pod的狀態(tài)將被修改,Endpoint Controller將從Service的Endpoint中刪除包含該容器所在Pod的IP地址的Endpoint條目。
此外,為了自定義Pod的可用性探測(cè)方式,Kubernetes在1.14版本引入Pod Readiness Gates。Pod Readiness Gates給予了Pod之外的組件控制某個(gè)Pod就緒的能力,通過Pod Readiness Gates機(jī)制,用戶可以設(shè)置自定義的Pod可用性探測(cè)方式來告訴Kubernetes某個(gè)Pod是否可用,具體使用方式是用戶提供一個(gè)外部的控制器(Controller)來設(shè)置相應(yīng)Pod的可用性狀態(tài)。
資源監(jiān)控
在Kubernetes集群中,應(yīng)用程序的執(zhí)行情況可以在不同的級(jí)別監(jiān)測(cè)到,這些級(jí)別包括容器、Pod、Service和整個(gè)集群。作為Kubernetes集群的一部分,Kubernetes希望提供給用戶詳細(xì)的各個(gè)級(jí)別的資源使用信息,這將使用戶深入地了解應(yīng)用的執(zhí)行情況,并找到應(yīng)用中可能的瓶頸。
kubelet作為連接Kubernetes Master和各Node的橋梁,管理運(yùn)行在Node上的Pod和容器。kubelet將每個(gè)Pod都轉(zhuǎn)換成它的成員容器,同時(shí)獲取單獨(dú)的容器使用統(tǒng)計(jì)信息,然后通過該REST API暴露這些聚合后的Pod資源使用的統(tǒng)計(jì)信息。
從Kubernetes 1.8版本開始,性能指標(biāo)數(shù)據(jù)的查詢接口升級(jí)為標(biāo)準(zhǔn)的Metrics API,后端服務(wù)則升級(jí)為全新的Metrics Server。Metrics Server 可以提供Core Metrics(核心指標(biāo)),包括Node和Pod的CPU和內(nèi)存使用數(shù)據(jù)。其他 Custom Metrics(自定義指標(biāo))則由第三方組件(如Prometheus)采集和存儲(chǔ)。
容器運(yùn)行時(shí)
kubelet負(fù)責(zé)本節(jié)點(diǎn)上所有Pod的全生命周期管理,其中就包括相關(guān)容器的創(chuàng)建和銷毀這種基本操作。容器的創(chuàng)建和銷毀等操作的代碼不屬于Kubernetes的代碼范疇。kubelet需要通過某種進(jìn)程間的調(diào)用方式如gRPC來實(shí)現(xiàn)與Docker容器引擎之間的調(diào)用控制功能。
"容器"概念是早于Docker出現(xiàn)的,容器技術(shù)最早來自Linux,又被稱為L(zhǎng)inux Container。LXC項(xiàng)目是一個(gè)Linux容器的工具集,也是真正意義上的一個(gè)Container Runtime,它的作用就是將用戶的進(jìn)程包裝成一個(gè)Linux容器并啟動(dòng)運(yùn)行。Docker最初使用了LXC項(xiàng)目代碼作為Container Runtime來運(yùn)行容器,但從0.9版本開始就使用新一代容器運(yùn)行時(shí)Libcontainer替代,再后來,Libcontainer項(xiàng)目更名為runC,被Docker公司捐贈(zèng)給了OCI組織,成為OCI容器運(yùn)行時(shí)規(guī)范的第1個(gè)標(biāo)準(zhǔn)參考實(shí)現(xiàn)。所以,LXC與runC其實(shí)都可被看作開源的 Container Runtime,但它們都屬于低級(jí)別的容器運(yùn)行時(shí)(low-level container runtimes),因?yàn)樗鼈儾簧婕叭萜鬟\(yùn)行時(shí)所依賴的鏡像操作功能,如拉取鏡像,也沒有對(duì)外提遠(yuǎn)程供編程接口以方便其他應(yīng)用集成。
后來又有了高級(jí)別容器運(yùn)行時(shí)(high-level container runtimes),其中最知名的就是Docker公司開源的containerd。containerd 被設(shè)計(jì)成嵌入一個(gè)更大的系統(tǒng),如Kubernetes中使用,而不是直接由開發(fā)人員或終端用戶使用,containerd底層驅(qū)動(dòng)runC來實(shí)現(xiàn)底層的容器運(yùn)行時(shí),對(duì)外則提供了鏡像拉取及基于gRPC接口的容器CRUD封裝接口。發(fā)展至今,containerd已經(jīng)從Docker里的一個(gè)內(nèi)部組件,變成一個(gè)流行的、工業(yè)級(jí)的開源容器運(yùn)行時(shí),已經(jīng)支持容器鏡像的獲取和存儲(chǔ)、容器的執(zhí)行和管理、存儲(chǔ)和網(wǎng)絡(luò)等相關(guān)功能。
除了containerd,還有類似的其他一些高級(jí)別容器運(yùn)行時(shí)也都在runC的基礎(chǔ)上發(fā)展而來,目前比較流行的有紅帽開源的CRI-O、openEuler社區(qū)開源的iSula等。這些Container Runtime還有另外一個(gè)共同特點(diǎn),即都實(shí)現(xiàn)了Kubernetes提出的CRI接口規(guī)范(Container Runtime Interface), 可以直接接入Kubernetes中。
CRI接口規(guī)范,就是容器運(yùn)行時(shí)接口規(guī)范,這個(gè)規(guī)范是Kubernetes順應(yīng)容器技術(shù)標(biāo)準(zhǔn)化發(fā)展潮流的一個(gè)重要?dú)v史產(chǎn)物,早在Kubernetes 1.5版本中就引入了CRI接口規(guī)范。引入了CRI接口規(guī)范后,kubelet就可以通過CRI插件來實(shí)現(xiàn)容器的全生命周期控制,不同廠家的Container Runtime只需實(shí)現(xiàn)對(duì)應(yīng)的 CRI插件代碼即可,Kubernetes無須重新編譯就可以使用更多的容器運(yùn)行時(shí)。
隨著CRI機(jī)制的成熟及第三方Container Runtime的不斷涌現(xiàn),用戶有了新的需求:在一個(gè)Kubernetes集群中配置并啟用多種Container Runtime,不同類型的Pod可以選擇不同特性的Container Runtime來運(yùn)行,以實(shí)現(xiàn)資源占用或者性能、穩(wěn)定性等方面的優(yōu)化,這就是RuntimeClass出現(xiàn)的背景和動(dòng)力。Kubernetes從1.12版本開始引入 RuntimeClass,用于在啟動(dòng)容器時(shí)選擇特定的容器運(yùn)行時(shí)。在1.14 之后,它又作為一種內(nèi)置集群資源對(duì)象 RuntimeClass 被引入進(jìn)來。1.16 又在 1.14 的基礎(chǔ)上擴(kuò)充了 Scheduling 和 Overhead 的能力。
通過在配置文件中指定Container Runtime 的類型,一旦創(chuàng)建好RuntimeClass資源,就可以通過Pod中的 spec.runtimeClassName字段與它進(jìn)行關(guān)聯(lián)了。當(dāng)目標(biāo)Pod被調(diào)度到某個(gè)具體的kubelet時(shí),kubelet就會(huì)通過CRI接口調(diào)用指定的Container Runtime 來運(yùn)行該P(yáng)od,如果指定的RuntimeClass不存在,無法運(yùn)行相應(yīng)的 Container Runtime,那么Pod會(huì)進(jìn)入Failed狀態(tài)。
kube-proxy 簡(jiǎn)介
Kubernetes集群的每個(gè)Node上都會(huì)運(yùn)行一個(gè)kube-proxy服務(wù)進(jìn)程,可以把這個(gè)進(jìn)程看作Service的透明代理兼負(fù)載均衡器,其核心功能是將到某個(gè)Service的訪問請(qǐng)求轉(zhuǎn)發(fā)到后端的多個(gè)Pod實(shí)例上。
kube-proxy在運(yùn)行過程中動(dòng)態(tài)創(chuàng)建與Service相關(guān)的iptables規(guī)則,這些規(guī)則實(shí)現(xiàn)了將訪問服務(wù)(ClusterIP或NodePort)的請(qǐng)求負(fù)載分發(fā)到后端Pod的功能。由于iptables機(jī)制針對(duì)的是本地的kube-proxy端口,所以在每個(gè)Node上都要運(yùn)行kube-proxy組件,這樣一來,在Kubernetes集群內(nèi)部,可以在任意Node上發(fā)起對(duì)Service的訪問請(qǐng)求。綜上所述,由于kube-proxy的作用,客戶端在 Service調(diào)用過程中無須關(guān)心后端有幾個(gè)Pod,中間過程的通信、負(fù)載均衡及故障恢復(fù)都是透明的。
Client向Service的請(qǐng)求流量通過IPVS(IP Virtual Server)轉(zhuǎn)發(fā)到目標(biāo)Pod,不經(jīng)過kube-proxy進(jìn)程的轉(zhuǎn)發(fā),kube-proxy進(jìn)程只承擔(dān)了控制層面的功能(可見kube-proxy本身無法實(shí)現(xiàn)請(qǐng)求的轉(zhuǎn)發(fā)),即通過API Server的Watch接口實(shí)時(shí)跟蹤Service與Endpoint的變更信息,并更新Node節(jié)點(diǎn)上的IPVS。
iptables與IPVS雖然都是基于Netfilter實(shí)現(xiàn)的,但因?yàn)槎ㄎ徊煌?,二者有著本質(zhì)的差別:iptables是為防火墻設(shè)計(jì)的;IPVS專門用于高性能負(fù)載均衡,并使用更高效的數(shù)據(jù)結(jié)構(gòu)(哈希表),允許幾乎無限的規(guī)模。
由于IPVS無法提供包過濾、airpin-masquerade tricks(地址偽裝)、 SNAT等功能,因此在某些場(chǎng)景(如NodePort的實(shí)現(xiàn))下還要與iptables搭配使用。在IPVS模式下,kube-proxy又做了重要的升級(jí),即使用iptables的擴(kuò)展ipset,而不是直接調(diào)用iptables來生成規(guī)則鏈。文章來源:http://www.zghlxwxcb.cn/news/detail-804662.html
參考
《Kubernetes權(quán)威指南 從Docker到Kubernetes實(shí)踐全接觸》 龔正 吳治輝 閆健勇 編著
《深入剖析Kubernetes》 張磊 著
https://lib.jimmysong.io/kubernetes-handbook/architecture/ Kubernetes 架構(gòu)
https://zhuanlan.zhihu.com/p/149403551 了解Kubernetes內(nèi)部的架構(gòu)
http://docs.kubernetes.org.cn/251.html Kubernetes 架構(gòu)
https://zhuanlan.zhihu.com/p/444114515 Kubernetes核心架構(gòu)與高可用集群詳解
https://zhuanlan.zhihu.com/p/161347454 Kubernetes: 微內(nèi)核的分布式操作系統(tǒng)
https://zhuanlan.zhihu.com/p/467382099 kubernetes核心組件的運(yùn)行機(jī)制文章來源地址http://www.zghlxwxcb.cn/news/detail-804662.html
到了這里,關(guān)于Kubernetes架構(gòu)概述的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!