Kubernetes 架構指南
使用 Kubernetes 來編排容器,這種描述說起來簡單,但理解它的實際含義以及如何實現它完全是另外一回事。如果你正在運行或管理 Kubernetes 集群,那麼你就會知道 Kubernetes 由一台稱為 「 控制平面 」 的機器和許多其他 工作節點 機器組成。每種類型都有一個複雜但穩定的堆棧,這使編排成為可能,熟悉每個組件有助於理解它是如何工作的。
![Kubernetes 架構圖](/data/attachment/album/202207/03/105141a8y1z95g1pv8ts51.png "Kubernetes architecture diagram")
(Nived Velayudhan, CC BY-SA 4.0)
控制平面組件
Kubernetes 安裝在一個稱為「 控制平面 」的機器上,它會運行 Kubernetes 守護進程,並在啟動容器和 容器組 時與之通信。下面介紹控制平面的各個組件。
etcd
etcd 是一種快速、分散式一致性鍵值存儲器,用作 Kubernetes 對象數據的持久存儲,如容器組、副本控制器、密鑰和服務。etcd 是 Kubernetes 存儲集群狀態和元數據的唯一地方。唯一與 etcd 直連的組件是 Kubernetes API 伺服器。其他所有組件都通過 API 伺服器間接的從 etcd 讀寫數據。
etcd 還實現了一個監控功能,它提供了一個基於事件的介面,用於非同步監控鍵的更改。一旦你更改了一個鍵,它的監控者就會收到通知。API 伺服器組件嚴重依賴於此來獲得通知,並將 etcd 變更至期望狀態。
為什麼 etcd 實例的數量應該是奇數?
你通常會運行三個、五個或七個 etcd 實例實現高可用(HA)環境,但這是為什麼呢?因為 etcd 是分散式數據存儲,可以水平擴展它,但你需要確保每個實例中的數據是一致的。因此,需要為系統當前狀態達成共識,etcd 為此使用 RAFT 共識演算法。
RAFT 演算法需要經過選舉(或仲裁)集群才能進入下一個狀態。如果你只有兩個 etcd 實例並且他們其中一個失敗的話,那麼 etcd 集群無法轉換到新的狀態,因為不存在過半這個概念。如果你有三個 etcd 實例,一個實例可能會失敗,但仍有 2 個實例可用於進行選舉。
API 伺服器
API 伺服器是 Kubernetes 中唯一直接與 etcd 交互的組件。Kubernetes 中的其他所有組件都必須通過 API 伺服器來處理集群狀態,包括客戶端(kubectl)。API 伺服器具有以下功能:
- 提供在 etcd 中存儲對象的一致方式。
- 執行驗證對象,防止客戶端存儲配置不正確的對象(如果它們直接寫入 etcd 數據存儲,可能會發生這種情況)。
- 提供 RESTful API 來創建、更新、修改或刪除資源。
- 提供 [樂觀並發鎖](https://stackoverflow.com/questions/52910322/kubernetes-resource-versioning#:~:text=Optimistic%20concurrency%20control%20(sometimes%20referred,updated%2C%20the%20version%20number%20increases.),在發生更新時,其他客戶端永遠不會有機會重寫對象。
- 對客戶端發送的請求進行身份驗證和授權。它使用插件提取客戶端的用戶名、ID、所屬組,並確定通過身份驗證的用戶是否可以對請求的資源執行請求的操作。
- 如果請求試圖創建、修改或刪除資源,則負責 許可權控制。例如,AlwaysPullImages、DefaultStorageClass 和 ResourceQuota。
- 實現了一種監控機制(類似於 etcd),用戶客戶端監控更改。這允許調度器和控制器管理器等組件以松耦合的方式與 API 伺服器交互。
控制器管理器
在 Kubernetes 中,控制器持續監控集群狀態,然後根據需要進行或請求更改。每個控制器都嘗試將當前集群狀態變更至期望狀態。控制器至少跟蹤一種 Kubernetes 資源類型,這些對象均有一個欄位來表示期望的狀態。
控制器示例:
- 副本管理器(管理 副本控制器 資源的控制器)
- 副本集 、守護進程集DaemonSet 和任務控制器
- 部署控制器
- 有狀態負載控制器
- 節點控制器
- 服務控制器
- 接入點控制器
- 命名空間控制器
- 持久卷 控制器
控制器通過監控機制來獲得變更通知。它們監視 API 伺服器對資源的變更,對每次更改執行操作,無論是新建對象還是更新或刪除現有對象。大多數時候,這些操作包括創建其他資源或更新監控的資源本身。不過,由於使用監控並不能保證控制器不會錯過任何事件,它們還會定期執行一系列操作,確保沒有錯過任何事件。
控制器管理器還執行生命周期功能。例如命名空間創建和生命周期、事件垃圾收集、已終止容器組垃圾收集、級聯刪除垃圾收集 和節點垃圾收集。有關更多信息,參考 雲控制器管理器。
調度器
調度器是一個將容器組分配給節點的控制平面進程。它會監視新創建沒有分配節點的容器組。調度器會給每個發現的容器組分配運行它的最佳節點。
滿足容器組調度要求的節點稱為可調度節點。如果沒有合適的節點,那麼容器組會一直處於未調度狀態,直到調度器可以安置它。一旦找到可調度節點,它就會運行一組函數來對節點進行評分,並選擇得分最高的節點,然後它會告訴 API 伺服器所選節點的信息。這個過程稱為綁定。
節點的選擇分為兩步:
- 過濾所有節點的列表,獲得可以調度容器組的節點列表(例如,PodFitsResources 過濾器檢查候選節點是否有足夠的可用資源來滿足容器組的特定資源請求)。
- 對第一步得到的節點列表進行評分和排序,選擇最佳節點。如果得分最高的有多個節點,循環過程可確保容器組會均勻地部署在所有節點上。
調度決策要考慮的因素包括:
- 容器組是否請求硬體/軟體資源?節點是否報告內存或磁碟壓力情況?
- 節點是否有與容器組規範中的節點選擇器匹配的標籤?
- 如果容器組請求綁定到特定地主機埠,該埠是否可用?
- 容器組是否容忍節點的污點?
- 容器組是否指定節點親和性或反親和性規則?
調度器不會指示所選節點運行容器組。調度器所做的就是通過 API 伺服器更新容器組定義。然後 API 伺服器通過監控機制通知 kubelet 容器組已被調度,然後目標節點上的 kubelet 服務看到容器組被調度到它的節點,它創建並運行容器組。
工作節點組件
工作節點運行 kubelet 代理,這允許控制平面接納它們來處理負載。與控制平面類似,工作節點使用幾個不同的組件來實現這一點。 以下部分描述了工作節點組件。
Kubelet
Kubelet 是一個運行在集群中每個節點上的代理,負責在工作節點上運行的所有事情。它確保容器在吊艙中運行。
kubelet服務的主要功能有:
- 通過在 API 伺服器中創建節點資源來註冊它正在運行的節點。
- 持續監控 API 伺服器上調度到節點的容器組。
- 使用配置的容器運行時啟動容器組的容器。
- 持續監控正在運行的容器,並將其狀態、事件和資源消耗報告給 API 伺服器。
- 運行容器存活探測,在探測失敗時重啟容器,當 API 伺服器中刪除容器組時終止(通知伺服器容器組終止的消息)。
服務代理
服務代理(kube-proxy)在每個節點上運行,確保一個容器組可以與另一個容器組通訊,一個節點可以與另一個節點對話,一個容器可以與另一個容器對話。它負責監視 API 伺服器對服務和容器組定義的更改,以保持整個網路配置是最新的。當一項服務得到多個容器組的支持時,代理會在這些容器組之間執行負載平衡。
kube-proxy 之所以叫代理,是因為它最初實際上是一個代理伺服器,用於接受連接並將它們代理到容器組。當前的實現是使用 iptables 規則將數據包重定向到隨機選擇的後端容器組,而無需通過實際的代理伺服器。
關於它工作原理的高級視圖:
- 當你創建一個服務時,會立即分配一個虛擬 IP 地址。
- API 伺服器會通知在工作節點上運行的 kube-proxy 代理有一個新服務。
- 每個 kube-proxy 通過設置 iptables 規則使服務可定址,確保截獲每個服務 IP/埠對,並將目的地址修改為支持服務的一個容器組。
- 監控 API 伺服器對服務或其端點對象的更改。
容器運行時
容器運行時有兩類:
- 較低級別的容器運行時: 它們主要關注運行中的容器並為容器設置命名空間和 控制組 。
- 更高級別的容器運行時(容器引擎): 它們專註于格式、解包、管理、共享鏡像以及為開發人員提供 API。
容器運行時負責:
- 如果容器鏡像本地不存在,則從鏡像倉庫中提取。
- 將鏡像解壓到寫時複製文件系統,所有容器層疊加創建一個合併的文件系統。
- 準備一個容器掛載點。
- 設置容器鏡像的元數據,如覆蓋命令、用戶輸入的入口命令,並設置 SECCOMP 規則,確保容器按預期運行。
- 通知內核將進程、網路和文件系統等隔離分配給容器。
- 通知內核分配一些資源限制,如 CPU 或內存限制。
- 將系統調用(syscall)傳遞給內核啟動容器。
- 確保 SElinux/AppArmor 設置正確。
協同
系統級組件協同工作,確保 Kubernetes 集群的每個部分都能實現其目和執行其功能。當你深入編輯 YAML 文件 時,有時很難理解請求是如何在集群中通信的。現在你已經了解了各個部分是如何組合在一起的,你可以更好地理解 Kubernetes 內部發生了什麼,這有助於診斷問題、維護健康的集群並優化你的工作流。
via: https://opensource.com/article/22/2/kubernetes-architecture
作者:Nived Velayudhan 選題:lujun9972 譯者:MjSeven 校對:turbokernel
本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive