【云原生|Kubernetes】06-Pod的生命周期和重启策略
文章目录
- 【云原生|Kubernetes】06-Pod的生命周期和重启策略
- Pod生命周期
- 生命周期
- Pod的状态
- Pod子状态
- Pod重启策略
- 调试Pod
- Pod 停滞在 Pending 状态
- Pod 停滞在 Waiting 状态
- Pod 处于 Crashing 或别的不健康状态
- Pod 处于 Running 态但是没有正常工作
Pod生命周期
生命周期
我们一般把Pod从创建到结束删除这段时间范围叫做Pod的什么周期,它主要包括一下几个过程:
- 对于所有的pod来说,首先是Pause容器的启动,Pause容器会为我们创建pod网络,volume,并随着pod一起运行;
- 随后将是init容器启动,一个pod中可以定义多个初始化容器,他们必须是串行执行,只有当所有的初始化容器执行完后,对应的主容器才会启动;
- init容器可有可无,可多可少
- 一个Init C完成后,才能进行下一个Init C的构建。如果Init容器失败,k8s会不断重启该Pod,直到Init容器运行成功为止。然而,如果pod对应的restartPolicy为Never,那么它不会重启
- 随后主容器启动,主容器Main C运行过程中,如果定义了start操作,首先进行一个start操作。然后如果定义了readiness就绪检测,就执行readiness就绪检测,readiness检测成功完成后,pod才会显示running,才会对外提供服务。如果定义了liveness存活检测,也会同时开始执行,如果liveness检测失败,kubelet杀死该Pod,然后根据重启策略restartPolicy决定是否对pod执行重启。若容器中不包含liveness探针,则kubelet认为该pod的liveness探针返回值永远是success。liveness存活检测是持续过程,一直持续到stop操作完成之后,Main C结束之前。
- 可以使用 Pod 的配置文件定义主容器的启动操作。您可以使用
command
或args
字段来定义容器启动时要执行的命令或参数(即start操作)- 主容器Main C结束退出时,如果定义了stop操作,则先进行stop操作,stop操作完成以后才允许退出。
- 可以使用 Pod 的配置文件定义主容器的停止操作。您可以使用
lifecycle
字段来定义容器在停止时要执行的命令或操作。(即stop操作)
Pod的状态
Pod在整个生命周期中被系统定义了各种状态,熟悉Pod的各种状态对于理解如何设置Pod的调度策略,重启策略和排查pod的启动异常事很有必要的。
状态值 | 描述 |
---|---|
Pending | API Server已经创建该Pod,但是在Pod内还有一个或多个容器的镜像没有创建,包括正在下载镜像的过程。当 Pod 创建后,它将进入 “Pending” 状态。在这个阶段中,Kubernetes 正在为该 Pod 分配节点和资源,并启动 Pod 中的容器。如果 Pod 中的容器无法启动,该 Pod 将一直停留在 “Pending” 状态。 |
Running | 当 Pod 中的容器成功启动并运行后,该 Pod 将进入 “Running” 状态。在这个阶段中,Pod 中的容器正在运行,并且可以通过 Kubernetes API 进行访问。 |
Successed | 当 Pod 中的所有容器成功完成其任务并退出时,该 Pod 将被标记为 “Succeeded” 状态。在这个阶段中,Pod 中的所有容器都已经完成了它们的任务,并且成功退出了。 |
Failed | 如果 Pod 中的容器由于错误或其他原因而意外终止,该 Pod 将被标记为 “Failed” 状态。在这个阶段中,Pod 中的容器已经停止运行,并且可能需要手动修复或重新创建。 |
Unkone | 果 Kubernetes 状态检查器无法确定 Pod 的状态,该 Pod 将被标记为 “Unknown” 状态。在这个阶段中,Kubernetes 可能无法连接到 Pod 中的容器,或者容器的状态可能无法被正确报告。 |
Pod子状态
状态值 | 描述 |
---|---|
ContainerCreating | Pod 中的一个或多个容器正在创建,并且尚未完成启动。这种状态通常表示容器镜像在下载或容器正在启动过程中。 |
Terminated | Pod 中的所有容器都已经终止或退出,并且没有任何重启。这种状态通常表示 Pod 已经完成了它的任务或者已经被删除。 |
Unschedulable | 该子状态表示 Pod 无法被调度到任何节点上。这可能是由于节点资源不足、Pod 的调度要求无法满足、网络或存储问题等原因导致的。 |
CrashLoopBackOff | 该子状态表示容器已经因为某种原因而崩溃,并且 Kubernetes 正在尝试重新启动容器。如果容器在启动后立即崩溃,则可能会导致 CrashLoopBackOff。 |
ImagePullBackOff | 该子状态表示容器镜像无法下载或者容器镜像在下载时发生了错误。这可能是由于镜像名称或标记错误、访问控制问题等原因导致的。 |
PodInitializing | 该子状态表示 Pod 已经被调度到节点上,并且正在启动 Init 容器。Init 容器是在其他容器启动之前运行的容器,它们用于执行初始化任务。 |
VolumePending | 该子状态表示 Pod 中的某些卷正在等待创建或者挂载到节点上。这可能是由于卷的创建或者挂载需要一些时间,或者卷的资源不足导致的。 |
ErrImagePull | 该子状态表示容器镜像无法下载或者容器镜像在下载时发生了错误。这可能是由于镜像名称或标记错误、访问控制问题等原因导致的。 |
ImageInspectError | 该子状态表示 Kubernetes 无法检查容器镜像。这可能是由于镜像名称或标记错误、访问控制问题等原因导致的。 |
CreateContainerConfigError | 子状态表示容器无法被创建,因为容器配置存在问题。这可能是由于容器的配置文件错误或者缺失、容器启动命令错误等原因导致的。 |
CreateContainerError | 该子状态表示容器无法被创建,因为容器运行时存在问题。这可能是由于容器镜像问题、容器与节点的通信问题等原因导致的。 |
PodScheduled | 该子状态表示 Pod 已经被 Kubernetes API 接受,并且已经被调度到了某个节点上 |
Initialized | 该子状态表示 Pod 中的所有 Init 容器都已经成功初始化并且已经退出。 |
Ready | 该子状态表示 Pod 中的所有容器都已经就绪,可以接收网络流量。 |
ContainersReady | 该子状态表示 Pod 中的所有容器都已经启动并且就绪,可以接收网络流量 |
Terminating | 该子状态表示 Pod 正在被删除,其中的容器正在被终止。 |
Pod重启策略
- Pod的重启策略应用于Pod内的所有容器,并且仅在Pod所处的Node上由Kubelet进行判断和重启操作。当某个容器异常退出或者健康检查失败时,kubelet将根据RestartPolicy的设置进行相应的操作。
- Pod的重启策略包括Always,OnFailure,Never;默认值为Always
设置值 | 描述 |
---|---|
Always | 该重启策略表示容器将一直被重启,无论容器是如何终止的。如果容器崩溃、被删除或者因为其他原因被终止,Kubernetes 都将自动重启该容器。 |
OnFailure | 该重启策略表示容器只有在失败时才会被重启。如果容器崩溃、被删除或者因为其他原因被终止,Kubernetes 将自动重启该容器。如果容器自行退出或者正常终止,不会被重启。 |
Never | 该重启策略表示容器只会在 Pod 第一次启动时被启动。如果容器崩溃、被删除或者因为其他原因被终止,Kubernetes 不会自动重启该容器。 |
- 不同资源类型对应的策略
Pod的重启策略与控制方式息息相关,当前可用于管理Pod的控制器 包括ReplicationController、Job、DaemonSet及直接通过kubelet管理(静 态Pod)。每种控制器对Pod的重启策略要求如下:
- RC和DaemonSet:必须设置为Always,需要保证该容器持续运行。
- Job:OnFailure或Never,确保容器执行完成后不再重启。
- kubelet:在Pod失效时自动重启它,不论将RestartPolicy设置为 什么值,也不会对Pod进行健康检查。
- 结合Pod的状态和重启策略,列出一些常见的状态转换场景:
调试Pod
调试 Pod 的第一步是查看 Pod 信息。用如下命令查看 Pod 的当前状态和最近的事件:
kubectl describe pods ${POD_NAME}
查看一下 Pod 中的容器所处的状态。这些容器的状态都是 Running
吗?最近有没有重启过?后面的调试都是要依靠 Pod 的状态的。
Pod 停滞在 Pending 状态
如果一个 Pod 停滞在 Pending
状态,表示 Pod 没有被调度到节点上。通常这是因为 某种类型的资源不足导致无法调度。 查看上面的 kubectl describe ...
命令的输出,其中应该显示了为什么没被调度的原因。 常见原因如下:
- 资源不足: 你可能耗尽了集群上所有的 CPU 或内存。此时,你需要删除 Pod、调整资源请求或者为集群添加节点。 更多信息请参阅计算资源文档
- 使用了
hostPort
: 如果绑定 Pod 到hostPort
,那么能够运行该 Pod 的节点就有限了。 多数情况下,hostPort
是非必要的,而应该采用 Service 对象来暴露 Pod。 如果确实需要使用hostPort
,那么集群中节点的个数就是所能创建的 Pod 的数量上限。
Pod 停滞在 Waiting 状态
如果 Pod 停滞在 Waiting
状态,则表示 Pod 已经被调度到某工作节点,但是无法在该节点上运行。 同样,kubectl describe ...
命令的输出可能很有用。 Waiting
状态的最常见原因是拉取镜像失败。要检查的有三个方面:
- 确保镜像名字拼写正确
- 确保镜像已被推送到镜像仓库
- 尝试手动是否能拉取镜像。例如,如果你在你的 PC 上使用 Docker,请运行
docker pull <镜像>
。
Pod 处于 Crashing 或别的不健康状态
一旦 Pod 被调度,就可以采用 调试运行中的 Pod 中的方法来进一步调试。
Pod 处于 Running 态但是没有正常工作
如果 Pod 行为不符合预期,很可能 Pod 描述(例如你本地机器上的 mypod.yaml
)中有问题, 并且该错误在创建 Pod 时被忽略掉,没有报错。 通常,Pod 的定义中节区嵌套关系错误、字段名字拼错的情况都会引起对应内容被忽略掉。 例如,如果你误将 command
写成 commnd
,Pod 虽然可以创建, 但它不会执行你期望它执行的命令行。
可以做的第一件事是删除你的 Pod,并尝试带有 --validate
选项重新创建。 例如,运行 kubectl apply --validate -f mypod.yaml
。 如果 command
被误拼成 commnd
,你将会看到下面的错误信息:
I0805 10:43:25.129850 46757 schema.go:126] unknown field: commnd
I0805 10:43:25.129973 46757 schema.go:129] this may be a false alarm, see https://github.com/kubernetes/kubernetes/issues/6842
pods/mypod
接下来就要检查的是 API 服务器上的 Pod 与你所期望创建的是否匹配 (例如,你原本使用本机上的一个 YAML 文件来创建 Pod)。 例如,运行 kubectl get pods/mypod -o yaml > mypod-on-apiserver.yaml
, 之后手动比较 mypod.yaml
与从 API 服务器取回的 Pod 描述。 从 API 服务器处获得的 YAML 通常包含一些创建 Pod 所用的 YAML 中不存在的行,这是正常的。 不过,如果如果源文件中有些行在 API 服务器版本中不存在,则意味着 Pod 规约是有问题的。
l` 与从 API 服务器取回的 Pod 描述。 从 API 服务器处获得的 YAML 通常包含一些创建 Pod 所用的 YAML 中不存在的行,这是正常的。 不过,如果如果源文件中有些行在 API 服务器版本中不存在,则意味着 Pod 规约是有问题的。