kubectl rollout undo 是最短回滚路径,但必须每次更新时加 --record=true 才能准确定位版本;否则 revision 无上下文,回滚成盲操作,且需验证镜像 digest 可达性、RS 切换与 Pod 就绪状态。

回滚命令本身很简单,但前提全在更新时埋点
直接执行 kubectl rollout undo deployment/myapp 是最短路径,但它**只在你每次更新都加了 --record=true 时才真正可用**。不加这个参数,kubectl rollout history deployment/myapp 里看到的 CHANGE-CAUSE 全是 <none>,revision 号虽有,但无法确认哪次对应哪个镜像——回滚就变成盲操作。
常见错误现象:kubectl rollout undo 返回 “rolled back”,但新 Pod 卡在 ImagePullBackOff 或 CrashLoopBackOff,因为回滚拉的是同名 tag(比如 v1.2),而该 tag 已被 CI 重新推送覆盖,实际拉到的是另一个 digest。
- 必须在每次
kubectl apply -f deploy.yaml或kubectl set image时显式加--record=true - 等价写法:在 Deployment YAML 的
spec.template.metadata.annotations里手动加kubectl.kubernetes.io/last-applied-configuration和自定义变更说明 -
--record只记录命令文本,不保证镜像未被删;生产环境应配合镜像 digest 使用(如myapp@sha256:abc123)
revision 编号不是“第几次更新”,而是 RS 的创建顺序
Deployment 回滚本质是把流量切回到某个历史 ReplicaSet(RS),每个 RS 锁定了当时的完整 Pod 模板(含镜像、env、labels)。revision 编号就是 Kubernetes 给每个 RS 分配的整数 ID,从 1 开始递增,但它会因非镜像变更而跳变:比如你只改了 replicas: 3 → 4 或更新了一个 ConfigMap 挂载,也会生成新 RS 并增加 revision 号。
这意味着:--to-revision=3 不一定对应“第三个镜像版本”,可能只是第三次任意变更。如果你没保留足够旧的 RS,它还可能已被 GC 清理掉(默认 revisionHistoryLimit: 10)。
立即学习“go语言免费学习笔记(深入)”;
- 查真实可用 revision:
kubectl get rs -l app=myapp -o wide,看哪些 RS 的DESIRED> 0 且 annotation 里有deployment.kubernetes.io/revision - 验证目标 RS 是否还存活着:
kubectl get rs myapp-7d8c9b4f56 -o jsonpath='{.metadata.annotations."deployment\.kubernetes\.io/revision}' - 调整保留策略:在 Deployment YAML 中设
spec.revisionHistoryLimit: 20,避免关键版本被自动清理
用 Go 客户端调 Rollback() 才算真回滚
如果你需要可审计、幂等、绕过 kubectl 命令行限制的回滚(比如集成进 CI/CD 或告警自动响应),必须用 Go clientset 调 Kubernetes 原生 /rollback endpoint,而不是 patch 或 update Deployment 的 image 字段。
误用 Update() 或 Patch() 会导致新 rollout 触发,revision 加一,旧版本 RS 可能被挤出历史,彻底失去回滚能力。
- 正确调用:
clientset.AppsV1().Deployments("myns").Rollback(ctx, "myapp", &appsv1.RollbackConfig{ Name: "myapp", Revision: 3, UpdatedAnnotations: map[string]string{} }, metav1.UpdateOptions{}) -
Revision必须是int64类型,不能是字符串;值得从 RS annotation 实时读取,不能硬编码或递推 - 查 revision 的逻辑:List 所有 RS → 过滤
ownerReferences匹配目标 Deployment → 提取deployment.kubernetes.io/revisionannotation → 转int64→ 按数值降序排 → 取第二个(即上一版)
回滚成功 ≠ 服务恢复,必须验证三件事
无论用 kubectl 还是 Go 客户端,API 层返回成功只代表 rollback 请求已提交,Pod 状态切换、就绪探针通过、流量接入都是后续异步过程。跳过验证,等于没回滚。
- 确认镜像已切回:
kubectl get deploy myapp -o jsonpath='{.spec.template.spec.containers[0].image}' - 确认 RS 切换完成:
kubectl get rs -l app=myapp,目标 revision 的 RS 的CURRENT应上升,当前 revision 的 RS 的CURRENT应归零 - 确认 Pod 就绪:
kubectl get pods -l app=myapp -o wide,新启动的 Pod AGE 要小、STATUS 为Running、READY 为1/1,且无Events报错
最容易被忽略的是:旧镜像是否还在 Registry 可拉取。回滚前没验证 digest 可达性,回滚后所有 Pod 启动失败,反而扩大故障面。


















