Kubernetes之Pod生命週期詳解

簡述

Kubernetes 是一種用於在一組主機上運行和協同容器化應用程序的系統,提供應用部署、規劃、更新維護的機制。應用運行在 kubernetes 集羣之上,實現服務的擴容、縮容,執行滾動更新以及在不同版本的應用程序之間調度流量以測試功能或回滾有問題的部署。Kubernetes 實現管理服務的各項功能是通過定義各種類型的資源來實現的,如 deployment、pod、service、volume 等。下面通過該文章來簡述 pod 的基礎信息並詳述 pod 的生命週期。

 

Pod簡介

Pod 是 kubernetes 系統的基礎單元,是由用戶創建或部署的最小組件,也是 kubernetes 系統上運行容器化應用的資源對象。Kubernetes 集羣中其他資源對象都是爲 pod 這個資源對象做支撐來實現 kubernetes 管理應用服務的目的。

Kubernetes 集羣組件主要包括主節點組件API Server、Controller Manager、Scheduler 以及子節點組件 kubelet、container Runtime(如docker)、kube-proxy 等。從與集羣各組件交互角度講述 pod 的創建、運行、銷燬等生命週期,Pod 生命週期中的幾種不同狀態包括pending、running、succeeded、failed、Unknown。

 

與API Server交互

API Server 提供了集羣與外部交互的接口,通過 kubectl 命令或者其他 API 客戶端提交 pod spec 給 API Server 作爲pod創建的起始。

 

Pod 與 API Server 交互的主要流程如下:

  1. API Server 在接收到創建pod的請求之後,會根據用戶提交的參數值來創建一個運行時的pod對象。

  2. 根據 API Server 請求的上下文的元數據來驗證兩者的 namespace 是否匹配,如果不匹配則創建失敗。

  3. Namespace 匹配成功之後,會向 pod 對象注入一些系統數據,如果 pod 未提供 pod 的名字,則 API Server 會將 pod 的 uid 作爲 pod 的名字。

  4. API Server 接下來會檢查 pod 對象的必需字段是否爲空,如果爲空,創建失敗。

  5. 上述準備工作完成之後會將在 etcd 中持久化這個對象,將異步調用返回結果封裝成 restful.response,完成結果反饋。

  6. 至此,API Server 創建過程完成,剩下的由 scheduler 和 kubelet 來完成,此時 pod 處於 pending 狀態。

 

與scheduler交互

當提交創建 pod 的請求與 API Server 的交互完成之後,接下來由 scheduler 進行工作,該組件主要是完成 pod 的調度來決定 pod 具體運行在集羣的哪個節點上。注意,此處聲明一點,API Server 完成任務之後,將信息寫入到 etcd 中,此時 scheduler 通過 watch 機制監聽到寫入到 etcd 的信息然後再進行工作。

 

Scheduler 讀取到寫入到 etcd 中的 pod 信息,然後基於一系列規則從集羣中挑選一個合適的節點來運行它,調度時主要通過三步來確定 pod 運行節點:

  1. 節點預選:基於一系列預選規則(如 PodFitsResource 和 MatchNode-Selector 等)對每個節點進行檢查,將不符合的節點過濾掉從而完成節點預選。

  2. 節點優選:對預選出的節點進行優先級排序,以便選出最適合運行 pod 對象的節點。

  3. 從優先級結果中挑選出優先級最高的節點來運行 pod 對象,當此類節點多個時則隨機選擇一個。

注:如果有特殊 pod 資源需要運行在特殊節點上,此時可以通過組合節點標籤以及 pod 標籤和標籤選擇器等來實現高級調度,如 MatchInterPodAffinity、MatchNodeSelector 和 PodToleratesNodeTaints 等預選策略,他們爲用戶提供自定義 Pod 親和性或反親和性、節點親和性以及基於污點及容忍度的調度機制。

 

預選策略

