Kubernetes 架構指南

你可以使用 Kubernetes 編排容器。這聽上去很簡單,但理解這實際上意味着什麼,以及如何完成完全是另一回事。如果你正在運行或管理 Kubernetes 集羣,那麼你知道 Kubernetes 由一臺指定爲控制平面的計算機和許多其他指定爲工作節點的計算機組成。每一個都有一個複雜但強大的堆棧,使編排成爲可能,熟悉每個組件有助於理解它們是如何工作的。

控制平面組件

你把 Kubernetes 安裝在一個叫作控制平面的機器上。它運行 Kubernetes 守護程序,在啓動容器和 pod 時與之通信。以下介紹控制平面組件。

etcd

etcd 是一種快速、分佈式、一致的鍵值存儲,用作持久存儲 Kubernetes 對象數據(如 pod、複製控制器、祕密和服務)的後備存儲。etcd 是 Kubernetes 存儲集羣狀態和元數據的唯一地方。與 etcd 直接對話的唯一組件是 Kubernetes API 服務器。所有其他組件通過 API 服務器間接向 etcd 讀寫數據。

etcd 還實現了一個監視功能,它提供了一個基於事件的接口,用於異步監視密鑰的更改。一旦你更改了一個密鑰,監視器就會得到通知。API 服務器組件嚴重依賴於此來獲得通知,並將 etcd 的當前狀態遷移到所需狀態。

爲什麼 etcd 實例的數量應該是奇數?

在高可用性(HA)環境中,通常會有三個、五個或七個 etcd 實例運行,但爲什麼呢?因爲 etcd 是一個分佈式數據存儲。可以橫向擴展,但也需要確保每個實例中的數據是一致的,爲此,系統需要就狀態達成共識。etcd 爲此使用 RAFT 共識算法。

該算法需要多數(或仲裁)才能使集羣進入下一個狀態。如果只有兩個 ectd 實例,且其中任何一個都失敗,etcd 集羣將無法轉換到新狀態,因爲不存在多數。如果有三個 ectd 實例,一個實例可能會失敗,但仍有大多數實例可用於達到仲裁。

API 服務器

API 服務器是 Kubernetes 中唯一直接與 etcd 交互的組件。Kubernetes 中的所有其他組件必須通過 API 服務器才能與集羣狀態一起工作,包括客戶端(kubectl)。API 服務器具有以下功能:

——提供在 etcd 中存儲對象的一致方式。

——對這些對象執行驗證,這樣客戶端就不會存儲配置不當的對象(如果直接寫入 etcd 數據存儲,可能會發生這種情況)。

——提供 RESTful API 來創建、更新、修改或刪除資源。

——提供樂觀併發鎖定,因此在併發更新的情況下,其他客戶端永遠不會覆蓋對對象的更改。

——對客戶端發送的請求執行身份驗證和授權。它使用插件提取客戶端的用戶名、用戶 ID、用戶所屬的組,並確定經過身份驗證的用戶是否可以對請求的資源執行請求的操作。

——如果請求試圖創建、修改或刪除資源,則負責許可控制。例如,AlwaysPubllimages、DefaultStorageClass 和 ResourceQuota。

——實現一種監視機制(類似於 etcd),以便客戶端監視更改。這允許調度器和控制器管理器等組件以松耦合的方式與 API 服務器交互。

控制器管理器

在 Kubernetes 中,控制器是監視集羣狀態的控制循環,然後在需要時進行更改或請求更改。每個控制器都會嘗試將當前集羣狀態移近所需狀態。控制器跟蹤至少一種 Kubernetes 資源類型,這些對象有一個表示所需狀態的 spec 字段。

控制器示例:

——Replication Manager(用於 ReplicationController 資源的控制器)

——複製集、守護程序集和作業控制器

——部署控制器

——狀態集控制器

——節點控制器

——服務控制器

——端點控制器

——命名空間控制器

——持久卷控制器

控制器使用監視機制獲得更改通知。它們監視 API 服務器對資源的更改,並對每次更改執行操作,無論是創建新對象還是更新或刪除現有對象。大多數情況下,這些操作包括創建其他資源或更新監視的資源本身。儘管如此,因爲使用監視並不能保證控制器不會錯過一個事件,它們也會定期執行重新列出操作,以確保沒有錯過任何事情。

Controller Manager 還執行生命週期功能,如命名空間創建和生命週期、事件垃圾收集、終止的 pod 垃圾收集、級聯刪除垃圾收集和節點垃圾收集。

調度器

調度器是一個控制平面進程,將 pod 分配給節點。它監視新創建的沒有分配節點的 pod。對於調度器發現的每一個 pod,調度器將負責找到該 pod 運行的最佳節點。

