Pod 的生命周期

本页面讲述 Pod 的生命周期。 Pod 遵循一个预定义的生命周期,起始于 Pending 阶段,当至少其中有一个主要容器正常启动,则进入 Running,之后取决于 Pod 中是否有容器以失败状态结束而进入 Succeeded 或者 Failed 阶段。

在 Pod 运行期间,kubelet 能够重启容器以处理一些失效场景。 在 Pod 内部,Kubernetes 跟踪不同容器的状态 并确定使 Pod 重新变得健康所需要采取的动作。

在 Kubernetes API 中,Pod 包含规约部分和实际状态部分。 Pod 对象的状态包含了一组 Pod 状况(Conditions)。 如果应用需要的话,你也可以向其中注入自定义的就绪性信息。

Pod 在其生命周期中只会被调度一次。 一旦 Pod 被调度(分派)到某个节点,Pod 会一直在该节点运行,直到 Pod 停止或者 被终止。

Pod 生命期

和一个独立的应用容器一样,Pod 也被认为是相对临时性(而不是长期存在)的实体。 Pod 会被创建、赋予一个唯一的 ID(UID), 并被调度到节点,并在终止(根据重启策略)或删除之前一直运行在该节点。

如果一个节点死掉了,调度到该节点 的 Pod 也被计划在给定超时期限结束后删除。

Pod 自身不具有自愈能力。如果 Pod 被调度到某节点之后失效,或者调度操作本身失效,Pod 会被删除;与此类似,Pod 无法在节点资源耗尽或者节点维护期间继续存活。Kubernetes 使用一种高级抽象,称作 控制器,来管理这些相对而言 可随时丢弃的 Pod 实例。

任何给定的 Pod (由 UID 定义)从不会被“重新调度(rescheduled)”到不同的节点; 相反,这一 Pod 可以被一个新的、几乎完全相同的 Pod 替换掉。 如果需要,新 Pod 的名字可以不变,但是其 UID 会不同。

如果某物声称其生命期与某 Pod 相同,例如存储卷, 这就意味着该对象在此 Pod (UID 亦相同)存在期间也一直存在。 如果 Pod 因为任何原因被删除,甚至某完全相同的替代 Pod 被创建时, 这个相关的对象(例如这里的卷)也会被删除并重建。

Pod 阶段

Pod 的 status 字段是一个 PodStatus 对象,其中包含一个 phase 字段。

Pod 的阶段(Phase)是 Pod 在其生命周期中所处位置的简单宏观概述。 该阶段并不是对容器或 Pod 状态的综合汇总,也不是为了成为完整的状态机。

Pod 阶段的数量和含义是严格定义的。 除了本文档中列举的内容外,不应该再假定 Pod 有其他的 phase 值。

下面是 phase 可能的值:

取值 描述 Pending(悬决) Pod 已被 Kubernetes 系统接受,但有一个或者多个容器尚未创建亦未运行。此阶段包括等待 Pod 被调度的时间和通过网络下载镜像的时间, Running(运行中) Pod 已经绑定到了某个节点,Pod 中所有的容器都已被创建。至少有一个容器仍在运行,或者正处于启动或重启状态。 Succeeded(成功) Pod 中的所有容器都已成功终止,并且不会再重启。 Failed(失败) Pod 中的所有容器都已终止,并且至少有一个容器是因为失败终止。也就是说,容器以非 0 状态退出或者被系统终止。 Unknown(未知) 因为某些原因无法取得 Pod 的状态。这种情况通常是因为与 Pod 所在主机通信失败。

如果某节点死掉或者与集群中其他节点失联,Kubernetes 会实施一种策略,将失去的节点上运行的所有 Pod 的 phase 设置为 Failed。

Pod 状况 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 人类可读的消息,给出上次状态转换的详细信息

Pod 就绪态 FEATURE STATE: Kubernetes v1.14 [stable] 你的应用可以向 PodStatus 中注入额外的反馈或者信号:Pod Readiness(Pod 就绪态)。 要使用这一特性,可以设置 Pod 规约中的 readinessGates 列表,为 kubelet 提供一组额外的状况供其评估 Pod 就绪态时使用。

就绪态门控基于 Pod 的 status.conditions 字段的当前值来做决定。 如果 Kubernetes 无法在 status.conditions 字段中找到某状况,则该状况的 状态值默认为 "False"。

这里是一个例子:

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
...

Pod 就绪态的状态 命令 kubectl patch 不支持修改对象的状态。 如果需要设置 Pod 的 status.conditions,应用或者 Operators 需要使用 PATCH 操作。 你可以使用 Kubernetes 客户端库 之一来编写代码,针对 Pod 就绪态设置定制的 Pod 状况。

对于使用定制状况的 Pod 而言,只有当下面的陈述都适用时,该 Pod 才会被评估为就绪:

