--atomic 与 --wait 实际在做什么
一句话总结
--wait 表示“等待所有资源就绪”,--atomic 表示“如果无法全部就绪,就回滚”。不使用它们,失败的部署也会被报告为成功。
为什么需要这些选项
helm upgrade 默认只把清单发送给 API 服务器,随后立即返回成功,并不检查 Pod 是否真的启动。即使镜像标签写错并出现 ImagePullBackOff,helm 也会输出 STATUS: deployed。CI 日志显示绿色,只有用户遭遇故障。
加入 --wait 后,helm 会轮询 Deployment、StatefulSet 与 DaemonSet 的就绪状态。如果在 --timeout(默认 5 分钟)内没有就绪,就按失败处理,CI 终于会显示红色。
但如果只停留在失败状态,问题仍然存在:新修订已经创建,资源也只更新了一半。--atomic 会在此时自动运行 helm rollback,恢复到先前状态。--atomic 内含 --wait——如果不等待,就根本无法得知部署失败。
它是如何工作的
helm upgrade demo ./chart \
--atomic \
--timeout 5m \
--history-max 10
这一行应该成为部署脚本的基本形式。timeout 应设置为启动最慢的 Pod 所需时间,再加上余量。太短会回滚正常部署,太长则会延迟发现故障。
常见误解
误以为有 --atomic 就万事安全。 atomic 只能回滚 Kubernetes 资源。如果由 hook 运行的迁移 Job 已经修改了数据库,数据库不会自动恢复。因此,模式变更必须拆分为前后版本都能承受的步骤部署:扩展 → 部署 → 清理。
误以为增加 timeout 就能解决问题。 ImagePullBackOff 不会因为等待而恢复。30 分钟的 timeout 只会让故障晚 30 分钟被发现。
发布卡在 pending 状态时
部署在中途终止后,发布可能停留在 pending-upgrade 或 pending-install 状态。
此时,下一次部署会被如下错误拒绝。
Error: another operation (install/upgrade/rollback) is in progress
Helm 3 把发布状态保存在命名空间的 Secret 中,却没有单独的锁, 因此“正在进行”的标记会原样残留。进程已经退出,只剩标记还在。
按下面的顺序解除。
helm history demo # 1) 마지막 리비전의 상태를 본다
helm rollback demo <직전 성공 리비전> # 2) 대개 이걸로 풀린다
# 롤백도 거절되면 마지막 수단 — 갇힌 리비전의 Secret 을 지운다
kubectl -n <ns> get secret -l owner=helm,name=demo
kubectl -n <ns> delete secret sh.helm.release.v1.demo.v<갇힌 번호>
最后一种方法会删除该修订的历史记录,无法恢复。删除之前,应使用
helm get manifest demo --revision <n> 保存其内容。
回滚无法恢复的内容
helm rollback 会恢复发布清单,清单以外的内容则保持不变。
| 会恢复 | 不会恢复 |
|---|---|
| Deployment、Service、ConfigMap 的 spec | hook 执行的数据库迁移 |
| 镜像标签、环境变量、replicas | PVC 中的数据 |
| 资源请求与限制 | 发送给其他系统的事件与通知 |
| 已删除资源原先保存的状态 |
尤其要注意最后一行。如果从 Chart 中移除某个资源并部署,Helm 会删除它。 回滚后,资源虽然会重新创建,其中的内容却是全新的。暂时移除 StatefulSet 再回滚,就是一条可能导致数据丢失的路径。
部署流水线的基本形式
helm upgrade --install demo ./chart -f values/prod.yaml --set image.tag="$GIT_SHA" --atomic --timeout 5m --history-max 10 --wait-for-jobs
# helm 이 초록불을 준 뒤에 바깥에서 확인한다
curl -fsS --retry 5 --retry-delay 3 https://demo.example.com/healthz
人们经常漏掉 --wait-for-jobs。--wait 会等待 Deployment 与 StatefulSet,
却不会等待 Job。迁移 Job 尚未结束,新 Pod 就开始接收流量的事故由此发生。
实际工作中真正重要的事
--wait 检查的是工作负载的就绪状态,而不是“服务是否正常”。即使 Pod 已经 Ready,响应也可能是 500。因此,部署流水线的最后一步必须始终包含一次从外部发起的冒烟测试。helm 显示绿色与用户真正能够使用服务,是两个不同的命题。