QingyaFan / blog

博客

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Pod 的生命周期状态

QingyaFan opened this issue · comments

Pod 的状态

pkg/apis/core/types.go L3910

type PodStatus struct {
	Phase PodPhase
	Conditions []PodCondition
	QOSClass PodQOSClass
	ContainerStatuses []ContainerStatus
	EphemeralContainerStatuses []ContainerStatus
	Resize PodResizeStatus
	ResourceClaimStatuses []PodResourceClaimStatus
}
  • Phase:Pod 所处阶段
  • Conditions:是一个 PodConditin 数组,我启动了一个 postgres 的 deployment,describe 其中一个 pod,你会发现

image

Pod 的阶段(phase)

PodPhase 是一个字符串别名:type PodPhase string,是pod当前 condition 的一个描述,包括 Pending、Running、Succeeded、Failed、Unknown 1

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

从这些描述中,我们可以看出 Pod 和 Container 的关系很紧密。

Pod ReadinessGate

ReadinessGate 影响Pod是否就绪的判断,Pod就绪则会被认为可以接受请求。使用方法是在 Pod 的 .spec.readinessGates 加入 kv,它是一个数组,允许多个条件同时满足才被认定为 ready,例如:

kind: Pod
...
spec:
  readinessGates:
    - conditionType: "www.example.com/feature-1"
status:
  conditions:
...

kubectl patch方法不支持修改 status,只能用 client-go 之类的 sdk 编程实现,如通过 controller。如果一个 Pod 使用了自定义 condition,只有满足以下条件,Pod才能被认定为 ready:

  1. pod中所有的container都已 ready
  2. 所有 readinessGates 都为 True

如果 container 都已ready,但 readiness gates 并不都为 True,那么 Pod 状态将是 ContainersReady

与 ReadinessProbe 的不同

注意 k8s 的 ReadinessProbe(就绪探针)和 ReadinessGate 没有直接关系,但只有它俩都 ready,Pod才会被认定为可以接收请求。ReadinessProbe 支持 HTTP、RPC、执行脚本来确定某个Pod是否 ready:

HTTP

apiVersion: v1
kind: Pod
metadata:
  name: http-readiness-pod
spec:
  containers:
  - name: http-container
    image: my-http-app
    ports:
    - containerPort: 8080
    readinessProbe:
      httpGet:
        path: /healthz
        port: 8080
      initialDelaySeconds: 5
      periodSeconds: 10

说明:

  • initialDelaySeconds:容器启动后,探针开始执行检查的延迟时间
  • periodSeconds:探针检查的时间间隔

RPC

apiVersion: v1
kind: Pod
metadata:
  name: tcp-readiness-pod
spec:
  containers:
  - name: tcp-container
    image: my-rpc-app
    ports:
    - containerPort: 9090
    readinessProbe:
      tcpSocket:
        port: 9090
      initialDelaySeconds: 5
      periodSeconds: 10

执行脚本

apiVersion: v1
kind: Pod
metadata:
  name: exec-readiness-pod
spec:
  containers:
  - name: exec-container
    image: my-script-app
    readinessProbe:
      exec:
        command:
        - /bin/sh
        - -c
        - "curl -f http://localhost:8080/healthz || exit 1"
      initialDelaySeconds: 5
      periodSeconds: 10

容器的状态(Status)

类型定义参见 2

  • Waiting,如果容器并不处在 Running 或 Terminated 状态之一,它就处在 Waiting 状态。 处于 Waiting 状态的容器仍在运行它完成启动所需要的操作:例如, 从某个容器镜像仓库拉取容器镜像,或者向容器应用 Secret 数据等等。 当你使用 kubectl 来查询包含 Waiting 状态的容器的 Pod 时,你也会看到一个 Reason 字段,其中给出了容器处于等待状态的原因。
  • Running,Running 状态表明容器正在执行状态并且没有问题发生。 如果配置了 postStart 回调,那么该回调已经执行且已完成。 如果你使用 kubectl 来查询包含 Running 状态的容器的 Pod 时, 你也会看到关于容器进入 Running 状态的信息。
  • Terminated,处于 Terminated 状态的容器已经开始执行并且或者正常结束或者因为某些原因失败。 如果你使用 kubectl 来查询包含 Terminated 状态的容器的 Pod 时, 你会看到容器进入此状态的原因、退出代码以及容器执行期间的起止时间。如果容器配置了 preStop 回调,则该回调会在容器进入 Terminated 状态之前执行。

