目录
pod 有了 phase,为什么还要有 conditions
前言
Kubernetes 中, pod 从创建到成功运行会分别处于不同的阶段,每个阶段又分为不同的状态,本文将简单介绍这个环节。
在 K8S 源码中,使用了 PodPhase 这个变量定义这几个阶段信息,如下图所示:
- 运行中(Pod Running):该 Pod 已经绑定到了一个节点上,Pod 中所有的容器都已被创建。至少有一个容器正在运行,或者正处于启动或重启状态。
- 等待中(Pod Pending): 创建 Pod 的请求已被 Kubernetes 系统接受,但有一个或者多个容器镜像尚未创建。可能的原因有,写数据到etcd,调度,pull镜像,启动容器这四个阶段中的任何一个阶段,pending 伴随的事件通常会有:ADDED, Modified这两个事件的产生。等待时间包括调度 Pod 的时间和下载镜像的时间,这可能需要花些时间。
- 正常终止(Pod Succeeded):pod中的所有的容器已经正常的自行退出,并且k8s永远不会自动重启这些容器,一般会是在部署job的时候会出现。
- 异常停止(Pod Eailed):Pod 中的所有容器都已终止了,并且至少有一个容器是因为失败终止。也就是说,容器以非0状态退出或者被系统终止。
- 未知状态(Pod Unkonwn):出于某种原因,无法获得Pod的状态,通常是由于与Pod主机通信时出错。
实际上还有一中状态Terminating,在代码和文档中都没有说明,但却是存在。这种情况出现杂无法获取所在主机的资源情况,一直在尝试建立连接。
PodStatus对象
Pod 有一个 PodStatus 对象,其中包含一个 PodConditions 数组。Pod 可能通过也可能未通过其中的一些状况测试。
pod 的 phase 字段
phase 作用
用于描述、查看、分析 pod 当前处于什么状态。
有哪些 phase
通常情况下,在 pod 的生命周期中,每个 pod 会处于 5 个不同的 phase:pending,running,succeed,failed,unknown。同一时间,1 个 pod 只能处于 1 个 phase。
- 当 pod 刚被创建时,它处于 pending 这个 phase,等待被调度;
- 如果 pod 中的一个或多个 container 处于运行状态时,那么 pod 就处于 running phase;
- 如果 pod 中的 container 不是被设置为无限运行下去的情况下(比如执行定时任务或一次性任务),且 container 运行结束,那么 pod 处于 succeed phase;
- 反之,如果 pod 中的 container 不是被设置为无限运行下去的情况下(比如执行定时任务或一次性任务),且 container 运行失败,那么 pod 处于 failed phase;
- 如果 pod 所在 node 上的 kubelet 出现故障或意外,而停止向 Kubernetes API server 报告它所在 node 上的 pod 的状态时,那么此时该 node 上的 pod 就处于 unknown phase;
pod 的 conditions 字段
pod 有了 phase,为什么还要有 conditions
因为 pod 的 phase 比较简单的描述了 pod 处于哪个具体情况,但是没有明确说明具体原因。
pod 的 conditions 的作用
用于描述 1 个 pod 当前是否处于哪个 phase,以及处于该 phase 的原因。及作为一个辅助手段,详细的展示 pod 的状态信息,用于问题排查分析时提供更多依据。同一时间,1 个 pod 可能处于多个 conditions。
Pod 的 conditions 表示了 Pod 的一些条件,是一个数组。pod的 conditions 状况默认有4个,它是由Pod controller生成,里面包含一些 Pod 必须满足的条件,只有所有的条件为 True 时,Pod 才可以提供服务。
pod 的 conditions 分类
通常分为 4 个 conditions:PodScheduled,Initialized,ContainersReady,Ready。见名知意:
- PodScheduled:意味着 pod 是否已经被调度到某个 node;
- Initialized:Pod 的 init containers 是否全部完成;
- ContainersReady:pod 中的所有 container 是否全部就绪;但这并不意味着 pod 也 ready;
- Ready:pod 是否就绪;只有 pod 中的所有 container 就绪,且 pod 的 readiness probe 也完成了,意味着 pod 可以对外提供服务了,才是 ready 状态。
conditions设计原则
conditions
寄居于资源对象的status
字段中,与status
其他字段值一样都用来表示资源的状态。 不过conditions
的设计初衷是提供一种通用的数据结构表示资源的状态,它通常能够提供比status
其他字段更详细的信息(比如状态切换时间、更新时间),conditions
实际上是一种扩展机制,外部监控程序可以根据conditions
无差别地监控各种资源的状态,而不必过分关注资源对象status
中的其他信息。
通常status.conditions
字段类型为切片,切片中的每个元素表示资源的某个状态,该状态由特定的控制器更新,比如Deployment
控制器会更新deployment
对象的status.conditions
信息。conditions
作为扩展机制,它还支持第三方控制器增加新的状态。通常status.conditions
中的信息由控制器根据资源的status
其他字段计算出来。
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"`
}