預選策略就是節點過濾器,例如 MathNodeSelector 實現的規則,以及 PodFitsResources 實現的規則等。執行預選操作時,如果不存在適合的節點,此時 pod 會一直處於 pending 狀態,直到至少有一個可用節點。

 

支持的預選策略列舉一下(1.10版本):

CheckNodeCondition

General

NoDiskConflict

PodToleratesNodeTaintsPodToleratesNodeNoExecuteTaints

CheckServiceAffinity

MaxEBsVolumeCount

MaxGCEPDVolumeCount

MaxAzureDiskVolumeCount

CheckVolumeBinding

NoVolumeZoneConflict

CheckNodeMemoryPressure

CheckNodePIDPressure

CheckNodeDiskPressure

MatchInterPodAffinity

 

簡單介紹幾種:

  • CheckNodeCondition:檢查是否可以在節點報告磁盤、網絡不可用或未準備好的情況下將 pod 對象調度其上。

  • NoDiskConflict:檢查 pod 對象請求的存儲卷在此節點上是否可用,若不存在衝突則通過檢查。

  • MathNodeSelector:若 pod 對象定義了 spec.NodeSelector 屬性,則檢查節點標籤是否能匹配此屬性值。

     

優選函數

常用優選函數:

BalancedResourceAllocation 

LeaastRequstedPriority 

NodePreferAvoidPodsPriority 

NodeAffinityPriority 

TaintTolerationPriority 

InterPodAffinityPriority 

SelectorSpreadPriority 

NodeLabelPriority 

MostRequestedPriority 

ImageLoccalityPriority

 

此外調度器支持爲每個優選函數指定一個簡單的整數值表示權重,進行節點優先級分值的計算,計算公式如下:

FinalScoreNode = (weight1 * priorityFunc1) + (weight2 * priorityFunc2)+ ....

 

列舉說明幾個優選函數:

  • TaintToleraionPriority:基於Pod資源對節點的污點容忍調度偏好進行其優先級的評估,它將 Pod 對象的 tolerations 列表與節點的污點進行匹配度檢查,成功匹配的條目越多,則節點得分越低。

  • NodeAffinityPriority:基於節點親和性調度偏好進行優先級評估,它將根據 Pod 資源中的 nodeSelector 對給定節點進行匹配度計算,成功匹配到的條目越多則節點得分越高。

 

對於上述節點調度中還包括一些節點親和度:硬親和度和軟親和性、資源親和調度。硬親和調度和軟親和調度以及反親和調度、污點容忍度等,都是 pod 調度的策略,不一一詳述。

當 scheduler 通過一系列策略選定 pod 運行節點之後將結果信息更新至 API Server,由 API Server 更新至 etcd 中,並由 API Server 反映調度結果,接下來由 kubelet 在所選定的節點上啓動 pod。

 

 

Kubelet組件啓動pod

kubelet 組件的作用不單單是創建 pod,另外還包括節點管理、cAdvisor 資源監控管理、容器健康檢查等功能。

 

啓動pod流程分析

kubelet 通過 API Server 監聽 etcd 目錄,同步 pod 列表。如果發現有新的 pod 綁定到本節點,則按照 pod 清單要求創建 pod,如果是發現 pod 被更新,則做出相應更改。

 

讀取到 pod 的信息之後,如果是創建和修改 pod 的任務,則做如下處理:

  1. 爲該 pod 創建一個數據目錄 

  2. 從 API Server 讀取該 pod 清單 

  3. 爲該 pod 掛載外部卷 

  4. 下載 pod 所需的 Secret 

  5. 檢查已經運行在節點中 pod,如果該 pod 沒有容器或者 Pause 容器沒有啓動,則先停止pod裏所有的容器進程。

  6. 使用 pause 鏡像爲每個pod創建一個容器,該容器用於接管 Pod 中所有其他容器的網絡。

  7. 爲 pod 中的每個容器做如下處理:1.爲容器計算一個 hash 值,然後用容器的名字去查詢對於 docker 容器的 hash 值。若查找到容器,且兩者的 hash 值不同,則停止 docker 中容器中進程,並停止與之關聯的 pause 容器,若相同,則不做處理。若容器被終止了,且容器沒有指定的重啓策略,則不做任何處理調用 docker client  下載容器鏡像,並啓動容器。

 

