主题
06 故障修复记录
2026-08-14 GitLab 19.2.2 首次部署故障修复
背景
在 RKE2 集群(192.168.122.31)上用官方 Helm Chart 10.2.2 部署 GitLab CE 19.2.2 高可用实例时,遇到三个主要问题:
- PostgreSQL 版本不兼容 — GitLab 19.x 要求 PG >= 17,原配置使用 PG 16
- ConfigMap 挂载失败 — RKE2/containerd 环境下 init 容器无法在
/etc/创建挂载点(只读文件系统) - Helm extraEnv 补丁冲突 —
extraEnv中重复键触发 strategic merge patch 冲突
故障一:PostgreSQL 版本不兼容
现象:
gitlab-migrationsJob 反复 CrashLoopBackOff- 日志报错:
ActiveRecord::StatementInvalid: PG::UndefinedTable或 PG 版本检查失败 - GitLab 19.x 明确要求
PostgreSQL >= 17
原因:
deploy/deps/10-postgres.yaml中镜像为postgres:16-alpinescripts/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-alpinescripts/sync-images.sh:postgres:16-alpine→postgres:17-alpine
故障二:ConfigMap 挂载到 /etc/ 失败(只读文件系统)
现象:
gitlab-webservice-default和gitlab-sidekiq-all-in-1-v2的 dependencies init 容器反复Init:Error- 日志:
mount: /etc/gitlab-templates-override: permission denied或read-only file system - 原因:RKE2/containerd 运行环境下,容器的
/etc/目录属于只读 rootfs overlay
尝试过的方案:
| 方案 | 结果 |
|---|---|
subPath 单文件挂到 /var/opt/gitlab/templates/gitlab.yml.erb | dependencies 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 等)
- 注释说明挂载路径限制
- CM 名称从
deploy/gitlab/values.yaml:- extraVolumes/extraVolumeMounts 路径改为
/opt/gitlab-templates-override
- extraVolumes/extraVolumeMounts 路径改为
故障三: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_DIRECTORY | strategic 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=0API 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.yaml | PG 16 → PG 17(镜像 tag + 注释) |
scripts/sync-images.sh | postgres:16-alpine → postgres:17-alpine |
deploy/gitlab/30-gitlab-yml-override-cm.yaml | CM 名称改为 gitlab-templates-override;含全部 9 个模板文件;注释挂载路径限制 |
deploy/gitlab/values.yaml | extraVolumes 路径改为 /opt/gitlab-templates-override;移除 extraEnv |
scripts/post-render.sh | 新建 — Helm post-renderer shell 入口 |
scripts/post-render.py | 新建 — 替换 webservice CM 中 gitlab.yml.erb |