本篇文章我们主要介绍Pod的生命周期。Pod遵循所定义的生命周期,在起始Pending阶段,如果Pod中primary容器中至少有一个开始运行,则其状态变为Running,然后再经过成功或失败阶段,主要取决于Pod中的任何容器是否因失败而终止。

Pod在其生命周期内仅仅只能被scheduled调度一次,一旦Pod被scheduled调度分配到某个Node节点后,该Pod将在Node上运行直到其停止或终止。在Pod运行的同时,kubelet能够重新启动容器以处理一些错误,在Pod中,Kubernetes会跟踪不同容器的状态,并且确定采取任何措施使Pod健康运行。

Pod寿命

像各个应用程序容器一样,Pod的寿命也是相对短暂的,当创建一个Pod时,会为其分配一个唯一的ID(UID),并将其调度到最合适的Node,直到其终止或删除为止。如果此Node死掉,Kubernetes会在超时后删除该Node节点上的Pod。

Pod本身并不能自我修复,如果Pod被安排到节点然后失败,又或者缺少资源,都会导致Pod被删除。Kubernetes使用更高级的抽象,也就是控制器,使用Pod控制器管理一次性的Pod实例工作。

Pod phase

Pod的status字段是PodStatus对象,其中包含一个phase字段,可以通过以下命令查看:

kubectl get pod <pod name> -o yaml

Pod phase字段简要的对Pod处于生命周期位置进行概括,以下是Pod phase可能的值:

描述
Pending 挂起。Pod已经被Kubernetes集群所接受,但是尚未有一个或多个容器可以运行,该状态包括Pod等待所花费的时间,以及容器镜像下载所需的时间
Running 正在运行。Pod已经被绑定在Node上,并且Pod内所有容器被创建,至少有一个容器已经运行,或者正在启动或重新启动
Succeeded 成功。Pod中所有容器都已经成功终止,并且不会再重启
Failed 失败。Pod中所有容器都已终止,并且至少有一个容器是因为失败终止,也就是说至少一个容器以非0状态退出或者被系统终止
Unknown 因为某些原因无法获取Pod状态,通常是因为与Pod所在的节点通信时发生错误

删除Pod时Terminating并不是Pod生命周期之一,Kubernetes授予Pod适当终止的期限,默认为30秒,可以使用 – force 来强制删除Pod

如果某个Node节点死亡或与集群断开连接,Kubernetes会应用一个策略,将该节点上的所有Pod的phase设置为Failed

容器状态

除了Pod总体状态,Kubernetes还会跟踪Pod内每个容器状态,你可以通过使用容器生命周期钩子来触发事件,来使容器在某些时间点运行。

一旦Scheduler将Pod分配给Node节点上,kubelet会为该Pod创建容器,容器有三种状态:Waiting、Running和Terminated。

可以通过以下命令查看Pod内容器的状态:

kubectl describe pod <pod name>

Waiting

处于Waiting状态的容器仍在运行以完成启动所需的操作,例如,从容器镜像注册表中提取容器镜像,或应用secret数据。当使用kubectl查询Pod容器状态是Waiting时,还会看到一个reason字段,reason字段简述了容器处于该状态的原因。

Running

该Running状态表示容器正在执行且没有任何问题,如果postStart配置了一个挂钩,则它已经执行完成。当使用kubectl查询Pod容器状态是Running时,还会看到有关容器何时进入Running状态的信息。

Terminated

处于Terminated状态表示容器开始执行,然后运行完成或者由于某种原因失败。如果preStop配置了挂钩,则挂钩在容器进入Terminated状态之前运行。当使用kubectl查询Pod容器状态是Terminated时,还会看到一个原因,一个退出代码以及容器执行开始和结束时间。

容器重启策略

容器的重启策略由spec.restartPolicy字段指定,有以下三种:

  • Always:容器失效时,kubelet自动重启该容器
  • OnFailure:容器终止运行且以非0退出时重启
  • Never:不论状态如何,kubelet都不重启该容器

restartPolicy策略应用于Pod中所有的容器,在Pod中容器退出后,kubelet会以指数级退避延迟(10s、20s、40s等)重启容器,上限为5分钟,一旦容器执行了10分钟而没有任何问题,kubelet将重置该容器退避计时器。

Pod conditions

Pod status字段下有一个数组类型的conditions字段,记录了通过该condition条件的情况,可以通过以下命令查看status.conditions字段

