kubectl rollout undo回滚本质是切换ReplicaSet而非重装旧配置;默认回滚至上一版本,--to-revision可指定目标;需--record记录变更以支持history追溯;回滚后须验证镜像、RS状态及Pod运行。

回滚 Deployment 用 kubectl rollout undo 最直接
绝大多数场景下,你不需要手写 Go 代码去回滚——Kubernetes 原生就支持通过 kubectl rollout undo deployment/<code> 命令触发回滚,底层调用的是 <code>apps/v1 的 Deployment REST 接口,触发控制器按 revisionHistoryLimit 里保留的旧 ReplicaSet 恢复。
如果你在写自动化运维工具或 CI/CD 插件,才需要在 Go 中调用 client-go 实现。注意:这不是“自己实现回滚逻辑”,而是模拟 kubectl 的行为,向 API Server 提交一个带 rollbackTo 字段的 Patch 请求。
-
kubectl rollout undo默认回滚到上一版本;加--to-revision=2可指定具体 revision - Go 中调用等价操作,必须确保集群启用
apps/v1API 组,且用户权限包含patch权限(deployments资源) - revision 编号不是 Pod 或 ReplicaSet 的 UID,而是 Deployment 的
.metadata.annotations["deployment.kubernetes.io/revision"]值
用 client-go Patch Deployment 触发回滚
client-go 不提供 Rollback() 封装方法,得手动构造 JSON Patch(类型为 application/strategic-merge-patch+json),写入 rollbackTo 字段。这是最常用也最稳妥的方式。
示例关键代码片段:
立即学习“go语言免费学习笔记(深入)”;
patchData := map[string]interface{}{
"spec": map[string]interface{}{
"rollbackTo": map[string]interface{}{
"revision": int64(3),
},
},
}
jsonData, _ := json.Marshal(patchData)
_, err := clientset.AppsV1().Deployments("default").Patch(
context.TODO(),
"my-app",
types.StrategicMergePatchType,
jsonData,
metav1.PatchOptions{},
)
- 必须用
types.StrategicMergePatchType,不能用JSONPatchType,否则报错invalid value: rollbackTo is not allowed in this type -
revision字段只接受整数,传"3"(字符串)会静默失败,API Server 不校验但不生效 - 如果指定的 revision 超出历史范围(比如
revisionHistoryLimit: 5但请求revision: 10),API Server 返回422 Unprocessable Entity错误,需捕获errors.IsInvalid(err)判断
回滚前必须确认 revision 是否存在
Deployment 的 revision 是由控制器在每次更新成功后自增生成的,不会因为手动删 ReplicaSet 而消失,但受 revisionHistoryLimit 限制。想安全回滚,得先查可用 revision 列表。
正确做法是:List 所有该 Deployment 的 ReplicaSet,按创建时间倒序,过滤掉被删除的,再提取 annotation 中的 revision 值:
rsList, _ := clientset.AppsV1().ReplicaSets("default").List(context.TODO(), metav1.ListOptions{
LabelSelector: "app=my-app", // 必须匹配 Deployment selector
})
var revisions []int64
for _, rs := range rsList.Items {
if revStr, ok := rs.Annotations["deployment.kubernetes.io/revision"]; ok {
if rev, err := strconv.ParseInt(revStr, 10, 64); err == nil {
revisions = append(revisions, rev)
}
}
}
sort.Sort(sort.Reverse(sort.Int64Slice(revisions)))
- 不能只依赖
deployment.status.conditions或status.observedGeneration判断是否可回滚 - LabelSelector 必须和 Deployment 的
.spec.selector.matchLabels完全一致,否则漏掉旧 ReplicaSet - 已缩容到 0 的 ReplicaSet 仍算有效历史,只要没被 GC 清理,就可用于回滚
StatefulSet 和 DaemonSet 不支持原生 rollback
kubectl rollout undo 对 StatefulSet 和 DaemonSet 会报错 rollout undo is not supported for StatefulSet,client-go 同样无法通过 Patch rollbackTo 回滚——因为这两个资源类型压根没定义该字段。
- StatefulSet 需手动 Patch
.spec.template回退到上一版 PodTemplate,并触发滚动更新(靠revision字段变化触发) - DaemonSet 同理,但要注意:回滚时若节点数多,可能因并发度限制导致部分节点延迟更新
- 没有通用“回滚”语义,意味着你要自己维护模板快照(比如存 ConfigMap 或 Git Tag),否则 Go 程序无法凭空还原旧配置
ResourceVersion 匹配),但多数运维场景没必要。


















