前言:Pod的生命周期概述
pod
遵循一个既定的生命周期,在起始的时候,它会是Pending
状态,然后如果有一个主容器运行成功,那么就进入Running
状态,之后取决于有没有容器失败,如果有失败的话则进入Failed
状态,否则则是Succeeded
状态。
当Pod
状态为运行态的时候,kubelet
仍然能够重启容器去处理错误。在K8S API层面,Pod
也和其他对象一样,拥有一个期望状态和一个实际状态,Pod
在它的生命周期内只会被调度一次,一旦Pod
被调度到了某个节点,这个Pod
就会一直在这个结点上运行,直到它被暂停或者结束。
在前文Pod详解(一)中我们说过,Pod
在k8s内部其实不是一个稳定的对象,而是一个相对暂时态并且不稳定的对象,Pod
是被更上层的封装,即workload resource
(老版本也叫controller
)所控制的,而这个上层的封装在K8S中才是一个能够自我调控以达到稳定存在状态的对象。
在Pod
被删除重建、或者失效的时候,workload resource
会建立一个全新的pod
,也就是name
不同,uid
也不同的Pod
来代替这个Pod
。
不知道大家有没有考虑过一个问题:既然Name已经能够唯一标识Pod,那么为什么Pod里还需要引入UID这个字段呢?
在K8S中对象的命名规则是这样的:子对象名字=父对象名字+随机字符串。
如果一个Pod
被高级workload
资源重建之后,会有一个新的名称(随机字符串)发生改变,以进行唯一性标识,但是Pod Name
的唯一性只是命名空间级别的,对于整个集群来说并不唯一,所以引入了UID
来作为集群内部的唯一标识。
同时,如果有和这个Pod
生命周期相同的关联物,比如一个volume
,它也会被销毁、重建。
我们可以简单的把Pod的状态分为两个部分,分别是阶段Phase
和状态Conditions
,前者是对Pod
的高级概述,用来粗略的表示Pod
在生命周期中的当前阶段;后者是一个更加详细和高级的状态,包含一个数组,每个元素都有一个Type
和Status
字段来提供更加详细的信息。
实战:重启Pod
下面让我们来试试:现在我有一个只有一个pod
的deployment
,我们来销毁这个pod会发生什么。
我们通过kubectl
来显示这个deployment
的详情信息,同样是前文Pod详解(一)中我们创建的那个非常简单的deployment
。
然后查看当前命名空间下的所有pod
,再手动删掉我们当前被deployment
所管理的这个pod。
再次查看deployment
的具体信息,以及当前命名空间下的所有事件,会发现原来的pod
已经被删除了,并且重新建立了一个相同配置的pod
实例,但是名字已经发生改变。
通过K8S事件,我们能很清楚的看到具体Pod
销毁重建的过程如下:
- 停止原有的容器,删掉
Pod
。 - 创建新
Pod
,拉取镜像创建容器。 - 给新的
Pod
分配资源,如IP
地址等。
Pod Phase
概述
这个字段标识着Pod的当前状态,一共有Pending、Running、Succeeded、Failed、Unknown
五个值,它是对Pod
所在生命周期中位置的简单宏观描述,我们可以通过status.phase
字段来观察到现在pod
的状态是什么样子的。
下面是对K8S官方文档的引用,详细解释了这五个值的描述以及什么时候会出现。
Value | Description |
---|---|
Pending | Pod已经被K8S系统接受,但有一个或者多个容器尚未创建亦未运行。此阶段包括等待Pod被调度的时间和通过网络下载镜像的时间。 |
Running | Pod已经绑定到了某个节点,Pod中所有的容器都已经被创建。至少有一个容器仍在运行,或者正处于启动或重启状态。 |
Succeeded | Pod中的所有容器都已成功终止,并且不会再重启。 |
Failed | Pod中的所有容器都已终止,并且至少有一个容器是因为失败终止。也就是说,容器以非0状态退出或者被系统终止。 |
Unknown | 因为某些原因无法取得Pod的状态,这种情况通常是因为与Pod所在的主机通信失败。 |
当然,除了上面的状态之外,Pod可能还有一个短暂的Terminating
状态用来表示这个Pod
正在结束中,只有在Pod
优雅结束的时候才会显示这个状态,我们有时候通过kubectl
能够得到这个状态,一般在一段时间之后,30S之后这个状态就会流转为其他状态。
如果集群中有某个节点死掉或者失联,那么K8S集群会将失去的节点上运行的所有Pod
的状态设置为Failed
。
源码
下面让我们来看看PodPhase
的源码。
// PodPhase is a label for the condition of a pod at the current time.
type PodPhase string
// These are the valid statuses of pods.
const (
// PodPending means the pod has been accepted by the system, but one or more of the containers
// has not been started. This includes time before being bound to a node, as well as time spent
// pulling images onto the host.
PodPending PodPhase = "Pending"
// PodRunning means the pod has been bound to a node and all of the containers have been started.
// At least one container is still running or is in the process of being restarted.
PodRunning PodPhase = "Running"
// PodSucceeded means that all containers in the pod have voluntarily terminated
// with a container exit code of 0, and the system is not going to restart any of these containers.
PodSucceeded PodPhase = "Succeeded"
// PodFailed means that all containers in the pod have terminated, and at least one container has
// terminated in a failure (exited with a non-zero exit code or was stopped by the system).
PodFailed PodPhase = "Failed"
// PodUnknown means that for some reason the state of the pod could not be obtained, typically due
// to an error in communicating with the host of the pod.
PodUnknown PodPhase = "Unknown"
)
能看出来PodPhase
其实就是字符串类型的别名,并且和文档上描述的一样,这个类型只有五个值,有点类似于自动机的思想,字段的值会在这五个值之间进行流转。
Pod Conditions
概述
Pod Conditions
能够表示更加详细的Pod
状态,每个Pod
都会有一个Conditions
数组,这个数组中的每个元素都会有type
和status
两个字段,以及一些其他的控制信息,能看出来这个状态带上了时间,信息等详细状态,这也刚好作为Pod phase
过于粗略、无法展示详细状态信息的补充。
同时,一个Pod
拥有一个Conditions
数组,而不是单独的Conditions
字段能够方便跟踪和记录Pod
的状态和实践的历史,以便更好地监控和诊断Pod
的行为,并且一个Pod
可能同时处于不同的条件状态下,方便表示当前的具体状态。
每个Condition
由以下五部分组成,翻译自K8S官方文档。
Field name | Description |
---|---|
type | Pod 条件的Name |
status | 标识这个Condition的状态,值可能为True False或者Unkown中的一个 |
lastProbeTime | 上次探测Pod Condition的时间戳 |
lastTransitionTime | 上次Pod从一个状态流转至另一个状态的时间 |
reason | 上一次状态流转的原因 |
message | 上一次状态流转蕴含的信息 |
源码
type PodCondition struct {
// Type is the type of the condition.
// More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions
Type PodConditionType `json:"type" protobuf:"bytes,1,opt,name=type,casttype=PodConditionType"`
// Status is the status of the condition.
// Can be True, False, Unknown.
// More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions
Status ConditionStatus `json:"status" protobuf:"bytes,2,opt,name=status,casttype=ConditionStatus"`
// Last time we probed the condition.
// +optional
LastProbeTime metav1.Time `json:"lastProbeTime,omitempty" protobuf:"bytes,3,opt,name=lastProbeTime"`
// Last time the condition transitioned from one status to another.
// +optional
LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty" protobuf:"bytes,4,opt,name=lastTransitionTime"`
// Unique, one-word, CamelCase reason for the condition's last transition.
// +optional
Reason string `json:"reason,omitempty" protobuf:"bytes,5,opt,name=reason"`
// Human-readable message indicating details about last transition.
// +optional
Message string `json:"message,omitempty" protobuf:"bytes,6,opt,name=message"`
}
首先我们能看到PodCondition
由两个结构体,两个时间戳和两个String
组成,时间戳和String代表的含义很容易看出来,通过变量名我们就能理解含义,所以主要讲解PodConditionType
和ConditionStatus
这两个结构体复合字段。
PodConditionType
// PodConditionType is a valid value for PodCondition.Type
type PodConditionType string
// These are valid conditions of pod.
const (
// ContainersReady indicates whether all containers in the pod are ready.
ContainersReady PodConditionType = "ContainersReady"
// PodInitialized means that all init containers in the pod have started successfully.
PodInitialized PodConditionType = "Initialized"
// PodReady means the pod is able to service requests and should be added to the
// load balancing pools of all matching services.
PodReady PodConditionType = "Ready"
// PodScheduled represents status of the scheduling process for this pod.
PodScheduled PodConditionType = "PodScheduled"
)
PodConditionType
的状态也是字符串类型的别名,但是它的值和Phase
字段的几个值相比,更加偏向于具体状态,分别有ContainersReadyPodInitializedPodReadyPodScheduled
几个值,它们的具体含义如下
- ContainerReady:所有容器是否全为就绪状态
- PodInitialized:所有初始化容器是否已经成功启动
- PodReady:Pod是否能够已经准备好接受流量,能够正常处理请求
- PodScheduled:Pod是否已经被调度到某个节点上
ConditionStatus
type ConditionStatus string
// These are valid condition statuses. "ConditionTrue" means a resource is in the condition.
// "ConditionFalse" means a resource is not in the condition. "ConditionUnknown" means kubernetes
// can't decide if a resource is in the condition or not. In the future, we could add other
// intermediate conditions, e.g. ConditionDegraded.
const (
ConditionTrue ConditionStatus = "True"
ConditionFalse ConditionStatus = "False"
ConditionUnknown ConditionStatus = "Unknown"
)
这个值主要是和条件PodConditionType
进行关联,用来指定当前Pod
有没有满足这个状态,如果满足则为真,否则为假,当特殊情况时,比如Pod
网络和集群无法联通,那么可能会出现Unknown
状态。
结语
今天这篇博客主要从Go
源码方面向大家剖析Pod
生命周期相关的两个字段Phase
和Conditions
,并介绍了它们的区别和具体作用。
《每天十分钟,轻松入门K8S》的第五篇04.源码级别Pod详解(二) 到这里就结束了,感谢您看到这里。
之后的几讲都会和Pod
相关,深入源码级别探索K8S核心概念Pod
相关内容,感兴趣的小伙伴欢迎点赞、评论、收藏,您的支持就是对我最大的鼓励。