文章目录
-
- [一. 三种重启策略详解](#一. 三种重启策略详解)
-
- [1.1. `Always`(默认值)](#1.1.
Always(默认值)) - [1.2. `OnFailure`](#1.2.
OnFailure) - [1.3. `Never`](#1.3.
Never)
- [1.1. `Always`(默认值)](#1.1.
- [二. 重启策略与控制器的关系](#二. 重启策略与控制器的关系)
- [三. 重启背后的机制:指数退避(Back-off)](#三. 重启背后的机制:指数退避(Back-off))
- [四. 常见误区澄清](#四. 常见误区澄清)
-
- [4.1. `livenessProbe`(存活探针)失败会导致重启吗?](#4.1.
livenessProbe(存活探针)失败会导致重启吗?) - [4.2. `readinessProbe`(就绪探针)失败会导致重启吗?](#4.2.
readinessProbe(就绪探针)失败会导致重启吗?) - [4.3. 节点重启后,Pod 会重启吗?](#4.3. 节点重启后,Pod 会重启吗?)
- [4.4. 如何查看容器的重启次数?](#4.4. 如何查看容器的重启次数?)
- [4.1. `livenessProbe`(存活探针)失败会导致重启吗?](#4.1.
- [五. 最佳实践建议](#五. 最佳实践建议)
-
- [5.1. 长期服务用 `Always`](#5.1. 长期服务用
Always) - [5.2. 批处理任务用 `OnFailure` + `backoffLimit`](#5.2. 批处理任务用
OnFailure+backoffLimit) - [5.3. 避免在 Pod 中处理复杂重启逻辑](#5.3. 避免在 Pod 中处理复杂重启逻辑)
- [5.4. 调试时使用 `Never`](#5.4. 调试时使用
Never) - [5.5. 总结](#5.5. 总结)
- [5.1. 长期服务用 `Always`](#5.1. 长期服务用
在 Kubernetes (K8s) 中, 重启策略(Restart Policy) 是决定当 Pod 中的容器终止(退出)时,Kubelet 应该如何处理该 Pod 的核心机制。与 Docker 不同,K8s 的重启策略是定义在 Pod 级别 ( .spec.restartPolicy),而不是单个容器级别。这意味着 Pod 中的所有容器共享同一个重启策略。
一. 三种重启策略详解
Kubernetes 支持以下三种重启策略:
1.1. Always(默认值)
- 行为 :无论容器因何种原因退出(正常退出代码 0 或异常退出代码非 0),Kubelet 都会自动重启该容器。
- 适用控制器 :
Deployment,StatefulSet,DaemonSet,ReplicaSet。 - 场景:长期运行的服务(如 Web 服务器、数据库、API 网关)。只要节点还在,服务就应该一直在线。
- 注意 :如果手动执行
kubectl delete pod,Pod 会被删除且不会重启(因为控制器会创建一个新的 Pod 来替代它,而不是重启旧的)。
1.2. OnFailure
- 行为 :只有当容器以非零状态码 (即发生错误/崩溃)退出时,Kubelet 才会重启容器。如果容器正常退出(状态码为 0),则不会重启。
- 适用控制器 :
Job,CronJob。 - 场景:批处理任务、数据迁移脚本、一次性计算任务。如果任务成功完成(exit 0),就不需要再跑了;如果失败了,则需要重试。
1.3. Never
- 行为 :无论容器因何种原因退出,Kubelet 永远不会 重启该容器。Pod 的状态将变为
Completed(正常退出)或Failed(异常退出)。 - 适用控制器 :
Job(某些特定场景)。 - 场景:调试任务、只需要运行一次且不在乎结果的任务、或者由外部系统监控并手动重启的任务。
二. 重启策略与控制器的关系
并非所有控制器都支持所有重启策略。K8s 会根据控制器类型强制校验:
| 控制器类型 | 支持的 RestartPolicy | 说明 |
|---|---|---|
| Deployment | Always |
必须始终运行,保证服务可用性。 |
| StatefulSet | Always |
同上,有状态服务需持续运行。 |
| DaemonSet | Always |
每个节点上的守护进程需持续运行。 |
| Job | OnFailure, Never |
任务完成后应结束,失败时可重试。 |
| CronJob | OnFailure, Never |
同 Job,由定时触发。 |
❌ 错误示例 :如果你在 Deployment 的 YAML 中设置
restartPolicy: OnFailure,K8s API Server 会直接拒绝创建,报错:Unsupported value: "OnFailure": supported values: "Always"。
三. 重启背后的机制:指数退避(Back-off)
为了防止容器因代码 Bug 导致"启动-崩溃-重启"的死循环(CrashLoopBackOff),Kubelet 采用了指数退避算法:
- 第一次重启:等待 10 秒。
- 第二次重启:等待 20 秒。
- 第三次重启:等待 40 秒。
- ...
- 最大等待时间 :上限通常为 5 分钟(300 秒)。
状态变化流程:
Running -> Error/Crash -> CrashLoopBackOff (等待中) -> Running (重试)
你可以在 kubectl describe pod <pod-name> 中看到 Last State 和 Reason: CrashLoopBackOff。
四. 常见误区澄清
4.1. livenessProbe(存活探针)失败会导致重启吗?
是的。
如果 livenessProbe 检查失败,Kubelet 会杀死 容器。然后,根据 restartPolicy:
- 如果是
Always或OnFailure(且退出码非0),容器会被重启。 - 如果是
Never,容器死后不再复活。
4.2. readinessProbe(就绪探针)失败会导致重启吗?
不会。
readinessProbe 失败只会将 Pod 从 Service 的 Endpoint 列表中移除(停止流量进入),但不会杀死或重启容器。
4.3. 节点重启后,Pod 会重启吗?
- 如果 Pod 是由控制器(如 Deployment)管理的,控制器会发现 Pod 缺失,并调度一个新的 Pod 到可用节点上。
- 这不属于"重启策略"的范畴,而是控制器的**期望状态协调(Reconciliation)**机制。
4.4. 如何查看容器的重启次数?
bash
kubectl get pods
# 输出示例:
# NAME READY STATUS RESTARTS AGE
# my-app-7d9f6b8c5-x2z9a 1/1 Running 3 10m
RESTARTS 列显示的数字就是该 Pod 历史上被重启的次数。
bash
kubectl describe pod <pod-name>
# 在 Containers 部分查看:
# Last State: Terminated
# Reason: Error
# Exit Code: 1
# Started: ...
# Finished: ...
# Ready: True
# Restart Count: 3
五. 最佳实践建议
5.1. 长期服务用 Always
对于 Web 应用、微服务,始终使用 Always。配合 livenessProbe 可以自动恢复死锁或僵死的进程。
5.2. 批处理任务用 OnFailure + backoffLimit
对于 Job,设置 restartPolicy: OnFailure,并在 Job spec 中设置 backoffLimit: 4(默认6次),防止无限重试浪费资源。
5.3. 避免在 Pod 中处理复杂重启逻辑
不要在应用代码里写 while true 来防止退出。让 K8s 管理生命周期,应用应该设计为"无状态"或"可快速启动"。
5.4. 调试时使用 Never
如果容器一启动就崩溃,你可以临时将策略改为 Never,这样容器死后会保留现场,你可以进入容器或通过日志排查问题,而不会被不断重启打断。
5.5. 总结
| 策略 | 何时重启 | 典型用途 | 控制器支持 |
|---|---|---|---|
| Always | 任何退出 | 长期服务 | Deployment, StatefulSet, DaemonSet |
| OnFailure | 仅异常退出 | 批处理/任务 | Job, CronJob |
| Never | 从不重启 | 调试/一次性 | Job |