Skip to content

06 故障修复记录

2026-08-14 GitLab 19.2.2 首次部署故障修复

背景

在 RKE2 集群(192.168.122.31)上用官方 Helm Chart 10.2.2 部署 GitLab CE 19.2.2 高可用实例时,遇到三个主要问题:

  1. PostgreSQL 版本不兼容 — GitLab 19.x 要求 PG >= 17,原配置使用 PG 16
  2. ConfigMap 挂载失败 — RKE2/containerd 环境下 init 容器无法在 /etc/ 创建挂载点(只读文件系统)
  3. Helm extraEnv 补丁冲突extraEnv 中重复键触发 strategic merge patch 冲突

故障一:PostgreSQL 版本不兼容

现象

  • gitlab-migrations Job 反复 CrashLoopBackOff
  • 日志报错:ActiveRecord::StatementInvalid: PG::UndefinedTable 或 PG 版本检查失败
  • GitLab 19.x 明确要求 PostgreSQL >= 17

原因

  • deploy/deps/10-postgres.yaml 中镜像为 postgres:16-alpine
  • scripts/sync-images.sh 中同步的也是 postgres:16-alpine

修复步骤

bash
# 1. 同步 PG 17 镜像到 Harbor
skopeo copy --dest-tls-verify=false \
  --dest-creds 'admin:xxx' \
  docker://docker.m.daocloud.io/library/postgres:17-alpine \
  docker://192.168.122.156:30000/gitlab/postgres:17-alpine

# 2. 删除旧 PG Deployment 和 PVC
kubectl -n gitlab delete deploy postgres
kubectl -n gitlab delete pvc postgres-data

# 3. 更新 deploy/deps/10-postgres.yaml
#    image: 192.168.122.156:30000/gitlab/postgres:17-alpine

# 4. 重新部署 PG
kubectl apply -f deploy/deps/10-postgres.yaml

# 5. 等待 PG 就绪(首次 initdb 约 2-5 分钟)
kubectl -n gitlab wait --for=condition=ready pod -l app=postgres --timeout=300s

# 6. 验证版本
kubectl -n gitlab exec deploy/postgres -- psql -U gitlab -c "SELECT version()"
# PostgreSQL 17.11 on x86_64-pc-linux-musl ...

# 7. 更新 scripts/sync-images.sh 中的镜像版本
#    "$DAO/library/postgres:17-alpine"

文件变更

  • deploy/deps/10-postgres.yaml:注释 PG 16 → PG 17,镜像 postgres:17-alpine
  • scripts/sync-images.shpostgres:16-alpinepostgres:17-alpine

故障二:ConfigMap 挂载到 /etc/ 失败(只读文件系统)

现象

  • gitlab-webservice-defaultgitlab-sidekiq-all-in-1-v2 的 dependencies init 容器反复 Init:Error
  • 日志:mount: /etc/gitlab-templates-override: permission deniedread-only file system
  • 原因:RKE2/containerd 运行环境下,容器的 /etc/ 目录属于只读 rootfs overlay

尝试过的方案

方案结果
subPath 单文件挂到 /var/opt/gitlab/templates/gitlab.yml.erbdependencies init 容器中该路径非目录,失败
extraVolumes 整目录挂到 /etc/gitlab/init 容器无法在只读 rootfs 创建挂载点
挂载到 /etc/gitlab-templates-override同上,/etc/ 下任何新路径都失败

最终方案:将挂载路径改为 /opt/gitlab-templates-override

yaml
# deploy/gitlab/values.yaml
gitlab:
  webservice:
    extraVolumes: |
      - name: templates-override
        configMap:
          name: gitlab-templates-override
    extraVolumeMounts: |
      - name: templates-override
        mountPath: /opt/gitlab-templates-override
        readOnly: true

原因分析

  • containerd 运行时为容器创建了只读 rootfs overlay,/etc//usr/ 等系统目录不可写
  • init 容器需要在挂载点创建临时目录,只读文件系统阻止了此操作
  • /opt/ 不在受限路径列表中,init 容器可正常创建挂载点

文件变更

  • deploy/gitlab/30-gitlab-yml-override-cm.yaml
    • CM 名称从 gitlab-gitlab-yml-override 改为 gitlab-templates-override
    • 包含所有 9 个模板文件(cable.yml.erb, configure, gitlab.yml.erb 等)
    • 注释说明挂载路径限制
  • deploy/gitlab/values.yaml
    • extraVolumes/extraVolumeMounts 路径改为 /opt/gitlab-templates-override

