1、概述
絕大部分Kubernetes
資源對象都包含status.conditions
字段,用來表示資源狀態,比如deployment
資源中的status.conditions
如下所示:
conditions: - lastTransitionTime: "2021-12-27T01:50:58Z" lastUpdateTime: "2021-12-27T01:50:58Z" message: Deployment has minimum availability. reason: MinimumReplicasAvailable status: "True" type: Available - lastTransitionTime: "2021-12-27T01:50:54Z" lastUpdateTime: "2021-12-27T01:50:58Z" message: ReplicaSet "nginx-v1-68b775fc4b" has successfully progressed. reason: NewReplicaSetAvailable status: "True" type: Progressing
deployment 的 conditions 狀況默認只有兩個,它是由Deployment controller生成,一是達到最小的可用副本數就變為 True,另一個是新的 rs 可用了就變為 True。
以上conditions
的信息是很容易讀懂的,然而有個問題曾經讓我很困惑,那就是:
conditions
和status
到底有什么區別?conditions
的設計原則是什么?在設計API擴展時,該如何定義conditions
?
本節會先從conditions
的設計原則講起,再介紹一些設計conditions
時的一些經驗總結。
2、conditions設計原則
conditions
寄居於資源對象的status
字段中,與status
其他字段值一樣都用來表示資源的狀態。不過conditions
的設計初衷是提供一種通用的數據結構表示資源的狀態,它通常能夠提供比status
其他字段更詳細的信息(比如狀態切換時間、更新時間),conditions
實際上是一種擴展機制,外部監控程序可以根據conditions
無差別地監控各種資源的狀態,而不必過分關注資源對象status
中的其他信息。
通常status.conditions
字段類型為切片,切片中的每個元素表示資源的某個狀態,該狀態由特定的控制器更新,比如Deployment
控制器會更新deployment
對象的status.conditions
信息。conditions
作為擴展機制,它還支持第三方控制器增加新的狀態。通常status.conditions
中的信息由控制器根據資源的status
其他字段計算出來。
3、condition字段內容
通常一個condition
必須包含type
(狀態類型)和status
(狀態值)兩個信息。在Kubernetes
v1.19版之前,關於condition
並沒有統一的標准,導致眾多API都自行定義了condition
。比如:
- Deployment使用的Condition為
type DeploymentCondition struct
; - Pod使用的Condition為
type PodCondition struct
;
慶幸的是,在Kubernetes
v1.19版本社區提供了一個標准的condition
類型定義,由於兼容性考慮,Kubernetes
既有的API不一定能采用這一標准類型,但對於后續新增的API將會使用這一標准類型,並且筆者建議用戶設計的CRD擴展也應使用這一標准類型。
標准的condition
類型定義如下所示:
type ConditionStatus string const ( ConditionTrue ConditionStatus = "True" ConditionFalse ConditionStatus = "False" ConditionUnknown ConditionStatus = "Unknown" ) type Condition struct { // 類型(使用駝峰風格),如”Available“。 Type string // 狀態(枚舉值:”True“、”False“和”Unknown“)。 Status ConditionStatus // 觀察到的generation。 // 如果ObservedGeneration 比metada.generation小,說明不是最新狀態。 // +optional ObservedGeneration int64 // 上次變化時間 LastTransitionTime Time // 狀態變化原因(使用駝峰風格),如”NewReplicaSetAvailable“ Reason string // 描述信息,如”Deployment has minimum availability“ Message string `json:"message" protobuf:"bytes,6,opt,name=message"` }
標准的condition
類型定義對condition
的各個字段做了進一步約定。除了ObservedGeneration
是可選的以外,其他字段都是必填的。
4、condition設計約定
為了讓condition
起到最大的作用,需要遵守一定的設計約定:
約定一:condition定義要有明確的信息
每個condition
需要傳遞一個用戶關心的明確信息,用戶讀取到該信息不需要再根據資源的其他狀態來揣測和計算。
約定二:condition需要保持兼容
condition
一旦被定義,它就成了API中的一部分,需要跟API一樣提供穩定性保證。如果需要新的condition
仍然可以增加(沒有破壞兼容性),但既有的condition
是否能夠改變就需要根據API成熟度來決定,比如stable
的API不可以改變,alpha
的API可以改變。
約定三:condition需要控制器第一次處理資源時更新
控制器需要盡快地更新condition
狀態值(condition.status
),即便該狀態值為Unknown
,這么做的好處是可以讓其他組件了解到控制器正在調諧
這個資源。
然而,並不是所有的控制器都能遵守這個約定,即控制器並不會報告特定的condition
(此時該condition
狀態值可能為Unknown
),可能該condition
還無法確定,需要在下一次調諧
時決定。此種情況下,外部組件無法讀取到特定的condition
,可以假設該condition
為Unknown
。
約定四:condition類型名需要確保可讀性
condition
類型名要使用人類可讀的名稱,而且盡量避免出現雙重否定的語境。例如,類型名Ready
比使用Failed
要好,因為condition
狀態為False
時,Failed = False
將出現雙重否定,不如Ready = False
容易理解。
約定五:condition不要定義成狀態機
condition
需要描述當前資源的確定狀態,而不是當前資源狀態機中的狀態。通俗地講,condition
類型需要使用形容詞(如Ready
)或過去動詞(Succeeded
),而不是使用當前運行時(如Deploying
)。
5、常用資源Conditions解釋(持續更新)
5.1 Pod conditions
Pod 的 conditions 表示了 Pod 的一些條件,是一個數組。pod的 conditions 狀況默認有4個,它是由Pod controller生成,里面包含一些 Pod 必須滿足的條件,只有所有的條件為 True 時,Pod 才可以提供服務。
PodScheduled
:Pod 已經被調度到某節點;ContainersReady
:Pod 中所有容器都已就緒;Initialized
:所有的 Init容器都已成功啟動;Ready
:Pod 可以為請求提供服務,並且應該被添加到對應服務的負載均衡池中。
字段名稱 | 描述 |
---|---|
type |
Pod 狀況的名稱 |
status |
表明該狀況是否適用,可能的取值有 "True ", "False " 或 "Unknown " |
lastProbeTime |
上次探測 Pod 狀況時的時間戳 |
lastTransitionTime |
Pod 上次從一種狀態轉換到另一種狀態時的時間戳 |
reason |
機器可讀的、駝峰編碼(UpperCamelCase)的文字,表述上次狀況變化的原因 |
message |
人類可讀的消息,給出上次狀態轉換的詳細信息 |
使用readinessGates自定義 Pod 狀況信息
Kubernetes v1.14 [stable]
你的應用可以向 PodStatus 中注入額外的反饋或者信號:Pod Readiness(Pod 就緒態)。 要使用這一特性,可以設置 Pod 規約中的 readinessGates
列表,為 kubelet 提供一組額外的狀況供其評估 Pod 就緒態時使用。
就緒態門控基於 Pod 的 status.conditions
字段的當前值來做決定。 如果 Kubernetes 無法在 status.conditions
字段中找到某狀況,則該狀況的狀態值默認為 "False
"。
這里是一個例子(更詳細例子參見:【k8s】Pod-readinessGates):
kind: Pod ... spec: readinessGates: - conditionType: "www.example.com/feature-1" status: conditions: - type: Ready # 內置的 Pod 狀況 status: "False" lastProbeTime: null lastTransitionTime: 2018-01-01T00:00:00Z - type: "www.example.com/feature-1" # 額外的 Pod 狀況 status: "False" lastProbeTime: null lastTransitionTime: 2018-01-01T00:00:00Z containerStatuses: - containerID: docker://abcd... ready: true ...
命令 kubectl patch
不支持修改對象的狀態。 如果需要設置 Pod 的 status.conditions
,應用或者 Operators 需要使用 PATCH
操作。 你可以使用 Kubernetes 客戶端庫 之一來編寫代碼,針對 Pod 就緒態設置定制的 Pod 狀況。
對於使用定制狀況的 Pod 而言,只有當下面的陳述都適用時,該 Pod 才會被評估為就緒:
- Pod 中所有容器都已就緒;
readinessGates
中的所有狀況都為True
值。
參考:https://my.oschina.net/renhc/blog/4809076
參考:https://kubernetes.io/zh/docs/concepts/workloads/pods/pod-lifecycle/#pod-conditions