“清单已勾选”不等于“系统可上线”。一份有效的 Kubernetes 上线清单,必须同时写清检查对象、执行方法、通过标准、失败动作和证据保存位置。
本文以一个运行在 prod 命名空间、由 Deployment 管理的无状态 HTTP API 为例。示例变量需要替换成实际值,并先在非生产环境验证。数据库迁移、消息消费、定时任务和有状态工作负载还需要增加各自的专项检查。
使用方式:先建立发布上下文
开始前固定本次发布对象,避免后续命令误查其他环境:
1 | export NS=prod |
在变更单或流水线中记录:
| 字段 | 示例 | 作用 |
|---|---|---|
| 需求或缺陷编号 | REQ-1842 |
串联代码、镜像和发布记录 |
| Git 提交 | 完整 commit SHA | 确认构建源代码 |
| 镜像 | 仓库地址加 digest | 保证实际运行内容不可变 |
| 目标环境 | 集群、命名空间、工作负载 | 防止操作错环境 |
| 观察窗口 | 发布后 30 分钟 | 明确何时才能宣布完成 |
| 回滚目标 | 上一镜像 digest | 避免故障时临时寻找版本 |
| 停止条件 | 错误率、延迟、不可用副本阈值 | 让回滚决策可执行 |
下面 20 项不是平均用力。核心交易链路、外部入口和包含数据变更的服务,应设置更严格的门槛。
一、变更、制品与配置
1. 变更范围和依赖已经说明
上线前必须知道“改了什么”,也要知道“没有改什么”。至少列出 API、配置、数据库、消息格式、定时任务、Ingress、Service 和下游依赖的变化。
通过标准: 需求、提交、镜像和部署对象可以相互追溯;高风险变化有负责人、验证步骤和停止条件;共享基础设施明确归属,不在应用发布中顺手重建。
1 | git show --stat --oneline HEAD |
如果本次只更新应用镜像,就不要同时修改平台团队维护的 Ingress、证书或集群级策略。发布范围越小,失败定位和回滚越可靠。
2. 镜像使用不可变 digest
latest、stable 或普通版本标签都可能被重新指向。Deployment 应保存镜像 digest,标签只用于方便人阅读。
1 | image: registry.example.com/team/order-api@sha256:<64-hex-digest> |
通过标准: digest 对应本次 Git 提交;镜像已经完成漏洞、恶意软件和敏感信息扫描;基础镜像来源可追溯;生产 Deployment 不依赖可变标签。
1 | kubectl -n "$NS" get deployment "$APP" \ |
镜像扫描结果要保留在制品或流水线记录中。发现高危漏洞时,应根据是否可利用、是否暴露和是否存在补丁作出可审计决策,而不是只看漏洞数量。
3. 清单通过服务端校验,并审阅真实差异
本地 YAML 能解析,不代表 API Server 接受,也不代表 Admission Policy 会放行。先做服务端 dry-run,再查看差异:
1 | kubectl apply --server-side --dry-run=server -f "$MANIFEST_DIR" |
kubectl diff 在“存在差异”时通常返回退出码 1,流水线需要区分“有预期差异”和“命令执行失败”:
1 | set +e |
通过标准: dry-run 成功;diff 只有本次批准的字段;没有意外删除对象、修改 selector、替换 Service ClusterIP 或覆盖平台托管资源。
4. 配置与 Secret 已校验
检查必填键、值格式、环境差异和引用对象是否存在。Secret 的 base64 只是编码,不是加密;不要把明文或解码结果打印进 CI 日志。
1 | kubectl -n "$NS" get configmap "${APP}-config" -o name |
通过标准: 配置有 schema 或启动校验;Secret 来自受控系统并有轮换方案;Pod 只读取所需 Secret;配置变化能触发受控滚动更新,例如使用带内容哈希的 ConfigMap 名称。
不要在同一个 ConfigMap 名称下静默替换关键配置,又期待所有 Pod 同时生效。明确配置版本,才能复现和回滚。
5. 数据库和消息契约向前、向后兼容
Deployment 回滚只能恢复应用镜像,不能自动撤销已经执行的数据库迁移或已发布的消息。推荐使用“扩展—迁移—收缩”:
- 先增加新字段、表或兼容消费逻辑;
- 部署能同时理解新旧结构的应用;
- 回填数据并验证;
- 所有旧版本退出观察窗口后,再删除旧字段。
通过标准: 新旧版本可在滚动期间共存;迁移可重复执行或能识别已完成状态;大表变更评估锁等待和耗时;消息消费者能处理版本差异;失败后有恢复而不只是 rollout undo。
二、资源、容量与调度
6. requests 与 limits 来自观测数据
调度器主要依据 requests 放置 Pod;内存超过 limit 可能触发 OOM,CPU limit 可能带来节流。不要机械套用固定比例。
1 | kubectl -n "$NS" get deployment "$APP" \ |
通过标准: 每个业务容器都有 requests;内存 limit 留有峰值和运行时开销;CPU 策略经过压测;命名空间 ResourceQuota 和节点可分配资源能容纳滚动发布时的额外副本。
建议同时看过去 7~30 天的 P50、P95、峰值和 OOM/节流指标。只看某一时刻的 kubectl top 容易低估批处理、促销和缓存重建峰值。
7. 副本数和扩缩容策略覆盖故障场景
需要高可用的服务通常不能只运行一个副本。使用 HPA 时,目标利用率依赖资源 requests,缺失 requests 会让部分指标无法正确计算。
1 | kubectl -n "$NS" get deployment "$APP" \ |
通过标准: 单个 Pod 或单个节点失效后仍能维持最低容量;HPA 的最小、最大副本和稳定窗口有压测依据;节点池能在扩容时间内提供资源;下游连接池不会因副本增加被打满。
8. 副本跨故障域分布
多个副本落在同一节点,不能抵御节点故障。优先使用拓扑分布约束表达节点或可用区分布:
1 | topologySpreadConstraints: |
1 | kubectl -n "$NS" get pod -l "app=$APP" \ |
通过标准: labelSelector 与 Pod 标签一致;故障域标签在节点上真实存在;约束不会在节点不足时让全部新 Pod Pending;关键副本不会集中到单节点。
9. PDB 与维护目标一致
PodDisruptionBudget 约束通过 Eviction API 发起的自愿中断,例如部分节点维护;它不能阻止节点宕机,也不直接控制 Deployment 的滚动更新。
1 | apiVersion: policy/v1 |
通过标准: PDB selector 能选中目标 Pod;副本数允许满足 minAvailable;节点排空不会永久卡住;维护手册说明何时允许临时调整 PDB,且调整需要审批。
1 | kubectl -n "$NS" get pdb "$APP" |
三、生命周期与流量
10. startup、readiness、liveness 语义分离
startupProbe保护启动较慢的应用,成功前不会执行其他两类探针;readinessProbe决定 Pod 是否进入 Service 后端;livenessProbe只处理进程无法自行恢复的状态,失败会触发重启。
1 | startupProbe: |
通过标准: 最坏启动时间小于 startup 窗口; readiness 能快速摘除不可服务实例;liveness 不依赖易抖动的外部数据库,不会在高负载时制造级联重启;探针端点轻量且不记录噪声日志。
11. SIGTERM 和在途请求可以优雅结束
Pod 终止时,应用应停止接收新请求、等待在途请求完成、提交或终止后台任务,然后在宽限期内退出。
1 | terminationGracePeriodSeconds: 30 |
通过标准: 应用正确处理 SIGTERM;关停超时大于常见请求耗时;消息消费者先停止拉取再处理已获取消息;长连接有关闭策略;强制终止不会留下重复写入或悬挂锁。
可以在非生产环境执行一次真实终止演练,并同时观察客户端错误、Pod Events 和应用日志。仅看到 Pod 最终消失,不足以证明优雅退出成功。
12. 滚动策略与集群余量匹配
1 | strategy: |
通过标准: maxUnavailable 满足可用性目标;maxSurge 所需额外 CPU、内存、IP 和下游连接均有余量;minReadySeconds 能挡住“刚 Ready 就失败”的实例;进度超时符合真实启动时间。
对于三个副本的关键 API,maxUnavailable: 0、maxSurge: 1 是一个常见起点,不是通用答案。容量紧张时,应先扩容节点或分阶段发布,而不是为了让 rollout 继续而降低可用门槛。
13. Service selector、端口与 EndpointSlice 一致
1 | kubectl -n "$NS" get service "$APP" -o wide |
通过标准: Service selector 选中预期 Pod;targetPort 对应容器端口名称或端口;EndpointSlice 至少包含期望数量的 Ready 地址;从集群内访问 Service 能得到业务级正确响应。
不要只请求 /livez。至少执行一个不会产生副作用的核心读取或契约检查,确认路由、中间件和依赖装配正常。
14. Ingress、TLS、DNS 和入口所有权清晰
1 | kubectl -n "$NS" get ingress -o wide |
通过标准: Host、Path 和后端 Service 正确;证书域名与有效期满足要求;HTTP 到 HTTPS 策略符合预期;入口控制器有可用副本;从真实访问网络完成 Host、TLS 和内容验证。
如果 Ingress 由平台团队或独立仓库管理,应用流水线只能读取和验证,不能重复 apply。共享入口的无意覆盖,影响范围通常远大于单个应用。
四、安全边界
15. 容器遵循最小权限
1 | securityContext: |
通过标准: 不使用 privileged、hostPID、hostNetwork 或不必要的 hostPath;容器以非 root 用户运行;默认丢弃 Linux capabilities;根文件系统只读;确需写入的目录通过受控卷提供。
安全设置需要在镜像和非生产环境先验证。若应用依赖向根目录写缓存,应修正路径或挂载专用临时目录,而不是直接取消所有限制。
16. ServiceAccount 和 RBAC 只授予必要动作
不访问 Kubernetes API 的业务 Pod 通常可以关闭令牌自动挂载:
1 | automountServiceAccountToken: false |
需要访问 API 时,使用独立 ServiceAccount 和命名空间级 Role,避免复用默认账号或授予 cluster-admin。
1 | kubectl auth can-i --as="system:serviceaccount:${NS}:${APP}" get configmaps -n "$NS" |
通过标准: 第二条检查应返回 no;权限清单与代码真实调用匹配;部署账号与运行时账号分离;临时提权有到期时间和审计记录。
17. NetworkPolicy 已验证为“实际生效”
NetworkPolicy 是否生效取决于集群网络插件。仅创建对象,不代表数据面一定执行了策略。
通过标准: 默认拒绝策略与业务放行策略配套;入口只允许 Ingress Controller 或明确调用方;出口只允许 DNS、数据库和必要外部 API;在测试命名空间分别验证允许与拒绝路径。
1 | kubectl -n "$NS" get networkpolicy |
上线前不要直接在生产一次性启用严格 egress。先从流量观测得到真实依赖,补齐 DNS、时间同步、遥测出口和第三方回调,再在隔离环境验证。
五、观测、恢复与发布责任
18. 指标、日志和追踪能回答“是否变差”
最低观测面包括:
- 流量:请求数、吞吐、队列长度;
- 错误:5xx、业务失败、依赖错误、超时;
- 延迟:P50、P95、P99,并按路由或用例分组;
- 饱和度:CPU 节流、内存、连接池、线程或协程、磁盘和网络;
- Kubernetes:不可用副本、Pending、重启、OOMKilled、探针失败和 Events。
通过标准: 新版本、Pod、节点和请求 ID 能关联;仪表盘在发布前可访问;关键告警已经路由到当班人员;发布开始前保存同一时间窗口的基线。
19. 回滚与数据恢复已经演练
1 | kubectl -n "$NS" rollout history deployment/"$APP" |
发生异常时,先停止继续放量并保存证据。若变更只有兼容的应用镜像,可以回到上一 digest;若包含数据库、缓存结构或消息副作用,按专项恢复方案处理。
通过标准: 上一镜像仍可拉取;配置和 Secret 版本可恢复;备份完成过实际恢复验证;回滚命令、负责人和权限已确认;明确哪些变化不能通过 Deployment 回滚解决。
20. 发布门禁、观察窗口和交接完整
发布不是 kubectl apply 返回零就结束。建议把发布划分为四个状态:
1 | 待发布 → 发布中 → 观察中 → 已完成 |
通过标准: 变更单包含开始与结束时间、操作者、审批人、命令退出码、rollout 结果、镜像 digest、指标截图或查询链接、异常记录和最终结论;观察窗口结束前不宣布完成;跨班次发布有明确交接人。
建议至少设置以下停止条件:
- 新 Pod 在进度截止时间内无法全部 Available;
- 错误率超过基线和预设阈值;
- P95/P99 延迟持续恶化;
- OOM、重启或探针失败持续增加;
- 核心业务校验失败;
- 数据迁移或下游依赖出现不可恢复错误。
一份可复用的 Deployment 基线
下面的片段把多项检查放在一起。它是起点,不是可直接复制到所有服务的模板:
1 | apiVersion: apps/v1 |
示例没有设置 CPU limit,是为了强调“按压测和集群策略决定”,不是建议所有服务都取消 CPU limit。资源、探针、宽限期和副本数必须用真实负载验证。
发布当天的执行顺序
发布前
1 | kubectl config current-context |
保存当前 Deployment、镜像 digest、Available 副本和业务指标基线。确认回滚目标仍可从镜像仓库拉取。
发布中
通过受控流水线应用清单,不建议个人终端临时拼接补丁。并行观察:
1 | kubectl -n "$NS" rollout status deployment/"$APP" --timeout=10m |
get pod -w 和 Events 是辅助证据,最终仍要回到业务错误率、延迟和核心校验。
发布后
1 | kubectl -n "$NS" get deployment "$APP" \ |
从集群内、Ingress 内网入口和真实用户路径分别验证。至少覆盖一个成功用例、一个预期失败用例、认证、关键依赖和不会产生副作用的读请求。
自动化门禁的分层
| 阶段 | 建议自动化内容 | 失败处理 |
|---|---|---|
| 提交检查 | YAML/schema、策略、镜像扫描 | 阻止合并 |
| 环境预检 | 服务端 dry-run、diff、容量和依赖检查 | 阻止发布 |
| 滚动发布 | rollout、Available 副本、Events | 停止继续放量 |
| 业务校验 | API 契约、只读核心用例、入口访问 | 自动回滚或人工判定 |
| 观察窗口 | 错误率、延迟、饱和度、业务指标 | 触发停止条件 |
自动回滚只适用于“失败信号可靠且回滚动作安全”的场景。数据迁移、消息副作用和外部写入通常需要人工确认,不应被一个模糊的 5xx 峰值直接触发破坏性动作。
小结
Kubernetes 上线检查的核心不是记住 20 个对象,而是把一次发布变成可验证、可停止、可恢复的工程流程:镜像能追溯,差异可审阅,容量有依据,探针有语义,权限和网络有边界,指标能判断是否退化,回滚不依赖临场记忆。
第一次落地时,不必追求一次自动化全部项目。先把 20 项写进变更模板,再逐步把可确定的检查搬进 CI;保留需要业务判断的审批点,并持续用事故与演练结果修订阈值。
一手资料
- Kubernetes:Deployments
- Kubernetes:配置存活、就绪和启动探针
- Kubernetes:容器资源管理
- Kubernetes:Pod 拓扑分布约束
- Kubernetes:Disruptions 与 PDB
- Kubernetes:Pod Security Standards
- Kubernetes:NetworkPolicy
- Kubernetes:Ingress
资料复核日期:2026-08-22。示例中的命名空间、标签、资源、超时、镜像和策略均为占位基线,实施前应以目标集群版本、网络插件、Admission Policy 和业务压测结果为准。
评论