滿足 pod 調度要求的節點稱爲可行節點。如果沒有合適的節點,pod 將保持未調度狀態,直到調度器可以放置它。一旦找到一個可行的節點,它就會運行一組函數對節點進行評分,並選擇得分最高的節點。然後,它將所選節點通知 API 服務器。這個過程稱爲綁定。

節點的選擇分爲兩步:

——篩選所有節點的列表,以獲得可接受節點的列表,你可以將 pod 安排到這些節點(例如,PodFitsResources 篩選器檢查候選節點是否有足夠的可用資源來滿足 pod 的特定資源請求)。

——對從第一步獲得的節點列表進行評分,並對它們進行排序,以選擇最佳節點。如果多個節點得分最高,循環過程可以確保 pod 在所有節點上均勻部署。

調度決策考慮的因素包括:

——pod 是否請求硬件 / 軟件資源?節點是否報告內存或磁盤壓力狀況?

——節點是否具有與 pod 規範中的節點選擇器匹配的標籤?

——如果 pod 請求綁定到特定的主機端口,該端口可用嗎?

——pod 能容忍節點的污染嗎?

——pod 是否指定節點關聯規則或反關聯規則?

調度器不會指示所選節點運行 pod。調度器只需通過 API 服務器更新 pod 定義。API 服務器通知 kubelet pod 已通過監視機制調度。然後目標節點上的 kubelet 服務看到 pod 被調度到其節點,它創建並運行 pod 的容器。

工作節點組件

Worker 節點運行 kubelet 代理,這允許它們被控制平面用來處理作業。與控制平面類似,工作節點使用幾個不同的組件來實現這一點。以下介紹工作節點組件。

kubelet

kubelet 是在集羣中的每個節點上運行的代理,負責在工作節點上運行的所有內容。它確保容器在 pod 中運行。

kubelet 服務的主要功能是:

——通過在 API 服務器中創建節點資源來註冊它正在運行的節點。

——持續監控 API 服務器,以查看已調度到節點的 pod。

——使用配置好的容器運行時啓動 pod 的容器。

——持續監控正在運行的容器,並向 API 服務器報告它們的狀態、事件和資源消耗。

——運行容器活性探測,當探針失敗時重新啓動容器,當容器的 pod 從 API 服務器上刪除時終止容器(通知服務器 pod 終止)。

服務代理

服務代理(kube-proxy)在每個節點上運行,確保一個 pod 可以與另一個 pod 對話,一個節點可以與另一個節點對話,以及一個容器可以與另一個容器對話。它負責監視 API 服務器上服務和 pod 定義的更改,以保持整個網絡配置是最新的。當一個服務得到多個 pod 的支持時,代理在這些 pod 之間執行負載均衡。

kube-proxy 之所以得名,是因爲它最初是一個實際的代理服務器,用於接受連接並將其代理到 pod。當前的實現使用 iptables 規則將數據包重定向到隨機選擇的後端 pod,而不通過實際的代理服務器。

關於其工作原理的高級視圖:

——創建服務時,會立即分配虛擬 IP 地址。

——API 服務器通知在工作節點上運行的 kube-proxy 存在新服務。

——每個 kube-proxy 通過設置 iptables 規則使服務可尋址,確保攔截每個服務 IP / 端口對,並將目標地址修改爲支持服務的 pod 之一。

——監視 API 服務器對服務或其端點對象的更改。

容器運行時

有兩類容器運行時:

——較低級別的容器運行時:它們關注於運行容器,併爲容器設置命名空間和 cgroup。

——更高級別的容器運行時(容器引擎):它們關注格式、解包、管理、鏡像共享,併爲開發人員提供 API。

容器運行時負責:

——從鏡像註冊表中提取所需的容器鏡像(如果在本地不可用)。

——將鏡像提取到一個寫時拷貝文件系統上,並覆蓋所有容器層,以創建一個合併的文件系統。

——準備容器掛載點。

——設置容器鏡像中的元數據,如覆蓋 CMD、用戶輸入中的 ENTRYPOINT,並設置 SECCOMP 規則,確保容器按預期運行。

——修改內核,將隔離(如進程、網絡和文件系統)分配給該容器。

——提醒內核分配一些資源限制,如 CPU 或內存限制。

——將系統調用(syscall)傳遞給內核以啓動容器。

——確保 SElinux/AppArmor 設置正確。

一起工作

系統級組件協同工作,以確保 Kubernetes 集羣的每個部分都能實現其目的並執行其功能。有時(當你深入編輯一個 YAML 文件時),理解你的請求在集羣中是如何被傳達的可能會讓你不知所措。現在,有了一張各部分如何組合在一起的視圖,你可以更好地瞭解 Kubernetes 內部發生了什麼,這有助於你診斷問題,維護健康的集羣,並優化工作流程。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/E879_LCsbc06qZ1FS5QXZA