Pod 状态 ^

通过kubectl explain pod.status命令查看Pod 状态信息,Pod 的 status 字段是一个 PodStatus 对象,其中包含一个 phase 字段。

下面是 phase 可能的值:

  • 挂起(Pending):这个状态意味着,Pod 的 YAML 文件已经提交给了 Kubernetes,API 对象已经被创建并保存在 Etcd 当中。但是,这个 Pod 里有些容器因为某种原因而不能被顺利创建。比如,调度不成功。
  • 运行中(Running):该 Pod 已经调度成功,跟一个具体的节点绑定。Pod 中所有的容器都已被创建。至少有一个容器正在运行,或者正处于启动或重启状态
  • 成功(Succeeded):Pod 中的所有容器都被成功终止,并且不会再重启。这种情况在运行一次性任务时最为常见。
  • 失败(Failed):Pod 中的所有容器都已终止了,并且至少有一个容器是因为失败终止。也就是说,容器以非0状态退出或者被系统终止。这个状态的出现,意味着你得想办法 Debug 这个容器的应用,比如查看 Pod 的 Events 和日志。
  • 未知(Unknown):这是一个异常状态,意味着 Pod 的状态不能持续地被 kubelet 汇报给 kube-apiserver,这很有可能是主从节点(Master 和 Kubelet)间的通信出现了问题。

Pod conditions ^

Pod 有一个 PodStatus 对象,其中包含一个 PodConditions 数组。Pod 可能通过也可能未通过其中的一些状况测试。

  • PodScheduled:Pod 已经被调度到某节点;
  • ContainersReady:Pod 中所有容器都已就绪;
  • Initialized:所有的 Init 容器 都已成功启动;
  • Ready:Pod 可以为请求提供服务,并且应该被添加到对应服务的负载均衡池中。
字段名称 描述
type Pod 状况的名称
status 表明该状况是否适用,可能的取值有 “True“, “False“ 或 “Unknown
lastProbeTime 上次探测 Pod 状况时的时间戳
lastTransitionTime Pod 上次从一种状态转换到另一种状态时的时间戳
reason 机器可读的、驼峰编码(UpperCamelCase)的文字,表述上次状况变化的原因
message 人类可读的消息,给出上次状态转换的详细信息

Container states ^

Kubernetes 会跟踪 Pod 中每个容器的状态,就像它跟踪 Pod 总体上的阶段一样。 你可以使用容器生命周期回调 来在容器生命周期中的特定时间点触发事件。

一旦调度器将 Pod 分派给某个节点,kubelet 就通过 容器运行时 开始为 Pod 创建容器。 容器的状态有三种:Waiting(等待)、Running(运行中)和 Terminated(已终止)。

要检查 Pod 中容器的状态,你可以使用 kubectl describe pod <pod 名称>。 其输出中包含 Pod 中每个容器的状态。

每种状态都有特定的含义

Waiting (等待)

如果容器并不处在 RunningTerminated 状态之一,它就处在 Waiting 状态。 处于 Waiting 状态的容器仍在运行它完成启动所需要的操作:例如,从某个容器镜像 仓库拉取容器镜像,或者向容器应用 Secret 数据等等。 当你使用 kubectl 来查询包含 Waiting 状态的容器的 Pod 时,你也会看到一个 Reason 字段,其中给出了容器处于等待状态的原因。

Running(运行中)

Running 状态表明容器正在执行状态并且没有问题发生。 如果配置了 postStart 回调,那么该回调已经执行且已完成。 如果你使用 kubectl 来查询包含 Running 状态的容器的 Pod 时,你也会看到 关于容器进入 Running 状态的信息。

Terminated(已终止)

处于 Terminated 状态的容器已经开始执行并且或者正常结束或者因为某些原因失败。 如果你使用 kubectl 来查询包含 Terminated 状态的容器的 Pod 时,你会看到 容器进入此状态的原因、退出代码以及容器执行期间的起止时间。

如果容器配置了 preStop 回调,则该回调会在容器进入 Terminated 状态之前执行。

容器重启策略 ^

Pod 的 spec 中包含一个 restartPolicy 字段,其可能取值包括 Always、OnFailure 和 Never。默认值是 Always。

restartPolicy 适用于 Pod 中的所有容器。restartPolicy 仅针对同一节点上 kubelet 的容器重启动作。当 Pod 中的容器退出时,kubelet 会按指数回退 方式计算重启的延迟(10s、20s、40s、…),其最长延迟为 5 分钟。 一旦某容器执行了 10 分钟并且没有出现问题,kubelet 对该容器的重启回退计时器执行 重置操作。不同类型的的控制器可以控制 Pod 的重启策略:

  • Job:适用于一次性任务如批量计算,任务结束后 Pod 会被此类控制器清除。Job 的重启策略只能是"OnFailure"或者"Never"
  • ReplicaSetDeployment:此类控制器希望 Pod 一直运行下去,它们的重启策略只能是"Always"
  • DaemonSet:每个节点上启动一个 Pod,很明显此类控制器的重启策略也应该是"Always"

Pod Hook

实际上 Kubernetes 为我们的容器提供了生命周期的钩子,就是我们说的 Pod Hook,Pod Hook 是由 kubelet 发起的,当容器中的进程启动前或者容器中的进程终止之前运行,这是包含在容器的生命周期之中。我们可以同时为 Pod 中的所有容器都配置 hook。

Kubernetes 为我们提供了两种钩子函数:

  • PostStart:这个钩子在容器创建后立即执行。但是,并不能保证钩子将在容器 ENTRYPOINT 之前运行(并不严格保证顺序),因为没有参数传递给处理程序。主要用于资源部署、环境准备等。不过需要注意的是如果钩子花费太长时间以至于不能运行或者挂起,容器将不能达到 running 状态。
  • PreStop:这个钩子在容器终止之前立即被调用。它是阻塞的,意味着它是同步的,所以它必须在删除容器的调用发出之前完成。主要用于优雅关闭应用程序、通知其他系统等。如果钩子在执行期间挂起,Pod 阶段将停留在 running 状态并且永不会达到 failed 状态。

如果 PostStart 或者 PreStop 钩子失败, 它会杀死容器。所以我们应该让钩子函数尽可能的轻量。当然有些情况下,长时间运行命令是合理的, 比如在停止容器之前预先保存状态。

PostStartPreStop 区别:

PostStart并不严格保证顺序。

preStop 发生的时机,则是容器被杀死之前。preStop 操作的执行,是同步的。所以,它会阻塞当前的容器杀死流程,直到这个 Hook 定义操作完成之后,才允许容器被杀死

另外我们有两种方式来实现上面的钩子函数:

  • Exec - 用于执行一段特定的命令,不过要注意的是该命令消耗的资源会被计入容器。
  • HTTP - 对容器上的特定的端点执行 HTTP 请求。