故障三:Helm extraEnv strategic merge patch 冲突

现象

  • helm upgrade 报错:failed to create patch: unable to find list key
  • 错误信息指向 extraEnv 中的 CONFIG_TEMPLATE_DIRECTORY
  • 原因:values.yaml 中的 extraEnv 与 chart 内部定义的 extraEnv 合并时,Kubernetes strategic merge patch 发现重复键

尝试过的方案

方案结果
values 中设 extraEnv 注入 CONFIG_TEMPLATE_DIRECTORYstrategic merge patch 冲突
使用 --set 传入 env同样冲突
删掉 extraEnv,改 subPath 单文件init 容器路径非目录问题

最终方案:Helm post-renderer

编写 Python 脚本(scripts/post-render.py),在 Helm 渲染完成后,直接将 gitlab-templates-override CM 中的 gitlab.yml.erb(含 port: 9020)替换到 gitlab-webservice CM 中。

bash
# scripts/post-render.sh
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
OVERRIDE="$SCRIPT_DIR/../deploy/gitlab/30-gitlab-yml-override-cm.yaml"
exec python3 "$SCRIPT_DIR/post-render.py" "$OVERRIDE"
python
# scripts/post-render.py(核心逻辑)
# 1. 读取 override CM 中的 gitlab.yml.erb
# 2. 读取 helm 渲染输出(stdin)
# 3. 找到 gitlab-webservice ConfigMap,替换 gitlab.yml.erb 内容
# 4. 输出修改后的 YAML(stdout)

使用方式

bash
helm upgrade gitlab oci://192.168.122.156:30000/charts/gitlab --version 10.2.2 --plain-http \
  -n gitlab -f deploy/gitlab/values.yaml \
  --post-renderer ./scripts/post-render.sh \
  --timeout 15m

文件变更

  • 新建 scripts/post-render.sh
  • 新建 scripts/post-render.py

附带问题:Helm Release 卡住 & API Server 不可达

Helm Release 卡在 pending-install/upgrade

bash
# 查看状态
helm list -a -n gitlab

# 清理卡住的 release(删最新失败的 revision secret)
kubectl -n gitlab get secret -l owner=helm -o name | sort -V | tail -5
kubectl -n gitlab delete secret sh.helm.release.v1.gitlab.v<N>

# 同时清理可能残留的资源
kubectl -n gitlab delete job -l app=gitlab,component=migrations --force --grace-period=0

API Server 短暂不可达(192.168.122.31:6443):

bash
# 临时切换到其他 CP 节点的 kubeconfig
export KUBECONFIG=/tmp/config-122.23
# 或从其他 CP 节点拷贝 kubeconfig
scp 192.168.122.23:/etc/rancher/rke2/rke2.yaml /tmp/config-122.23
sed -i 's/127.0.0.1/192.168.122.23/' /tmp/config-122.23

最终部署验证

bash
# 1. 检查所有 Pod 状态
kubectl -n gitlab get pods
# 期望:webservice×2, sidekiq×2, shell×2, praefect×2, gitaly×3, postgres, redis, minio 全 Running

# 2. 检查 migrations 进度
kubectl -n gitlab logs -l component=migrations --tail=20
# 期望:Running db:schema:load rake task(首次约 15-30 分钟)

# 3. 监控 PG 活动(schema 加载期间)
kubectl -n gitlab exec deploy/postgres -- psql -U gitlab -d gitlabhq_production -c \
  "SELECT left(query,50) FROM pg_stat_activity WHERE state='active' AND query LIKE 'CREATE%'"

# 4. 验证 Web UI
curl -s http://192.168.122.31:30080/users/sign_in | grep -o '<title>[^<]*'
# Sign in · GitLab

# 5. 获取 root 密码
kubectl -n gitlab get secret gitlab-initial-root-password -o jsonpath='{.data.password}' | base64 -d; echo

修改文件汇总

文件变更
deploy/deps/10-postgres.yamlPG 16 → PG 17(镜像 tag + 注释)
scripts/sync-images.shpostgres:16-alpinepostgres:17-alpine
deploy/gitlab/30-gitlab-yml-override-cm.yamlCM 名称改为 gitlab-templates-override;含全部 9 个模板文件;注释挂载路径限制
deploy/gitlab/values.yamlextraVolumes 路径改为 /opt/gitlab-templates-override;移除 extraEnv
scripts/post-render.sh新建 — Helm post-renderer shell 入口
scripts/post-render.py新建 — 替换 webservice CM 中 gitlab.yml.erb