StatefulSet 设置 restartPolicy: Never 被拒绝:一次性任务需要另选控制器
StatefulSet 拒绝 Never 时,区分长期服务与一次性任务,按 Job 完成和重试规则调整控制器,并保留存储迁移与业务去重条件。
提交 StatefulSet,API 返回 restartPolicy: Unsupported value: "Never": supported values: "Always"。删除 restartPolicy 后能创建,但程序执行结束又被启动。先确认程序是需要持续提供服务,还是完成一次处理后就应该退出;这两种生命周期需要不同的控制器。
StatefulSet 的 Pod 模板只接受 Pod 级 restartPolicy: Always。单独的 Pod 支持 Never,并不代表 StatefulSet 里的同名字段也支持;把它改成 OnFailure 同样不能通过这项校验。以下针对 apps/v1 StatefulSet,以及 batch/v1 的普通 Job。
报错发生在资源校验,程序还没有运行
检查完整错误里的资源 kind 和字段路径,确认是 spec.template.spec.restartPolicy。这个错误与镜像拉取、容器退出码和探针无关,不需要先修改应用镜像或重启 kubelet。
StatefulSet 用于维护一组具有稳定身份的 Pod。它并没有“进程成功退出后永久停止这个副本”的模板模式。Deployment 等长期运行控制器也不能通过在 Pod 模板中设置 Never 来承担批处理任务。
若对象已经存在,在正确命名空间读取实际资源;示例中的 batch、report-worker 是占位值:
kubectl -n batch get statefulset report-worker -o yaml
区分已部署对象与被拒绝的文件。更新失败不会证明旧工作负载已经停止,也不保证旧 Pod 正在使用本次提交的配置。修改 init container 或 sidecar 的单独重启策略,不能绕过 StatefulSet 的这项 Pod 级校验。
长期服务退出,保留 Always 并查退出原因
如果程序本来是数据库、队列消费者或 HTTP 服务,退出后应恢复运行,Always 与其用途一致。需要核对入口命令、退出日志、资源限制和探针,而不是为消除重启把程序换成 Job。
反过来,在一次性程序后面增加 sleep 或 tail 让容器一直活着,也不会使 StatefulSet 具备任务完成状态。它掩盖了程序已经结束,后续更新或 Pod 替换仍可能再跑一次。
一次性任务使用 Job,分别配置完成与重试
Job 会跟踪任务成功完成的次数。其 Pod 模板允许 Never 或 OnFailure:Never 表示同一个 Pod 内的容器终止后不由 kubelet自动重启;OnFailure 允许失败容器在该 Pod 内重跑。Job 控制器是否另建 Pod,还取决于任务失败、重试等配置。
下面是单次批处理的结构示例。镜像地址、命名空间和任务名都必须替换;镜像入口需要真正执行任务、成功返回零、失败返回非零:
apiVersion: batch/v1
kind: Job
metadata:
name: report-once
namespace: batch
spec:
completions: 1
parallelism: 1
backoffLimit: 0
template:
spec:
restartPolicy: Never
containers:
- name: report
image: registry.example.com/team/report:reviewed-tag
backoffLimit: 0 用于不希望普通失败继续重试的方案;它也可能让暂时故障直接变成任务失败,需要人工处理。业务若允许重试,应设计相应次数、错误分类和恢复规则,不能为了不再看到重启一律设成零。
completions: 1、parallelism: 1 和 Never 也不提供业务严格只执行一次的保证,分布式调度仍可能让同一程序被启动多次。写入数据库、发消息或生成账单的任务需要任务标识、幂等或去重机制。已经部分完成后失败的工作,也不能仅凭新 Pod 启动就安全重做。
Job 的模板更新有自己的限制,不是改完镜像再 apply 就一定更新同一个已运行任务。发布下一次处理前,明确使用新的任务对象及任务标识,并检查是否会重复处理之前的数据。
不要把有状态资源直接删掉换种类
StatefulSet 与 Job 的 spec 不相同。不能仅替换 kind,保留 StatefulSet 的 serviceName、volumeClaimTemplates、selector 等配置就当成迁移完成。Job 需要明确挂载什么卷、使用哪些凭据和配置;它不会自动获得旧 StatefulSet 的 Pod 名称、网络身份或存储模板。
迁移前保存原资源配置、日志、任务状态和相关数据备份,确认旧副本不会与新任务同时写同一份数据。卷是否能同时挂载、PVC 的实际名称与保留策略,都需按现有部署核对。不要为了通过校验先删除 PVC,也不要复制旧 Pod 的控制器引用给新资源。
停止旧工作负载会影响服务或中断尚未完成的处理,应在批准的维护流程中协调。若程序依赖固定身份而又要任务式完成状态,需要专门设计这部分交付关系,普通 Job 示例不能代替它。
验证任务完成,而不只是资源被接受
创建后查看 Job 的状态、它实际管理的 Pod、容器退出日志和业务产物。Job 应按目标进入 Complete,失败则按具体退出原因处理;镜像拉取失败、没有创建 Pod或停在 Pending,都不等于任务已经执行一次。
修改配置的回退不会撤销已完成的业务写入。恢复旧 StatefulSet 前先核对新任务是否仍在运行、是否已经提交部分数据,避免一边回退一边再次执行同一个任务。