kubectl get pod <pod name> -o yaml
字段 描述
type Pod condition名称
status 指该条件是否适用,可能的指”True”、”False”、”Unknown”
lastProbeTime 上一次探测Pod条件的时间戳
lastTransitionTime Pod上一次从一种状态转换为另一种状态的时间戳。
reason 机器可读的文本,表示最后一次状态变更的原因标识
message 人可读,表示最后一次状态变更的原因

该type字段可能的值:

PodScheduled:Pod已经被Scheduler调度到某个Node

Initialized:所有init containers都已成功启动

Ready:Pod已经能够处理请求,可以被添加到后端的service负载

ContainersReady:所有容器都处于”Ready”状态

容器探针

探针是通过周期性的执行来诊断kubelet上的容器,kubelet调用探针执行诊断由容器实现的Handler,主要有三种类型的处理程序:

  • ExecAction:在容器内部执行命令,如果命令以状态0退出,则认为诊断成功。
  • TCPSocketAction:对指定端口上Pod的IP地址执行TCP检查,如果端口打开,则认为诊断成功。
  • HTTPSocketAction:对指定端口和Pod IP地址执行HTTP的GET请求,如果响应的状态码大于或等于200且小于400,则认为诊断成功。

探针具体有以下三个结果:

  • Success:诊断成功
  • Failure:诊断失败
  • Unknown:诊断失败,不采取任何措施

kubelet可以对容器诊断有三种探针方式:

  • livenessProbe:指示容器是否正在运行。如果存活性探针失败,则kubelet将杀死该容器,并且按照重启策略执行相应的操作。如果容器未提供存活性探针,则默认状态为Success。
  • readinessProbe:指示容器是否准备好响应请求。如果就绪性探针失败,则端点控制器将从与Pod匹配的Service的端点中删除该Pod的IP地址,初始延迟之前的就绪状态默认为Failure。如果容器未提供就绪性探针,则默认状态为Success。
  • startupProbe:指示容器中的应用是否已启动。如果提供了启动探针,则将禁用所有其他探针,知道启动成功成功。如果启动探针失败,则kubelet将杀死容器,并且该容器将受到重启策略的约束。如果容器未提供启动探针,则默认状态为Success。

这里很多人将readinessProbe和startupProbe搞混,其实还是有区别的。举个例子,当一个应用程序Pod启动需要60s的时间,readinessProbe探针我们设定每10s探针一次(失败3次认为探针失败),那么在容器还没有启动完成,kubelet就会杀死Pod,按照重启策略一直重启Pod,其实我们修改readinessProbe将失败次数改为6次,也可以解决这个问题,但是问题来了,要是下一个应用程序启动需要70秒,那就还需要修改。但是使用startupProbe探针,我们可以设定每10s探针一次(失败10次认为探针失败),也就是在100s内应用程序启动成功就没有问题,而且startupProbe也不受重启策略的约束,但是这种方式还是不能确定具体时间,只能给一个大概的范围。

Pod终止

Pod是集群节点上运行的进程,当我们不再需要时,允许这些进程正常终止。

一个Pod正常终止的流程如下:

  1. 用户使用kubectl工具手动删除特定的Pod

  2. API Server更新宽限期(默认30s),超过宽限期Pod被视为”dead”状态

  3. 将Pod标记为”Terminating”状态,kubelet看到Pod状态标记为”Terminating”,便开始关闭该Pod相关进程

    (1)如果Pod容器中定义了preStop钩子,则kubelet会在容器内部运行该钩子。如果preStop在宽限期到期后仍在运行,则kubelet要求将宽限期再延迟2秒

    (2)kubelet向容器内进程发送TERM信号

  4. 在kubelet正常关闭的同时,endpoints控制器监控到Pod对象关闭,将Pod与Service匹配的endpoints列表中删除

  5. 当宽限期到期时,kubelet会触发强制关闭,若存在任何一个运行的进程,Pod将收到SIGKILL信号

  6. 通过将宽限期设置为0(立即删除),kubelet请求API Server强制删除Pod对象

  7. API Server删除Pod对象,然后该Pod不再从客户端可见

强制Pod终止

默认情况下,所有删除均在30秒内完成,也可以通过kubectl delete命令支持 –grace-period=允许覆盖默认的宽限期

将宽限期设置为0,表示强行并立即从API Server中删除Pod

必须指定额外标志 –force 一起与 –grace-period=0 使用