bigywater.tech
Kubernetes · 52

rollout 历史与回滚:revision 存在哪里

`kubectl rollout history` 的历史存在哪?`rollout undo` 到底做了什么?revisionHistoryLimit 删掉历史后会怎样?这篇用 ReplicaSet 的 revision 注解把这几个问题都实测清楚。

revision 2 → 5
rollout undo --to-revision=2 之后,revision 2 的 ReplicaSet 被重新启用并改成的最新 revision 号
3 个 ReplicaSet
revisionHistoryLimit=2、改了 5 次后保留的 ReplicaSet 数(当前 + 最近 2 个旧的)
2 次修改 → 1 次发布
rollout pause 期间连改两次、resume 之后只产生的新 ReplicaSet 数

历史就是 ReplicaSet

实测 · 本机执行输出
  4 个版本之后的 ReplicaSet(revision, 名字后缀, replicas, env V):(1, '9864d', 0, 'v1'); (2, '667b7', 0, 'v2'); (3, '9d5bb', 0, 'v3'); (4, 'cb5f7', 2, 'v4')
  kubectl rollout history:
    deployment.apps/app
    REVISION  CHANGE-CAUSE
    1         <none>
    2         <none>
    3         <none>
    4         <none>
  kubectl rollout history --revision=2(那一版的 Pod 模板):deployment.apps/app with revision #2 | Image:	busybox:1.36 | Environment: | V:	v2

每改一次 Pod 模板,Deployment 就多一个 ReplicaSet,deployment.kubernetes.io/revision 注解记着它的版本号;旧的缩到 replicas=0 但保留。改了 4 次(v1 到 v4)后有 4 个 ReplicaSet,kubectl rollout history 列出 REVISION 1~4(CHANGE-CAUSE 都是 <none>),--revision=2 能看到那一版的模板内容。

undo 不是倒退

实测 · 本机执行输出
  kubectl rollout undo --to-revision=2:deployment.apps/app rolled back(另外 kubectl 打印了一条 Warning:这个 Deployment 是用 kubectl apply 管理的,undo 不会更新 last-applied 注解,之后再 apply 要小心)
  之后的 ReplicaSet:(1, '9864d', 0, 'v1'); (3, '9d5bb', 0, 'v3'); (4, 'cb5f7', 0, 'v4'); (5, '667b7', 2, 'v2')
  (revision 2 的 ReplicaSet 被重新启用并改成了最新的 revision 5,而不是新建;当前运行的 env=v2)
  不带 --to-revision 再 undo 一次:回到上一个版本;ReplicaSet:(1, '9864d', 0, 'v1'); (3, '9d5bb', 0, 'v3'); (5, '667b7', 0, 'v2'); (6, 'cb5f7', 2, 'v4')

rollout undo --to-revision=2:revision 2 的 ReplicaSet(后缀 667b7)被重新启用,编号改成最新的 5,而不是新建一个;1、3、4 保留。不带 --to-revision 再 undo 一次,回到“上一个版本”(v4,编号变成 6)。revision 号只增不减。注意 kubectl 的提示:如果 Deployment 是用 kubectl apply 管理的,undo 不会更新 last-applied-configuration,之后再 apply 旧 YAML 可能和实际不一致。

revisionHistoryLimit

实测 · 本机执行输出
  revisionHistoryLimit=2 改了 5 次之后的 ReplicaSet:(4, 'cb5f7', 0, 'v4'); (5, '945fb', 0, 'v5'); (6, 'f6475', 2, 'v6')(当前这个加最近 2 个旧的,更早的被删掉了)
  想回滚到已经被删掉的 revision 1:退出码 1;error: unable to find specified revision 1 in history

默认保留 10 个旧版本。设成 2、改了 5 次之后,只剩 revision 4、5、6 三个 ReplicaSet(当前加最近 2 个旧的),更早的被删掉:rollout undo --to-revision=1 报 unable to find specified revision 1 in history。想回滚得多远,就把它设多大。

change-cause 与 pause

实测 · 本机执行输出
  写了 kubernetes.io/change-cause 注解之后的 rollout history:
    deployment.apps/app
    REVISION  CHANGE-CAUSE
    1         初始版本 v1
    2         升级到 v2
  rollout pause 之后连续改了两次模板(env V=v3、再加 EXTRA=1):ReplicaSet 仍是 2 个,Pod 没动:(1, '9864d', 0, 'v1'); (2, '667b7', 2, 'v2')
  rollout resume 之后:3 个 ReplicaSet,两次修改合成了一次发布:(1, '9864d', 0, 'v1'); (2, '667b7', 0, 'v2'); (3, '65c9b', 2, 'v3')

给 Deployment 加注解 kubernetes.io/change-cause,会显示在 rollout history 的 CHANGE-CAUSE 列(“初始版本 v1”“升级到 v2”),这是现在唯一能给历史写说明的办法。rollout pause 之后连续改两次模板,ReplicaSet 数量不变、Pod 不动;rollout resume 后只多了一个 ReplicaSet,把两次修改合成了一次发布。

分步演示

发布历史
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / kind(Docker 里的单节点或多节点真实集群,节点是 Docker Desktop 虚拟机里的容器)/ kubectl;用空的 kubeconfig 之外的独立 kubeconfig,不碰用户自己的集群;计时用 date +%s%N / kubectl 事件时间戳,数字每次运行会有小幅抖动。三节点 kind 集群 kx-main(Kubernetes v1.37.0);Deployment app 2 个副本,busybox:1.36,环境变量 V 用来改变 Pod 模板(用 kubectl apply 修改);每次修改后等 updatedReplicas、readyReplicas、replicas 都等于 2 再继续;ReplicaSet 的版本取自注解 deployment.kubernetes.io/revision;每种情形各一次(ReplicaSet 名字后缀每次运行不同)
    • 没有验证:revisionHistoryLimit 为 0;回滚期间的 maxSurge 与 maxUnavailable;kubectl rollout status 的输出;Deployment 删除时 ReplicaSet 的级联(见垃圾回收一篇);对 StatefulSet、DaemonSet 的 rollout history(它们用的是 ControllerRevision 对象);kubectl set image 与 --record(已废弃)
    京ICP备2026067502号-1京公网安备11010502063487号