Pod 中所有容器都已就绪; readinessGates 中的所有状况都为 True 值。 当 Pod 的容器都已就绪,但至少一个定制状况没有取值或者取值为 False, kubelet 将 Pod 的状况设置为 ContainersReady。

Pod 的终止 由于 Pod 所代表的是在集群中节点上运行的进程,当不再需要这些进程时允许其体面地 终止是很重要的。一般不应武断地使用 KILL 信号终止它们,导致这些进程没有机会 完成清理操作。

设计的目标是令你能够请求删除进程,并且知道进程何时被终止,同时也能够确保删除 操作终将完成。当你请求删除某个 Pod 时,集群会记录并跟踪 Pod 的体面终止周期, 而不是直接强制地杀死 Pod。在存在强制关闭设施的前提下, kubelet 会尝试体面地终止 Pod。

通常情况下,容器运行时会发送一个 TERM 信号到每个容器中的主进程。 很多容器运行时都能够注意到容器镜像中 STOPSIGNAL 的值,并发送该信号而不是 TERM。 一旦超出了体面终止限期,容器运行时会向所有剩余进程发送 KILL 信号,之后 Pod 就会被从 API 服务器 上移除。如果 kubelet 或者容器运行时的管理服务在等待进程终止期间被重启, 集群会从头开始重试,赋予 Pod 完整的体面终止限期。

下面是一个例子:

你使用 kubectl 工具手动删除某个特定的 Pod,而该 Pod 的体面终止限期是默认值(30 秒)。

API 服务器中的 Pod 对象被更新,记录涵盖体面终止限期在内 Pod 的最终死期,超出所计算时间点则认为 Pod 已死(dead)。 如果你使用 kubectl describe 来查验你正在删除的 Pod,该 Pod 会显示为 "Terminating" (正在终止)。 在 Pod 运行所在的节点上:kubelet 一旦看到 Pod 被标记为正在终止(已经设置了体面终止限期),kubelet 即开始本地的 Pod 关闭过程。

如果 Pod 中的容器之一定义了 preStop 回调, kubelet 开始在容器内运行该回调逻辑。如果超出体面终止限期时,preStop 回调逻辑 仍在运行,kubelet 会请求给予该 Po

与此同时,kubelet 启动体面关闭逻辑,控制面会将 Pod 从对应的端点列表(以及端点切片列表, 如果启用了的话)中移除,过滤条件是 Pod 被对应的 服务以某 选择算符选定。 ReplicaSets和其他工作负载资源 不再将关闭进程中的 Pod 视为合法的、能够提供服务的副本。关闭动作很慢的 Pod 也无法继续处理请求数据,因为负载均衡器(例如服务代理)已经在终止宽限期开始的时候 将其从端点列表中移除。 超出终止宽限期限时,kubelet 会触发强制关闭过程。容器运行时会向 Pod 中所有容器内 仍在运行的进程发送 SIGKILL 信号。 kubelet 也会清理隐藏的 pause 容器,如果容器运行时使用了这种容器的话。

kubelet 触发强制从 API 服务器上删除 Pod 对象的逻辑,并将体面终止限期设置为 0 (这意味着马上删除)。

API 服务器删除 Pod 的 API 对象,从任何客户端都无法再看到该对象。

强制终止 Pod 注意: 对于某些工作负载及其 Pod 而言,强制删除很可能会带来某种破坏。 默认情况下,所有的删除操作都会附有 30 秒钟的宽限期限。 kubectl delete 命令支持 --grace-period= 选项,允许你重载默认值, 设定自己希望的期限值。

将宽限期限强制设置为 0 意味着立即从 API 服务器删除 Pod。 如果 Pod 仍然运行于某节点上,强制删除操作会触发 kubelet 立即执行清理操作。

说明: 你必须在设置 --grace-period=0 的同时额外设置 --force 参数才能发起强制删除请求。 执行强制删除操作时,API 服务器不再等待来自 kubelet 的、关于 Pod 已经在原来运行的节点上终止执行的确认消息。 API 服务器直接删除 Pod 对象,这样新的与之同名的 Pod 即可以被创建。 在节点侧,被设置为立即终止的 Pod 仍然会在被强行杀死之前获得一点点的宽限时间。

如果你需要强制删除 StatefulSet 的 Pod,请参阅 从 StatefulSet 中删除 Pod 的任务文档。

失效 Pod 的垃圾收集 对于已失败的 Pod 而言,对应的 API 对象仍然会保留在集群的 API 服务器上,直到 用户或者控制器进程显式地 将其删除。

控制面组件会在 Pod 个数超出所配置的阈值 (根据 kube-controller-manager 的 terminated-pod-gc-threshold 设置)时 删除已终止的 Pod(阶段值为 Succeeded 或 Failed)。 这一行为会避免随着时间演进不断创建和终止 Pod 而引起的资源泄露问题。

update @ 2021.01.20

results matching ""

    No results matching ""