在 kind 集群里复现 Helm 渲染失败、资源冲突和 hook 超时,练习判断 release 状态

演练目标

环境准备

隔离边界:只在独立 kind 集群中操作,不要对任何真实集群执行 helm install/uninstall/rollback。先确认 context,再创建集群。

kubectl config current-context
kind create cluster --name lab-helm
rm -rf /tmp/lab-helm && helm create /tmp/lab-helm/chart

增加两个模板:一个强制校验 image.tag,一个可选的 pre-install hook。

cat > /tmp/lab-helm/chart/templates/required.yaml <<'EOF'
apiVersion: v1
kind: ConfigMap
metadata: {name: lab-required}
data: {tag: '{{ required "image.tag 必填" .Values.image.tag }}'}
EOF
cat > /tmp/lab-helm/chart/templates/hook-job.yaml <<'EOF'
{{- if .Values.hookEnabled }}
apiVersion: batch/v1
kind: Job
metadata:
  name: lab-hook-job
  annotations:
    "helm.sh/hook": pre-install
spec:
  template:
    spec: {restartPolicy: Never, containers: [{name: hook, image: "busybox:1.36", command: ["sleep", "600"]}]}
{{- end }}
EOF

注入故障

渲染失败:不传 image.tag,required 会在提交 API 前报错。

helm install lab-render /tmp/lab-helm/chart -n lab-render --create-namespace --set image.tag= --timeout 30s

资源冲突:先手工创建同名 Deployment,再让 Helm 安装同名资源。

kubectl create namespace lab-conflict && kubectl -n lab-conflict create deployment lab-app --image=nginx:1.27-alpine
helm install lab-conflict /tmp/lab-helm/chart -n lab-conflict --set image.tag=1.27-alpine --set fullnameOverride=lab-app --timeout 60s

hook 卡住:Job 睡眠 600 秒,Helm 等到 timeout 后失败。

helm install lab-hook /tmp/lab-helm/chart -n lab-hook --create-namespace --set image.tag=1.27-alpine --set hookEnabled=true --timeout 20s > /tmp/lab-helm/hook.log 2>&1 & sleep 5
helm list -n lab-hook --all
wait || true
helm list -n lab-hook --all

观察现象

helm list -A --all
helm status lab-conflict -n lab-conflict
helm get manifest lab-conflict -n lab-conflict | grep -A6 'kind: Deployment'
kubectl -n lab-hook get jobs,pods; tail -3 /tmp/lab-helm/hook.log

预期 lab-render 不在 release 列表里,安装阶段就报 execution error ... image.tag 必填。lab-conflict 状态为 failed,错误包含 invalid ownership metadata,但 helm get manifest 仍能看到 Deployment lab-app。lab-hook 第一次查询为 pending-install,超时后变成 failed,Job lab-hook-job 和 Pod 仍在运行。

判断与定位

  1. 先写假设:模板渲染失败、API 拒绝、资源所有权不符、hook 未完成,还是等待超时;渲染失败可用 helm template 在本地复现。
  2. 资源冲突要看 invalid ownership metadata 和资源的 app.kubernetes.io/managed-by、meta.helm.sh/release-name 标签/注解,而不是只看“已存在”。
  3. hook 卡住时 release 先进入 pending-install,超时后变 failed;hook 资源不在 release manifest 中,helm uninstall 不保证删除它们,必须单独检查 Job/Pod。
  4. 容易误判:failed 不代表没有创建任何资源。失败的安装可能已创建部分对象,也可能把同名对象写进 release manifest;执行 helm uninstall 前先用 helm get manifest 核对删除集合。另一个误判是对首次安装失败的 release 执行 helm rollback,它没有可回滚的成功 revision。

修复

渲染失败:补上合法 tag 后重新安装,预期 Pod 进入 Running:

helm install lab-render /tmp/lab-helm/chart -n lab-render --set image.tag=1.27-alpine --wait --timeout=120s

资源冲突:在干净 namespace 中安装,或先确认同名资源归属再决定是否加入 release。hook 场景先 uninstall,再清理残留 Job:

helm uninstall lab-hook -n lab-hook || true
kubectl -n lab-hook get jobs
kubectl -n lab-hook delete job lab-hook-job --ignore-not-found

回滚验证:先安装正常版本,再升级到不存在的镜像,让 --wait 超时,最后回滚。

helm install lab-ok /tmp/lab-helm/chart -n lab-rollback --create-namespace --set image.tag=1.27-alpine --wait --timeout=120s
helm upgrade lab-ok /tmp/lab-helm/chart -n lab-rollback --set image.tag=no-such-tag --wait --timeout=45s || true
helm history lab-ok -n lab-rollback && helm rollback lab-ok 1 -n lab-rollback --wait --timeout=120s

helm history 应显示 revision 1 deployed、revision 2 failed,rollback 后 revision 3 deployed,Pod 恢复 Running。生产环境应结合 --atomic、--wait 和 CI 中的 helm diff 控制变更。

清理与回滚

for r in lab-render lab-conflict lab-hook; do helm uninstall "$r" -n "$r" 2>/dev/null || true; done
helm uninstall lab-ok -n lab-rollback 2>/dev/null || true
kubectl delete namespace lab-render lab-conflict lab-hook lab-rollback --ignore-not-found
kind delete cluster --name lab-helm && rm -rf /tmp/lab-helm

只删除本实验的 kind 集群和 namespace;不要对真实集群执行 helm uninstall,除非已经核对 release 归属。

复盘

延伸阅读

读完自测

  1. helm install 报渲染错误时,集群里会留下资源吗?
  2. 为什么 helm uninstall 不一定能清理 pre-install hook 创建的 Job?
  3. release 第一次安装就失败,为什么 helm rollback 无法恢复?
答案
  1. 不会;渲染失败发生在提交 API 之前,通常不会创建任何集群资源。
  2. hook 资源不在 release manifest 中,卸载不会跟踪它们,需要按名称或标签单独清理。
  3. 没有成功的 revision 可回滚;应修复失败原因后重新安装或升级,而不是 rollback 到失败版本。