新手必須知道的 Kubernetes 架構(gòu)

控制平面組件
ETCD
etcd 是一個(gè)快速、分布式、一致的鍵值存儲(chǔ),用作持久存儲(chǔ) Kubernetes 對(duì)象數(shù)據(jù)(如 pod、replication controllers, secrets, services 等)的后備存儲(chǔ)。實(shí)際上,etcd 是 Kubernetes 存儲(chǔ)集群狀態(tài)和元數(shù)據(jù)的唯一地方。唯一直接與 etcd 對(duì)話的組件是 Kubernetes API Server。所有其他組件通過 API Server 間接讀取和寫入數(shù)據(jù)到 etcd。
Etcd 還實(shí)現(xiàn)了一個(gè)監(jiān)視功能,它提供了一個(gè)基于事件的接口,用于異步監(jiān)控鍵的更改。一旦密鑰被更改,它的觀察者就會(huì)收到通知。API Server 組件在很大程度上依賴于此來獲得通知并將 etcd 的當(dāng)前狀態(tài)移動(dòng)到所需狀態(tài)。
etcd 實(shí)例的數(shù)量應(yīng)該是奇數(shù)嗎?
在 HA 環(huán)境中,您通常會(huì)運(yùn)行 3、5 或 7 個(gè) etcd 實(shí)例,但為什么呢?由于 etcd 是分布式數(shù)據(jù)存儲(chǔ),因此可以水平擴(kuò)展它,但您還需要確保每個(gè)實(shí)例中的數(shù)據(jù)是一致的,為此,您的系統(tǒng)需要就狀態(tài)達(dá)成共識(shí)。Etcd 為此使用了RAFT 共識(shí)算法[1]。
該算法需要多數(shù)(或仲裁)集群才能進(jìn)入下一個(gè)狀態(tài)。如果您只有 2 個(gè) ectd 實(shí)例,如果其中任何一個(gè)失敗,則 etcd 集群無法轉(zhuǎn)換到新狀態(tài),因?yàn)椴淮嬖诙鄶?shù),并且在 3 個(gè)實(shí)例的情況下,一個(gè)實(shí)例可能會(huì)失敗并且可以達(dá)到多數(shù)的實(shí)例仍然可用。
API Server
API Server 是 Kubernetes 中唯一與 etcd 直接交互的組件。Kubernetes 以及客戶端(kubectl)中的所有其他組件都必須通過 API Server 來處理集群狀態(tài)。API Server 提供以下功能:
提供在 etcd 中存儲(chǔ)對(duì)象的一致方式。 執(zhí)行這些對(duì)象的驗(yàn)證,以便客戶端無法存儲(chǔ)配置不正確的對(duì)象,如果它們直接寫入 etcd 數(shù)據(jù)存儲(chǔ)區(qū)可能會(huì)發(fā)生這種情況。 提供 RESTful API 來創(chuàng)建、更新、修改或刪除資源。 提供樂觀并發(fā)鎖定,因此在并發(fā)更新的情況下,對(duì)對(duì)象的更改永遠(yuǎn)不會(huì)被其他客戶端覆蓋。 對(duì)客戶端發(fā)送的請(qǐng)求執(zhí)行身份驗(yàn)證和授權(quán)。它使用插件提取客戶端的用戶名、用戶 ID 和用戶所屬的組,并確定經(jīng)過身份驗(yàn)證的用戶是否可以對(duì)請(qǐng)求的資源執(zhí)行請(qǐng)求的操作。 如果請(qǐng)求試圖創(chuàng)建、修改或刪除資源,則執(zhí)行準(zhǔn)入控制[2]。示例:AlwaysPullImages、DefaultStorageClass、ResourceQuota 等。 為客戶端實(shí)現(xiàn)監(jiān)視機(jī)制(類似于 etcd)以監(jiān)視更改。這允許調(diào)度程序和 Controller Manager 等組件以松散耦合的方式與 API Server 交互。
Controller Manager
在 Kubernetes 中,控制器是監(jiān)控集群狀態(tài)的控制循環(huán),然后根據(jù)需要進(jìn)行更改或請(qǐng)求更改。每個(gè)控制器都嘗試將當(dāng)前集群狀態(tài)移動(dòng)到更接近所需狀態(tài)。控制器跟蹤至少一種 Kubernetes 資源類型,并且這些對(duì)象有一個(gè)表示所需狀態(tài)的規(guī)范字段。
控制器示例:
Replication Manager(ReplicationController 資源的控制器) ReplicaSet、DaemonSet 和 Job 控制器 Deployment 控制器 StatefulSet 控制器 node 控制器 service 控制器 endpoints 控制器 namespace 控制器 PersistentVolume 控制器
控制器使用監(jiān)視機(jī)制來獲得更改通知。他們監(jiān)視 API Server 對(duì)資源的更改并針對(duì)每個(gè)更改執(zhí)行操作,無論是創(chuàng)建新對(duì)象還是更新或刪除現(xiàn)有對(duì)象。大多數(shù)時(shí)候,這些操作包括創(chuàng)建其他資源或自己更新被監(jiān)視的資源,但是由于使用監(jiān)視并不能保證控制器不會(huì)錯(cuò)過任何事件,它們還會(huì)定期執(zhí)行重新列出操作以確保沒有錯(cuò)過了任何東西。
Controller Manager 還執(zhí)行生命周期功能,例如命名空間創(chuàng)建和生命周期、事件垃圾回收、終止 pod 垃圾回收、級(jí)聯(lián)刪除垃圾回收[3]、節(jié)點(diǎn)垃圾回收等。
Scheduler
調(diào)度程序是一個(gè)控制平面進(jìn)程,它將 pod 分配給節(jié)點(diǎn)。它監(jiān)視沒有分配節(jié)點(diǎn)的新創(chuàng)建的 pod,并且對(duì)于調(diào)度程序發(fā)現(xiàn)的每個(gè) pod,調(diào)度程序負(fù)責(zé)為該 pod 找到運(yùn)行的最佳節(jié)點(diǎn)。
滿足 Pod 調(diào)度要求的節(jié)點(diǎn)稱為可行節(jié)點(diǎn)。如果沒有合適的節(jié)點(diǎn),則 pod 將保持未調(diào)度狀態(tài),直到調(diào)度程序能夠放置它。一旦找到可行節(jié)點(diǎn),它就會(huì)運(yùn)行一組函數(shù)來對(duì)節(jié)點(diǎn)進(jìn)行評(píng)分,并選擇得分最高的節(jié)點(diǎn)。然后它會(huì)通知 API Server 有關(guān)所選節(jié)點(diǎn)的信息,此過程稱為綁定。
節(jié)點(diǎn)的選擇分為兩步:
過濾所有節(jié)點(diǎn)的列表以獲取 pod 可以調(diào)度到的可接受節(jié)點(diǎn)列表。(例如,PodFitsResources 過濾器檢查候選節(jié)點(diǎn)是否有足夠的可用資源來滿足 Pod 的特定資源請(qǐng)求) 對(duì)從第 1 步獲得的節(jié)點(diǎn)列表進(jìn)行評(píng)分并對(duì)它們進(jìn)行排名以選擇最佳節(jié)點(diǎn)。如果多個(gè)節(jié)點(diǎn)得分最高,則使用循環(huán)法確保 pod 均勻地部署在所有節(jié)點(diǎn)上。
調(diào)度決策需要考慮的因素包括:
Pod 對(duì)硬件/軟件資源的請(qǐng)求?節(jié)點(diǎn)是否報(bào)告內(nèi)存或磁盤壓力情況? 該節(jié)點(diǎn)是否具有與 pod 規(guī)范中的節(jié)點(diǎn)選擇器匹配的標(biāo)簽? 如果 pod 請(qǐng)求綁定到特定的主機(jī)端口,該端口是否已在該節(jié)點(diǎn)上占用? pod 是否容忍節(jié)點(diǎn)的污點(diǎn)? pod 是否指定節(jié)點(diǎn)親和性或反親和性規(guī)則?等。
調(diào)度程序不會(huì)指示所選節(jié)點(diǎn)運(yùn)行 pod。Scheduler 所做的只是通過 API Server 更新 pod 定義。API server 通過 watch 機(jī)制通知 Kubelet pod 已經(jīng)被調(diào)度。然后目標(biāo)節(jié)點(diǎn)上的 kubelet 服務(wù)看到 pod 已被調(diào)度到它的節(jié)點(diǎn),它創(chuàng)建并運(yùn)行 pod 的容器。
工作節(jié)點(diǎn)組件
Kubelet
Kubelet 是在集群中的每個(gè)節(jié)點(diǎn)上運(yùn)行的代理,是負(fù)責(zé)在工作節(jié)點(diǎn)上運(yùn)行的所有內(nèi)容的組件。它確保容器在 Pod 中運(yùn)行。
kubelet 服務(wù)的主要功能有:
通過在 API Server 中創(chuàng)建節(jié)點(diǎn)資源來注冊(cè)它正在運(yùn)行的節(jié)點(diǎn)。 持續(xù)監(jiān)控 API Server 上已調(diào)度到節(jié)點(diǎn)的 Pod。 使用配置的容器運(yùn)行時(shí)啟動(dòng) pod 的容器。 持續(xù)監(jiān)控正在運(yùn)行的容器并將其狀態(tài)、事件和資源消耗報(bào)告給 API Server。 運(yùn)行容器活性探測(cè),在探測(cè)失敗時(shí)重新啟動(dòng)容器,在容器的 Pod 從 API Server 中刪除時(shí)終止容器,并通知服務(wù)器 Pod 已終止。
kube-proxy
它在每個(gè)節(jié)點(diǎn)上運(yùn)行,并確保一個(gè) pod 可以與另一個(gè) pod 對(duì)話,一個(gè)節(jié)點(diǎn)可以與另一個(gè)節(jié)點(diǎn)對(duì)話,一個(gè)容器可以與另一個(gè)容器通信等。它負(fù)責(zé)監(jiān)視 API Server 以了解Service和 pod 定義的更改,以保持整個(gè)網(wǎng)絡(luò)配置的最新狀態(tài)。當(dāng)一個(gè)Service由多個(gè) pod 時(shí),proxy會(huì)在這些 pod 之間負(fù)載平衡。
kube-proxy 之所以得名,是因?yàn)樗且粋€(gè)實(shí)際的代理服務(wù)器,用于接受連接并將它們代理到 Pod,當(dāng)前的實(shí)現(xiàn)使用 iptables 或 ipvs 規(guī)則將數(shù)據(jù)包重定向到隨機(jī)選擇的后端 Pod,而不通過實(shí)際的代理服務(wù)器傳遞它們。
創(chuàng)建服務(wù)時(shí),會(huì)立即分配一個(gè)虛擬 IP 地址。 API Server 通知在工作節(jié)點(diǎn)上運(yùn)行的 kube-proxy 代理已經(jīng)創(chuàng)建了新服務(wù)。 每個(gè) kube-proxy 通過設(shè)置 iptables 規(guī)則使服務(wù)可尋址,確保攔截每個(gè)服務(wù) IP/端口對(duì),并將目標(biāo)地址修改為支持服務(wù)的 pod 之一。 監(jiān)視 API Server 對(duì)服務(wù)或其端點(diǎn)對(duì)象的更改。
容器運(yùn)行時(shí)
專注于運(yùn)行容器、設(shè)置命名空間和容器的 cgroup 的容器運(yùn)行時(shí)稱為低級(jí)容器運(yùn)行時(shí),專注于格式、解包、管理和共享images并提供 API 以滿足開發(fā)人員需求的容器運(yùn)行時(shí)稱為高級(jí)容器運(yùn)行時(shí)(容器引擎)。
容器運(yùn)行時(shí)負(fù)責(zé):
如果本地不可用,則從鏡像注冊(cè)表中拉取容器所需的容器鏡像。 將鏡像提取到寫入時(shí)復(fù)制文件系統(tǒng),所有容器層相互重疊以創(chuàng)建合并文件系統(tǒng)。 準(zhǔn)備容器掛載點(diǎn) 從容器鏡像設(shè)置元數(shù)據(jù),例如覆蓋 CMD、來自用戶輸入的 ENTRYPOINT、設(shè)置 SECCOMP 規(guī)則等,以確保容器按預(yù)期運(yùn)行。 更改內(nèi)核以向該容器分配某種隔離,例如進(jìn)程、網(wǎng)絡(luò)和文件系統(tǒng)。 提醒內(nèi)核分配一些資源限制,如 CPU 或內(nèi)存限制。 將系統(tǒng)調(diào)用(syscall)傳遞給內(nèi)核以啟動(dòng)容器。 確保 SElinux/AppArmor 設(shè)置正確。
參考資料
RAFT 共識(shí)算法:?https://www.geeksforgeeks.org/raft-consensus-algorithm/
[2]準(zhǔn)入控制:?https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/
[3]級(jí)聯(lián)刪除垃圾回收:?https://kubernetes.io/docs/concepts/architecture/garbage-collection/
?推薦閱讀? 零基礎(chǔ)考完K8S高級(jí)證書,成功轉(zhuǎn)崗K8s運(yùn)維!? 微服務(wù)項(xiàng)目運(yùn)維:優(yōu)雅下線+灰度發(fā)布 Shell分析日志文件,全面解鎖新姿勢(shì)! 大型網(wǎng)站技術(shù)架構(gòu)設(shè)計(jì) 這篇文章帶你全面掌握 Nginx ! Linux 根分區(qū)快滿了,這個(gè)方法快速定位! 一文搞懂 Kubernetes 網(wǎng)絡(luò)通信原理 Shell 編程的經(jīng)典十三問!老司機(jī)也會(huì)翻車 SRE本質(zhì)就是一個(gè)懂運(yùn)維的資深開發(fā) Kubernetes 4000節(jié)點(diǎn)運(yùn)維經(jīng)驗(yàn)分享 從網(wǎng)管到架構(gòu)師,給你分享這10年的成長(zhǎng)感悟 Kubernetes 的高級(jí)部署策略,你不一定知道! 9個(gè)常用的Shell腳本,面試也常問! 基于Nginx實(shí)現(xiàn)灰度發(fā)布與AB測(cè)試 搭建一套完整的企業(yè)級(jí) K8s 集群(kubeadm方式) 點(diǎn)亮,服務(wù)器三年不宕機(jī)


