k8s 核心原理分析
本文內容
- API Server 原理分析
- Controller Manager原理分析
- Scheduler 調度器原理分析
- kubelet 運行機制分析
一. k8s API Server原理分析
1) API Server 作用:
- 集羣內各模塊間數據交互和通信的中心樞紐,是系統的"數據總線"
API Server提供k8s各類資源對象的增刪改查以及Watch等http rest接口
2) API Server 功能特性:
- 集羣管理的API入口
- 資源配額控制的入口
- 提供了完善的集羣安全機制
API server進程運行在master節點上,命令行工具kubectl就是和API Server進行交互
3) k8s集羣各個模塊之間如何通信?
- 集羣內各個功能模塊通過API Server將信息存入etcd,當需要獲取和操作這些數據時,則通過API Server提供的REST接口來實現,從而實現各模塊之間的信息交互
模塊間通信樣例如下
kubelet進程與API Server的交互 :每個Node節點上的kubelet每隔一個時間週期,就會調用一次API Server的REST接口報告自身狀態,API Server接收到這些信息後,將節點狀態信息更新到etcd中
二. Controller Manager 原理分析
1) Controller Manager 作用
- 集羣內部的管理控制中心
- 負責集羣內部Node,Pod副本,服務端點,命名空間,服務賬號,資源定額等的管理
當某個Node意外宕機時,Controller Manager會及時發現此故障並執行自動化修復流程,確保集羣始終處於預期的工作狀態
2) Controller Manager 結構
所屬控制器 | 描述 |
---|---|
Replication Controller | 副本控制器 |
Node Controller | 節點控制器 |
ResourceQuota Controller | 資源控制器 |
Namespace Controller | 命名空間控制器 |
ServiceAccount Controller | 准入控制器 |
Token Controller | token控制器 |
Service Controller | 服務控制器 |
Endpoint Controller | 端點控制器 |
各控制器原理分析
1. Replication Controller
RC 簡介
- 副本控制器,簡稱RC
- 作用就是確保集羣中任何一個RC關聯的Pod副本數量在任何時候保持預設值
Pod可以通過修改它的標籤來脫離RC的控制
該方法可以用於將Pod從集羣中遷移,數據修復等調試,對於一個被遷移的Pod副本,RC會創建一個新的Pod副本來替換被遷移的副本
RC 作用
- 重新調度:確保集羣中不多不少,僅有N個Pod實例
- 彈性伸縮:修改spec.replicas屬性,很容易擴大或縮小副本數量
- 滾動更新:逐個替換Pod的方式來輔助進行服務的滾動更新,這樣即便在滾動更新的過程中發生了不可預料的錯誤,Pod集合的更新也都在可控的範圍內
2. Node Controller
簡介
- 節點控制器
- 通過 API Server 實時獲取Node的相關信息,實現管理和監控集羣中的各個Node節點的相關控制功能
kubelet 進程在啓動時通過API Server註冊自身的節點信息,並且定時向API Server彙報狀態信息,API Server接受到這些信息後,將這些信息存儲到etcd中
節點的健康狀態包括:就緒,未就緒,未知
3. ResourceQuota Controller
簡介
- 資源配額管理器
- 確保指定的資源對象在任何時候都不會超量佔用系統資源,避免某些業務進程的設計或實現的缺陷導致整個系統的運行紊亂甚至意外宕機
支持以下三個層次的資源配額管理
- 容器級別:對cup和內存進行限制
- Pod級別:對一個Pod內所有容器的可用資源進行限制
- namespace級別:對pod數量,RC數量,service數量,resourceQuota數量,secret數量,可持有的pv數量進行限制
k8s的配額管理是通過AdmissionController准入控制來實現的,准入控制提供了兩種方式進行配額約束
- LimitRanger: 作用於pod和container
- ResourceQuota: 作用於namespace
如果pod定義時聲明瞭LimitRanger,那麼用戶通過AIPservice請求修改/創建資源時,准入控制會計算當前配額的使用情況,如果不符合配額約束,則修改/創建資源失敗
4.Namespace Controller
簡介
- 用戶通過APIServer可以創建新的namespace並保存在etcd中,Namespace Controller定時通過APIserver讀取這些Namespace信息
- 如果NameSpace被API標識爲優雅刪除,則將該Namespace的狀態設置成Terminating並保存到etcd中,同時Namespace Controller刪除該Namespace下的ServiceAccount,RC,Pod,Sercret,persistentVoluem,ListRange,ResourceQuota和Event等資源對象
5.Endpoint Controller
簡介
- Endpoints表示一個Service對應的所有Pod副本的訪問地址,kube-proxy進程獲取每個Service的Endpoints,從而實現了Service的負載均衡功能
- Endpoints Controller是負責生成和維護所有Endpoints對象的控制器
作用
- 負責監聽Service和對應的Pod副本的變化
- 如果檢測到Service被刪除,則刪除和該Service同名的Endpoints對象
- 如果檢測到新的Service被創建或修改,則根據該Service信息獲得相關的Pod列表,然後創建或更新Service對應的Endpoints對象
6.Service Controller
簡介
- Service Controller其實是k8s集羣和外部雲平臺之間的一個接口控制器
- Service Controller監聽Service的變化
- 如果是一個LoadBalancer類型的Service,則Service Controller確保外部的雲平臺上該Service對應的LoadBalancer實例被相應的創建,刪除以及更新路由轉發表
三. Scheduler 原理分析
簡介
- 負責Pod調度
- 將待調度的Pod按照特定的調度算法和調度策略綁定到集羣中的某個合適的Node上,並將綁定信息寫入etcd
調度流程
- 1.預選調度過程 : 即遍歷所有的目標Node,通過預選策略,篩選出符合要求的候選Node
- 2.確定最優節點 : 在第一步基礎上,通過優選策略,計算出每個候選節點的積分,積分最高者勝出
預選策略
- NoDiskConflict : 判斷是否存在磁盤衝突
- PodFitsResources : 判斷Node剩餘資源是否滿足要求
- PodSelectorMatches : 判斷Node是否包含待調度Pod的指定標籤
- PodFitsHost : 判斷待調度Pod指定的節點名稱是否和Node名稱一致
- CheckNodeLabelPresence : 判斷列出的標籤在備選Node中存在時,是否選擇該Node
- CheckServiceAffinity : 判斷備選Node是否包含指定標籤,或包含和待調度Pod在相同Service和Namespace下Pod所在節點的標籤列表
- PodFitsPorts : 判斷待調度Pod所需的端口是否在在Node中被佔用
優選策略
- LeastRequestedPriority : 用於選出資源消耗最小的節點
- CalculateNodeLabelPriority : 用於判斷列出的標籤在備選節點存在時,是否選擇該備選節點
- BalanceResourceAllocation :用於選出各項資源使用率最均衡的節點
四. kubelet 運行機制分析
簡介
- 在k8s集羣中,每個Node節點上都會啓動一個kubelet服務進程,該進程用於處理Master節點下發到本節點的任務,管理Pod以及Pod中的容器
- 每個kubelet進程會在API Server上註冊節點自身信息,定期想Master節點彙報節點資源的使用情況,並通過cAdvisor監控容器和節點資源
作用
- 節點管理
- Pod管理
- 容器健康檢查
- 資源監控
節點管理
- 節點通過kubelet的啓動參數來決定是否向API Server註冊自己
- 當前每個kubelet被授予創建和修改任何節點的權限,但是在實踐中,它僅僅創建和修改自己
- 當集羣資源不足時,用戶很容易通過kubelet的自注冊模式來實現擴容
kubelet在啓動時通過API Server註冊節點信息,並定時向API Server發送節點的新消息,API Server在接受到這些信息後,將其寫入etcd,通過kubelet的啓動參數可設置每隔多長時間向API Server報告節點自身狀態,默認爲10s
Pod管理
1.kubelet如何獲取自身Node所要運行的Pod清單?
- 文件 : 通過獲取指定路徑下的配置文件,並定期檢查該文件,指定路徑通過啓動參數配置
- HTTP :通過獲取指定URL下的數據,並定期輪詢該URL,指定URL通過啓動參數配置
- API Server : 通過API Server監聽etcd目錄,同步Pod列表
本章只討論通過API Server獲取Pod清單的方式
2.kubelet是如何創建和修改Pod任務的?流程大致是怎樣?
- 1)爲該Pod創建一個數據目錄
- 2)從API Server讀取Pod清單
- 3)爲該Pod掛載外部卷
- 4)下載Pod用到的secret
- 5)檢查已經運行在節點的Pod,如果該Pod中沒有容器或Pause容器沒有啓動,則先停止Pod裏所有容器的進程,如果有Pod中需要刪除的容器,則刪除這些容器
- 6)用k8s的pause鏡像爲每個Pod創建一個Pause容器,該Pause容器用於接管Pod中其他容器的網絡
- 7)對Pod中的每個容器做以下處理
- 爲容器計算一個hash值,然後用容器的名字去查詢對應Docker容器的hash值,若查找到容器並且二者hash值不一樣,則停止容器中的進程,並停止與之關聯的pause
容器進程,若兩個hash值相同,則不做任何處理 - 如果容器被終止了,且容器沒有指定任何重啓策略,則不做任何處理
- 調用docker client下載容器鏡像,調用docker client運行容器
- 爲容器計算一個hash值,然後用容器的名字去查詢對應Docker容器的hash值,若查找到容器並且二者hash值不一樣,則停止容器中的進程,並停止與之關聯的pause
容器健康檢查
1.kubelet如何檢查容器的檢查狀態?
- 存活探針:判斷容器是否健康
如果存活探針探測到容器不健康,那麼kubelet將刪除容器,並根據容器的重啓策略做相應處理
- 就緒探針:判斷容器是否啓動完成
如果就緒探針探測到容器沒就緒,則該Pod的狀態將被修改,Endpoint Controller將從Service的Endpoint中刪除包含該容器所在的Pod的IP地址的Endpoint條目
2.kubelet如何實現存活探針和就緒探針的?
- 命令:在容器內部執行一個命令,如果該命令的退出狀態碼爲0,則表示容器健康
- TCP: 通過容器的IP地址和端口號執行TCP檢查,如果端口可以被訪問,則表示容器健康
- HTTP: 通過容器的IP地址和端口號以及路徑調用http get方法,如果響應大於等於200且小於等於400,則表示容器健康
資源監控
1.是如何實現資源監控的?
- Heapster爲k8s提供了一個基本的監控平臺,它是集羣級別的監控和事件數據集成器
- Heapster的Pod通過kubelet發現所有運行在集羣中的節點,並查看來自這些節點的資源使用狀況信息
- kubelet通過cAdvisor獲取其所在節點以及容器的數據,Heapster通過帶着關聯標籤的Pod分組這些信息,這些數據被推送到一個可配置的後端,用於存儲和可視化展示
2.kubelet使用到的cAdvisor是什麼?
- cAdivsor是一個開源的分析容器資源使用率和性能特性的代理工具,它被集成到k8s中,cAdvisor通過它所在Node的Root容器,採集並分析該Node的全面使用狀況
kubelet作爲連接master和各Node之間的橋樑,管理運行在Node上的Pod和容器,kubelet將每個Pod轉換成它的成員容器,同時從cAdvisor獲取單獨的容器使用統計信息,然後通過該REST API暴露這些聚合後的Pod資源使用統計信息