如何为 Helm 发布启用“post-upgrade”钩子重建索引?

解读

在国内金融、运营商、政务云等落地场景中,CouchDB 常以 Helm Chart 形式部署在国产化 K8s 发行版(如统信、麒麟、华为 CCE、阿里 ACK)上。
升级 Chart 时,镜像版本或视图定义可能变更,导致旧索引失效;若不及时重建,查询会返回陈旧数据甚至触发 500 错误,直接影响业务合规审计。
因此,面试官想确认候选人是否能把 CouchDB 的索引重建动作与 Helm 的生命周期钩子结合,做到“升级即重建、失败即回滚、对运维透明”。

知识点

  1. Helm 钩子权重:权重越小越先执行;post-upgrade 在资源更新完成后触发。
  2. CouchDB 索引本质:每个设计文档下的 views 字段在首次查询时才同步生成 B+ 树索引;可通过 PUT /{db}/_design/{ddoc}/_view/{view}?update=true 强制重建。
  3. 国产化环境限制:
    • 镜像仓库多为内网 Harbor,需使用 imagePullSecret
    • 安全策略默认禁止 privileged: true,因此钩子 Job 必须非特权运行;
    • 审计要求日志落盘,钩子输出要重定向到 /proc/1/fd/1kubectl logs 收集。
  4. 幂等性:同一版本重复升级不能重复重建,否则大表场景会打满 IO;可用 ConfigMap 记录“已重建”标记,或利用 Helm {{ .Release.Revision }} 作为标注。
  5. 失败策略:helm upgrade --wait 会等待钩子 Job 完成;若重建失败,Job 的 restartPolicy=Never 结合 backoffLimit=0 可让 Helm 立即标记升级为失败,触发自动回滚

答案

  1. 在 CouchDB Helm Chart 的 templates/ 目录新增 post-upgrade-reindex-job.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: "{{ .Release.Name }}-reindex-{{ .Release.Revision }}"
  annotations:
    "helm.sh/hook": post-upgrade
    "helm.sh/hook-weight": "10"
    "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
spec:
  template:
    metadata:
      labels:
        app.kubernetes.io/managed-by: {{ .Release.Service }}
        couchdb.io/reindex-rev: "{{ .Release.Revision }}"   # 幂等关键
    spec:
      restartPolicy: Never
      backoffLimit: 0
      containers:
      - name: reindex
        image: {{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag }}
        command:
        - /bin/bash
        - -c
        - |
          set -euo pipefail
          echo "[$$] 开始重建索引"
          for db in $(curl -sS -u "${COUCHDB_USER}:${COUCHDB_PASSWORD}" http://couchdb:5984/_all_dbs | jq -r '.[]'); do
            for ddoc in $(curl -sS -u "${COUCHDB_USER}:${COUCHDB_PASSWORD}" http://couchdb:5984/${db}/_all_docs?startkey=\"_design/\"&endkey=\"_design0\" | jq -r '.rows[].id'); do
              echo "[$$] 强制重建 ${db}/${ddoc}"
              curl -sS -u "${COUCHDB_USER}:${COUCHDB_PASSWORD}" -X GET \
                "http://couchdb:5984/${db}/${ddoc}/_view/by_any?update=true&limit=1" > /dev/null
            done
          done
          echo "[$$] 重建完成"
        env:
        - name: COUCHDB_USER
          valueFrom:
            secretKeyRef:
              name: {{ .Release.Name }}-couchdb
              key: adminUsername
        - name: COUCHDB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: {{ .Release.Name }}-couchdb
              key: adminPassword
        resources:
          requests:
            cpu: 200m
            memory: 256Mi
          limits:
            cpu: 1000m
            memory: 1Gi
  1. 升级命令:
helm upgrade couchdb ./couchdb \
  --namespace couchdb \
  --wait --timeout 15m \
  --set image.tag=3.3.3-alpine
  1. 验证:
kubectl logs -n couchdb job/couchdb-reindex-5
helm status couchdb -n couchdb

若 Job 失败,Helm 自动回滚到上一版本,确保数据一致性

拓展思考

  1. 大集群表级别灰度:
    把钩子拆成CronJob,按业务优先级分批重建;结合CouchDB 分片stable=false 参数,避免一次性打满磁盘。
  2. 国产化信创适配:
    若 CPU 为鲲鹏 920,需将镜像编译为 linux/arm64;在 values.yaml 中提供 nodeSelector: {kubernetes.io/arch: arm64},防止调度到 x86 节点。
  3. 零信任安全:
    使用服务网格(如华为 ASM)对钩子 Job 与 CouchDB 之间的 5984 端口做 mTLS 加密,并在 AuthorizationPolicy 中限定仅允许 post-upgrade ServiceAccount 访问。
  4. 可观测性:
    在钩子容器内安装 couchdb-exporter,把重建耗时写入 Prometheus,通过夜莺或阿里云 ARMS配置告警规则:索引重建时间超过 5 分钟即@值班群。