install upgrade rollback
这一课你将能做到
- 对本地 Chart 执行
helm install / upgrade / upgrade --install / uninstall,并用 helm list、helm history、helm get values/manifest 读出 Release 状态与 revision
- 解释并演示
--wait、--atomic、--timeout 在失败升级时的行为差异,演练一次「失败自动回滚」
- 设计「按命名空间分环境」或「按 Release 名分环境」的布局,说出各自取舍,并与 GitOps 的 Application 命名对齐
为什么要学
Chart 能 template 只说明渲染对了;真正落地靠 Release 生命周期:install 创建、upgrade 推进、history 可审计、rollback 可回退、uninstall 可拆除。它与 kubectl 的 rollout undo 相关但粒度不同——Helm 以 整个 Release 的 revision 为单位,一次回滚恢复整组清单,而不只是单个 Deployment。GitOps 时代这条链没有作废:Argo CD/Flux 底层做的正是受控的 upgrade,你今天在 CLI 上理解的 revision、wait、atomic,明天就能直接读懂控制器日志与回滚策略。本课全部命令基于上一课的 backend Chart,真实可运行。
先建立图像
helm install → revision 1(创建 Release,落一组资源)
helm upgrade → revision 2、3…(每次成功升级递增)
helm history → 各 revision 的状态/描述/生效时间
helm rollback → 指回旧 revision(注意:是【新增】一个 revision,不删历史)
helm uninstall → 删除 Release 与其管理的资源
| 旗标 | 人话 | 适用场景 |
|---|
--wait | 等资源真正就绪才返回成功 | 要求「命令成功=Pod Ready」 |
--timeout | 等待上限(超时报失败) | 与 --wait 联用 |
--atomic | 升级失败自动回滚到上一 revision | 生产 upgrade 标配 |
--create-namespace | 目标命名空间不存在则先创建 | 首次部署 |
-f / --set | 环境参数 | 与 helm-templates 课的优先级一致 |
同一 Chart、两套环境的隔离方式(择一为主):
A) 分命名空间:-n dev / -n prod,Release 名可同为 backend
B) 分 Release 名:backend-dev / backend-prod(仍建议同时分 ns)
跟着做
步骤 1:首次安装
Chart 位于 ./coderoadmap-backend,values 文件已就绪:
helm install backend ./coderoadmap-backend \
-n coderoadmap-dev --create-namespace \
-f values-dev.yaml
helm list -n coderoadmap-dev
kubectl get deploy,svc -n coderoadmap-dev
应看到 STATUS: deployed;资源名前缀与 Release 名 backend 一致(来自 fullname helper)。
步骤 2:查看生效配置与清单
helm get values backend -n coderoadmap-dev # 用户覆盖值
helm get values backend -n coderoadmap-dev --all # 含默认值的完整计算结果
helm get manifest backend -n coderoadmap-dev # 当时渲染出的完整清单
helm get notes backend -n coderoadmap-dev # NOTES.txt 内容
核对 tag、副本数是否与 values-dev 一致。get manifest 是「集群里这组资源到底是谁部署的、长什么样」的权威快照,排障第一现场。
步骤 3:升级镜像 tag
helm upgrade backend ./coderoadmap-backend \
-n coderoadmap-dev \
-f values-dev.yaml \
--set image.tag=1.0.1 \
--wait --timeout 5m --atomic
helm history backend -n coderoadmap-dev
命令会阻塞到 Deployment 就绪;镜像变了触发滚动更新,Helm 额外记了一条 revision 2。注意 upgrade 要求 Release 已存在,首次部署报错就改用下面的幂等写法。
步骤 4:掌握幂等安装 upgrade --install
# 存在则升级、不存在则安装——脚本与 CI 里的标准姿势
helm upgrade --install backend ./coderoadmap-backend \
-n coderoadmap-dev --create-namespace \
-f values-dev.yaml --wait --timeout 5m --atomic
这一条覆盖「第一次装」和「第 N 次升」两种情况,避免脚本里写 if/else 判断。
步骤 5:读 history 并回滚
helm history backend -n coderoadmap-dev
# 假设要回到 revision 1 的内容
helm rollback backend 1 -n coderoadmap-dev
helm history backend -n coderoadmap-dev
观察:rollback 新增了 revision 4(内容等价于 revision 1),历史记录一条不删——history 是审计轨迹,不是栈。对照记忆:kubectl rollout undo 只回退单个 Deployment;helm rollback 恢复该 Release 当时的整组清单(含 Service/ConfigMap)。
步骤 6:演练失败升级(学习环境)
helm upgrade backend ./coderoadmap-backend \
-n coderoadmap-dev \
-f values-dev.yaml \
--set image.tag=does-not-exist-xyz \
--wait --timeout 2m --atomic || echo "EXPECTED FAILURE"
helm history backend -n coderoadmap-dev # 该 revision 状态为 failed,随后被回滚
kubectl get pods -n coderoadmap-dev # 回到升级前版本
不加 --atomic 时失败的半套资源会残留,需手动 helm rollback——这就是生产强制 atomic 的理由。
步骤 7:规划多环境命名
| 方案 | 示例 | 优点 | 注意 |
|---|
| 分命名空间 | -n coderoadmap-dev / -n coderoadmap-prod | 隔离清晰、RBAC/配额好做 | 需管理 ns 生命周期 |
| 分 Release 名 | backend-dev / backend-prod | 同集群 UI 一屏对比 | 名字长了易拼错 |
生产常见是 两者叠加:既分 ns 又分 values 文件,Release 名保持简短稳定,方便与后面 Argo CD 的 Application 名(backend-dev)一一对齐。
讲清楚要点
- 因为 Release 是命名实例,所以同 Chart 多次安装必须靠不同 Release 名或不同命名空间区分——同名同 ns 再 install 会直接报错,这不是 bug 是保护。
- 因为每次 upgrade 产生 revision,所以回滚有据可查——先
history 再 rollback,禁止凭记忆盲回。
- 因为默认 upgrade 在资源未就绪时也可能返回成功,所以关键路径必须加
--wait --timeout——把「命令成功」与「业务就绪」对齐,否则 CI 绿了 Pod 还在 ImagePullBackOff。
- 因为失败的升级可能残留半套资源,所以生产 upgrade 常加
--atomic——失败自动回到上一可用 revision;--atomic 隐含 --wait。
- 因为 Helm 回滚粒度是整份 Release manifest,所以 Chart 内无关资源也会一起回退——这决定了 Chart 边界要克制:一个 Chart 只管一个应用的一组紧耦合资源。
- 因为 GitOps 控制器底层同样在做 upgrade,所以 CLI 阶段练的 history/atomic 概念全部可迁移——差别只在「谁触发、真相源在哪」,gitops-intro 课展开。
你可能会懵的地方
-
rollback 到 1 之后,revision 2、3 还在吗?
在。rollback 是追加新 revision(内容指向旧版),历史不删——审计链完整,你能随时再次前滚。
-
--set 与 -f 同时用谁赢?
--set 优先级最高(覆盖任何 -f 文件)。短期试验无所谓,长期必须把结果写回 values 文件,否则「集群状态靠某人 shell 历史维持」。
-
uninstall 会删 PVC 吗?
Helm 默认不删它未声明的资源,但 PVC 删除行为取决于 Chart 的资源策略注解与 Helm 版本旗标。删有状态组件前先读 Chart 文档、先备份,学习环境先在空 ns 试验。
-
和裸 kubectl apply 混用会怎样?
手改集群字段后,下一次 upgrade/GitOps 同步可能覆盖你的改动或行为怪异。约定:要么 Helm/GitOps 管这个应用,要么裸 apply 管,绝不让两套工具抢同一组资源。
-
helm upgrade --install 能完全替代 helm install 吗?
实操上可以,且脚本更简单。需要精细区分「首次安装事件」(如触发安装后 hook)时再单独用 install。
错法对照
| 错法 | 问题 | 正解 |
|---|
upgrade 从不加 --wait | CI 显示成功但 Pod 未就绪 | --wait --timeout 标配 |
| 失败升级无 atomic,残留坏版本 | 服务半残、二次升级混乱 | --atomic 或立即手动 rollback |
| 用 kubectl edit 改副本「临时救火」 | 与下轮 upgrade/GitOps 冲突 | 改 values 再 upgrade/sync |
| dev/prod 同名 Release 同 ns 硬装 | 冲突或误覆盖 | 分 ns 或分 Release 名 |
| 把 rollback 理解成「删除历史」 | 预期错乱 | 记住 rollback 新增 revision |
升级时不带原 -f 文件 | 环境参数被重置为默认 | 每次 upgrade 重传全部 values 文件 |
卡点急救
- 现象:
Error: UPGRADE FAILED: another operation (install/upgrade/rollback) is in progress——上一次操作异常中断留下了 pending 状态;helm history 找到 pending 的 revision,执行 helm rollback <release> <上一个成功revision> 清理,再重试升级。
- 现象:upgrade 后配置「丢了」(副本数、tag 回到默认)——upgrade 没有记忆功能,你漏传了
-f 文件;养成固定脚本/Makefile 封装命令的习惯,每次都完整传参。
- 现象:
--wait 超时但 Pod 其实正常——常见于探针路径配错或 timeout 太短;先 kubectl get pods 确认真实状态,修 values 里 probes.*,或把 --timeout 调到覆盖冷启动(如 5m)。
面试常问
-
Helm upgrade 的 revision 机制是什么?如何回滚?
每次成功 install/upgrade/rollback 都会递增 Release 的 revision,Helm 把渲染后的 manifest 与 values 存为集群内 Secret(sh.helm.release.v1.<release>.v<N>)。helm history 列出全部 revision,helm rollback <release> <rev> 通过重放目标 revision 的 manifest 实现回滚,并再次生成新 revision——历史不可变、审计完整。
-
--wait、--atomic、--timeout 的关系?
--wait 让命令阻塞到资源就绪(默认只需创建成功),--timeout 设定等待上限,--atomic 在超时/失败时自动回滚到上一 revision 并隐含 --wait。生产标准组合是三者全开:把「命令返回成功」等价于「服务可用」。
-
Helm rollback 与 kubectl rollout undo 的区别?
粒度与范围不同:rollout undo 只回退单个 Deployment 的 Pod 模板历史;helm rollback 恢复整个 Release 当时的全部清单(Deployment、Service、ConfigMap、Secret 引用等),并记录为一条新 revision。前者适合单资源微调回退,后者是整组交付物的版本管理。
自测三问
helm rollback backend 1 之后 helm history 会多出什么?与 kubectl rollout undo 粒度差在哪?
--wait 与 --atomic 分别消除哪种恐惧?只用其中一个够吗?
- dev/prod 部署同一 Chart,你选分命名空间还是分 Release 名?与 GitOps 的 Application 命名如何对齐?
小结一句话
Release 生命周期 = install → upgrade(记 revision)→ rollback/uninstall;用 upgrade --install 幂等化、用 --wait --timeout --atomic 把命令成功对齐服务可用——这套概念直接通向 GitOps 同步。
延伸