Pod 或 容器 的异常状态 3
不明确状态有 Terminating、Pending、ContainerCreating、Waiting
异常状态有

  • CrashLoopBackOff,Pod 如果处于 CrashLoopBackOff 状态说明之前是启动了,只是又异常退出了,只要 Pod 的 restartPolicy 不是 Never 就可能被重启拉起。
  • ImagePullBackOff

Pod Condition

PodCondition 是 pod 的状况,phase 是对 condition 的标签

// staging/src/k8s.io/apiserver/pkg/apis/example/types.go L73
type PodCondition struct {
	Type   PodConditionType
	Status ConditionStatus
	// +optional
	LastProbeTime metav1.Time
	// +optional
	LastTransitionTime metav1.Time
	// +optional
	Reason string
	// +optional
	Message string
}

PodCondition 有如下几个:

  • PodScheduled, 表明Pod已经被调度到一个node
  • PodReadyToStartContainers, Pod sandbox 已被成功创建并且网络已经正常
  • ContainersReady, Pod 中所有的容器已 ready
  • Initialized, 所有 init containers 均已完成
  • Ready, Pod已经可以正常接受请求,可以加入到负载均衡的下游中了
  • DisruptionTarget,表明pod正在被 terminated,原因可能是抢占(preemption)驱逐(eviction)GC(garbage-collection)

Sidecar 容器对 Pod Condition 和 Ready 判断的影响

  1. 容器生命周期的不同步:Sidecar 容器通常用于辅助主应用容器,可能需要在主容器之前启动或在主容器之后停止。如果 Sidecar 容器启动较慢,Pod 的 Ready 状态会受到影响,因为 Kubernetes 会等待所有容器都处于就绪状态。例如,如果一个日志收集的 Sidecar 容器启动缓慢,主应用容器虽然已经就绪,但整个 Pod 仍然会被认为是未就绪的,直到 Sidecar 容器也就绪;
  2. 容器的健康检查:Kubernetes 使用健康检查(liveness 和 readiness probes)来确定容器的健康状态。如果 Sidecar 容器的健康检查配置不当,可能导致 Pod 被标记为不健康,尽管主应用容器正常运行。例如,如果 Sidecar 容器出现短暂的故障并触发了健康检查的失败,Pod 可能会被重启,影响到主应用容器的正常运行;
  3. 容器的资源消耗:Sidecar 容器可能会消耗大量资源(如 CPU、内存),从而影响 Pod 的整体性能和稳定性。如果资源分配不合理,可能导致资源争用,影响 Pod 的稳定性。例如,一个监控 Sidecar 容器消耗过多内存,导致主应用容器的内存不足,从而触发 Pod 的 OOM(Out Of Memory)情况;
  4. 终止信号的处理:Kubernetes 在终止 Pod 时,会向所有容器发送终止信号,并等待它们优雅地关闭。如果 Sidecar 容器关闭时间较长或无法正确处理终止信号,可能延迟整个 Pod 的终止过程。例如,一个代理 Sidecar 容器在接收到终止信号后需要较长时间关闭,可能会导致 Pod 无法及时释放资源,影响集群的调度效率。

Footnotes

  1. https://kubernetes.io/zh-cn/docs/concepts/workloads/pods/pod-lifecycle/

  2. https://github.com/kubernetes/kubernetes/blob/16a594f907d0d4a6224dab2d0704793d5e7898f6/pkg/apis/core/types.go#L2678

  3. https://imroc.cc/kubernetes/troubleshooting/pod/index.html