詳述pod聲明週期中的重要行爲

除了創建應用容器(主容器及輔助容器之外,注意,如果集羣中部署了 istio,則會在 pod 啓動的時候注入一個新的和 istio 相關的容器,那是另一個美好故事的開端),還可以爲 pod 對象定義其聲明週期中的多種行爲,如初始化容器、容器探測以及就緒性探測等。

 

容器生命週期的幾種行爲

初始化容器

初始化容器即 pod 內主容器啓動之前要運行的容器,主要是做一些前置工作,初始化容器具有以下特徵:

  1. 初始化容器必須首先執行,若初始化容器運行失敗,集羣會一直重啓初始化容器直至完成,注意,如果 pod 的重啓策略爲 Never,那初始化容器啓動失敗後就不會重啓。

  2. 初始化容器必須按照定義的順序執行,初始化容器可以通過 pod 的 spec.initContainers 進行定義。

 

聲明週期鉤子函數

Kubernetes 爲容器提供了兩種生命週期鉤子:

  • Poststart:於容器創建完成之後立即運行的鉤子程序。

  • preStop:容器終止之前立即運行的程序,是以同步方式的進行,因此其完成之前會阻塞 刪除容器的調用

 

備註:鉤子程序的執行方式有“Exec”和“HTTP”兩種。

 

容器探測

容器探測分爲存活性探測和就緒性探測容器探測是kubelet對容器健康狀態進行診斷,容器探測的方式主要以下三種:

  • ExecAction:在容器中執行命令,根據返回的狀態碼判斷容器健康狀態,返回0即表示成功,否則爲失敗。

  • TCPSocketAction: 通過與容器的某TCP端口嘗試建立連接進行診斷,端口能打開即爲表示成功,否則失敗。

  • HTTPGetAction:向容器指定 URL 發起 HTTP GET 請求,響應碼爲2xx或者是3xx爲成功,否則失敗。

 

Pod終止過程

終止過程主要分爲如下幾個步驟:

  1. 用戶發出刪除 pod 命令 

  2. Pod 對象隨着時間的推移更新,在寬限期(默認情況下30秒),pod 被視爲“dead”狀態 

  3. 將 pod 標記爲“Terminating”狀態 

  4. 第三步同時運行,監控到 pod 對象爲“Terminating”狀態的同時啓動 pod 關閉過程 

  5. 第三步同時進行,endpoints 控制器監控到 pod 對象關閉,將pod與service匹配的 endpoints 列表中刪除 

  6. 如果 pod 中定義了 preStop 鉤子處理程序,則 pod 被標記爲“Terminating”狀態時以同步的方式啓動執行;若寬限期結束後,preStop 仍未執行結束,第二步會重新執行並額外獲得一個2秒的小寬限期

  7. Pod 內對象的容器收到 TERM 信號

  8. 寬限期結束之後,若存在任何一個運行的進程,pod 會收到 SIGKILL 信號 

  9. Kubelet 請求 API Server 將此 Pod 資源寬限期設置爲0從而完成刪除操作

 

此外 kubelet 除了啓動之外,kubelet 中還有 cAdvisor,用於收集容器 CPU、內存、文件系統和網絡使用情況等信息,與 prometheus 結合實現對集羣內 pod 監控。

此外,除了上述三個組件在創建 pod 過程中的交互,還有 controller-manager 來保證 pod 處於用戶期望狀態(即保證 pod 永遠處於存活狀態)等功能以及 proxy 用於集羣內 pod 之間通信等。

 

本文由博雲研究院原創發表,轉載請註明出處。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章