Ceph+K8s 中间件实战 | 第 13 天:K8s 部署 GitLab 代码托管平台(Ceph RBD 持久化 + 架构 + 巡检)

第 13/15 天

引言:为什么在 K8s 上部署 GitLab?

GitLab 是企业级代码托管与 DevOps 平台,集成了 Git 仓库管理、CI/CD 流水线、Issue 跟踪、容器仓库等功能。在云原生时代,将 GitLab 部署到 Kubernetes 集群上,可以实现弹性伸缩、滚动升级和统一运维。

K8s Logo

然而,GitLab 是一个典型的”有状态重负载”应用——Git 仓库数据、PostgreSQL 数据库、Redis 缓存都需要持久化存储。当 K8s 接入 Ceph 分布式存储后,Ceph RBD 块存储为 GitLab 提供了高可靠、高性能的持久化卷方案。本篇将使用 GitLab 官方 Helm Chart 完成 GitLab 在 K8s 上的完整部署,所有持久化存储统一挂载到 Ceph RBD StorageClass。

一、设计架构

1.1 组件拓扑

GitLab 是一个由多个微服务组成的复合应用,官方 Helm Chart 将其拆分为以下核心组件:

组件 功能说明 存储需求 副本数
Webservice Rails 主应用(Puma),处理 HTTP 请求 无状态(共享存储) 2+
Workhorse 反向代理,处理大文件上传/Git Smart HTTP 无状态 2+
Sidekiq 后台任务处理(邮件、Pipeline 等) 无状态 2+
Gitaly Git 仓库存储服务(核心数据层) Ceph RBD 持久卷 按分片
PostgreSQL 元数据数据库(用户、项目、权限) Ceph RBD 持久卷 1(主)
Redis 缓存与会话存储 Ceph RBD 持久卷 1
MinIO 对象存储(制品、上传文件、LFS) Ceph RBD 持久卷 1
Nginx Ingress 入口流量路由与 TLS 终止 无状态 2+
Runner CI/CD 执行器(可选) 无状态 按需
Prometheus 内置监控采集 Ceph RBD 持久卷 1

1.2 数据流向

💻 代码示例

用户请求 → Nginx Ingress (TLS终止) → Workhorse → Webservice (Puma/Rails)

↓

Gitaly ←→ Ceph RBD (Git仓库数据)

↓

PostgreSQL ←→ Ceph RBD (元数据)

↓

Redis ←→ Ceph RBD (缓存)

↓

MinIO ←→ Ceph RBD (对象存储: LFS/制品)

↓

Sidekiq → 异步任务处理

1.3 高可用机制

  • Webservice/Workhorse 多副本:无状态服务通过 HorizontalPodAutoscaler 水平扩展,前置 Service 负载均衡
  • Gitaly 分片存储:Git 仓库按分片分布在多个 Gitaly Pod 上,每个分片挂载独立的 Ceph RBD PV,单分片故障不影响其他分片
  • PostgreSQL 主从复制:生产环境建议使用外部高可用 PostgreSQL(如 Patroni 集群),Chart 内置 PostgreSQL 为单节点
  • Ceph RBD 数据可靠性:Ceph 的多副本/纠删码机制确保数据在底层存储层面的高可用,即使单个 OSD 节点故障数据不丢失

1.4 存储规划

PVC 名称 用途 容量 StorageClass 访问模式
repo-data Gitaly Git 仓库 100Gi ceph-rbd ReadWriteOnce
postgresql-data PG 数据库 50Gi ceph-rbd ReadWriteOnce
redis-data Redis 持久化 10Gi ceph-rbd ReadWriteOnce
minio-data 对象存储 200Gi ceph-rbd ReadWriteOnce
prometheus-data 监控数据 10Gi ceph-rbd ReadWriteOnce

二、部署实战

2.1 前置条件检查

确保 Ceph RBD StorageClass 已就绪(参考第 2 天 CSI Driver 配置):

💻 代码示例

# 确认 Ceph RBD StorageClass 存在

kubectl get storageclass ceph-rbd

 

# 确认 CSI Driver 正常运行

kubectl get pods -n kube-system | grep ceph-csi

 

# 确认集群有足够的资源

kubectl top nodes

2.2 添加 GitLab 官方 Helm 仓库

💻 代码示例

# 添加 GitLab 官方 Helm Chart 仓库

helm repo add gitlab https://charts.gitlab.io/

helm repo update

 

# 查看 GitLab Chart 版本

helm search repo gitlab/gitlab –versions | head -10

 

# 拉取默认 values 用于参考

helm show values gitlab/gitlab > /tmp/gitlab-default-values.yaml

2.3 编写 values.yaml(Ceph RBD 持久化配置)

这是部署的核心配置文件,重点是将所有持久化存储指向 Ceph RBD StorageClass:

💻 代码示例

# /tmp/gitlab-values.yaml

# GitLab Helm Chart 自定义配置 – Ceph RBD 持久化

 

global:

# 基础域名(替换为你的实际域名)

hosts:

domain: example.com

gitlab:

name: gitlab.example.com

minio:

name: minio.example.com

registry:

name: registry.example.com

 

# 统一指定 Ceph RBD StorageClass

storageClass: ceph-rbd

 

# TLS 证书配置(生产环境建议使用 cert-manager)

ingress:

configureCertmanager: false

tls:

enabled: false

 

# GitLab Runner 配置

gitlab-runner:

install: true

runners:

config: |

[[runners]]

name = "k8s-runner"

executor = "kubernetes"

[runners.kubernetes]

namespace = "gitlab"

image = "alpine:latest"

 

# Webservice 配置

gitlab:

webservice:

minReplicas: 2

maxReplicas: 4

resources:

requests:

cpu: 500m

memory: 2Gi

limits:

cpu: 2000m

memory: 4Gi

# Sidekiq 后台任务

sidekiq:

minReplicas: 2

resources:

requests:

cpu: 200m

memory: 1Gi

 

# Gitaly – Git 仓库存储(核心持久化组件)

gitlab:

gitaly:

persistence:

enabled: true

storageClass: ceph-rbd

size: 100Gi

accessMode: ReadWriteOnce

 

# PostgreSQL – 元数据数据库

postgresql:

persistence:

enabled: true

storageClass: ceph-rbd

size: 50Gi

accessMode: ReadWriteOnce

postgresqlUsername: gitlab

postgresqlDatabase: gitlabhq_production

postgresqlPostgresPassword: "ChangeMePG2026!"

postgresqlPassword: "ChangeMeGitLab2026!"

resources:

requests:

cpu: 500m

memory: 1Gi

limits:

cpu: 2000m

memory: 4Gi

 

# Redis – 缓存与会话

redis:

persistence:

enabled: true

storageClass: ceph-rbd

size: 10Gi

accessMode: ReadWriteOnce

password: "ChangeMeRedis2026!"

resources:

requests:

cpu: 200m

memory: 512Mi

 

# MinIO – 内置对象存储(LFS、制品、上传文件)

minio:

enabled: true

persistence:

enabled: true

storageClass: ceph-rbd

size: 200Gi

accessMode: ReadWriteOnce

minioAccessKey: "gitlab-minio"

minioSecretKey: "ChangeMeMinIO2026!"

 

# Prometheus – 内置监控

prometheus:

install: true

persistence:

enabled: true

storageClass: ceph-rbd

size: 10Gi

 

# Nginx Ingress – 如果集群已有 Ingress Controller 可关闭

nginx-ingress:

enabled: false

 

# Cert-manager – 如果集群已有可关闭

certmanager:

install: false

2.4 执行 Helm 部署

💻 代码示例

# 创建命名空间

kubectl create namespace gitlab

 

# 执行 Helm 部署(首次部署可能需要 5-10 分钟拉取镜像)

helm install gitlab gitlab/gitlab

–namespace gitlab

–version 8.0.0

–set global.hosts.domain=example.com

–set global.hosts.gitlab.name=gitlab.example.com

-f /tmp/gitlab-values.yaml

 

# 等待所有 Pod 就绪(GitLab 组件较多,耐心等待)

kubectl get pods -n gitlab -w

 

# 查看 Helm Release 状态

helm status gitlab -n gitlab

2.5 验证 Pod 与 PVC 状态

💻 代码示例

# 查看所有 Pod 状态(正常应全部 Running)

kubectl get pods -n gitlab

 

# 查看 Service

kubectl get svc -n gitlab

 

# 查看 PVC 持久卷绑定状态(确认全部 Bound 到 Ceph RBD)

kubectl get pvc -n gitlab

 

# 查看实际挂载的 PV

kubectl get pv | grep ceph-rbd

 

# 查看 Ingress 路由规则

kubectl get ingress -n gitlab

预期输出示例:

💻 代码示例

{

"pvc_status": [

{"name": "repo-data-gitlab-gitaly-0", "status": "Bound", "capacity": "100Gi", "storageclass": "ceph-rbd"},

{"name": "data-gitlab-postgresql-0", "status": "Bound", "capacity": "50Gi", "storageclass": "ceph-rbd"},

{"name": "data-gitlab-redis-master-0", "status": "Bound", "capacity": "10Gi", "storageclass": "ceph-rbd"},

{"name": "data-gitlab-minio-0", "status": "Bound", "capacity": "200Gi", "storageclass": "ceph-rbd"}

]

}

所有 PVC 显示 Bound 且 StorageClass 为 ceph-rbd,说明 Ceph 分布式存储已成功为 GitLab 提供持久化卷。

三、登录验证

3.1 获取初始 Root 密码

💻 代码示例

# GitLab 初始 root 密码存储在 Secret 中(24小时后自动删除)

kubectl get secret gitlab-gitlab-initial-root-password -n gitlab -o jsonpath="{.data.password}" | base64 -d

echo

 

# 获取 GitLab Webservice Service 地址

kubectl get svc -n gitlab | grep webservice

3.2 通过端口转发访问(测试环境)

💻 代码示例

# 端口转发到本地访问

export GITLAB_POD=$(kubectl get pod -n gitlab -l app=webservice -o jsonpath="{.items[0].metadata.name}")

kubectl port-forward -n gitlab svc/gitlab-webservice-default 8080:8080 &

 

# 通过 curl 验证 GitLab 响应

curl -I http://localhost:8080/users/sign_in

# 预期返回 HTTP 200 OK

3.3 通过 API 验证

💻 代码示例

# 使用 root 账户和初始密码获取 API Token

# 首先通过 Web UI 登录后创建 Personal Access Token

 

# 使用 API Token 验证连接

export GITLAB_TOKEN="your-personal-access-token"

curl –header "PRIVATE-TOKEN: ${GITLAB_TOKEN}"

http://gitlab.example.com/api/v4/version

 

# 预期返回类似:

# {"version":"16.9.0","revision":"…"}

3.4 验证 Git 操作

💻 代码示例

# 克隆测试仓库

git clone http://gitlab.example.com/root/test-repo.git

 

# 推送代码验证 Gitaly + Ceph RBD 存储链路

cd test-repo

echo "# GitLab on K8s with Ceph RBD" > README.md

git add .

git commit -m "Test push via K8s GitLab"

git push origin main

四、日常巡检命令

4.1 Pod 健康检查

💻 代码示例

# 检查所有 Pod 状态,重点关注 Restart 次数

kubectl get pods -n gitlab -o wide

 

# 检查是否有 CrashLoopBackOff 或异常重启

kubectl get pods -n gitlab –field-selector=status.phase!=Running

 

# 查看 GitLab 组件事件

kubectl describe pod -n gitlab -l app=webservice | tail -20

4.2 存储容量巡检

💻 代码示例

# 查看 PVC 使用情况

kubectl get pvc -n gitlab

 

# 通过 Ceph 工具查看后端存储池容量

ceph df | grep kubernetes

 

# 查看 Ceph OSD 使用率

ceph osd df

 

# 检查 Gitaly 仓库存储路径磁盘占用

GITALY_POD=$(kubectl get pod -n gitlab -l app=gitaly -o jsonpath="{.items[0].metadata.name}")

kubectl exec -n gitlab $GITALY_POD — df -h /var/opt/gitlab/repositories

4.3 数据库巡检

💻 代码示例

# 进入 PostgreSQL Pod

PG_POD=$(kubectl get pod -n gitlab -l app=postgresql -o jsonpath="{.items[0].metadata.name}")

 

# 检查数据库连接数

kubectl exec -n gitlab $PG_POD — psql -U gitlab -d gitlabhq_production

-c "SELECT count(*) FROM pg_stat_activity;"

 

# 检查数据库大小

kubectl exec -n gitlab $PG_POD — psql -U gitlab -d gitlabhq_production

-c "SELECT pg_size_pretty(pg_database_size('gitlabhq_production'));"

 

# 检查最大连接数配置

kubectl exec -n gitlab $PG_POD — psql -U gitlab -d gitlabhq_production

-c "SHOW max_connections;"

4.4 日志查看

💻 代码示例

# 查看 Webservice 主应用日志

kubectl logs -n gitlab -l app=webservice –tail=50

 

# 查看 Sidekiq 后台任务日志

kubectl logs -n gitlab -l app=sidekiq –tail=50

 

# 查看 Gitaly 存储服务日志

kubectl logs -n gitlab -l app=gitaly –tail=30

 

# 查看 PostgreSQL 慢查询日志

kubectl logs -n gitlab -l app=postgresql –tail=50 | grep -i "duration"

4.5 性能监控

💻 代码示例

# 查看 Pod 资源使用率(需要 metrics-server)

kubectl top pods -n gitlab

 

# 查看 Prometheus 采集的 GitLab 指标

PROM_POD=$(kubectl get pod -n gitlab -l app=prometheus -o jsonpath="{.items[0].metadata.name}")

kubectl port-forward -n gitlab $PROM_POD 9090:9090 &

 

# 查询 GitLab API 请求延迟 P99

curl -s "http://localhost:9090/api/v1/query?query=gitlab_http_request_duration_seconds" | python3 -m json.tool | head -20

五、常见问题

Q1:Pod 启动失败,PVC 一直 Pending?

A:检查 Ceph RBD StorageClass 是否正确配置。运行 kubectl describe pvc <pvc-name> -n gitlab 查看事件,常见原因包括:① CSI Driver 未正常运行 ② Ceph 池容量不足 ③ StorageClass 名称拼写错误。确认 kubectl get storageclass 中存在 ceph-rbd。

Q2:Gitaly Pod OOM Killed,Git push 操作失败?

A:Gitaly 处理大型仓库时内存消耗大。编辑 values.yaml 增加 Gitaly 资源限制:gitlab.gitaly.resources.limits.memory: 4Gi,然后执行 helm upgrade gitlab gitlab/gitlab -n gitlab -f values.yaml。同时检查 Ceph RBD 的 IOPS 性能是否满足 Git 仓库的高频读写需求。

Q3:GitLab 页面加载缓慢,如何排查?

A:多维度排查:① 检查 Webservice Pod 资源是否充足(kubectl top pods -n gitlab)② 检查 PostgreSQL 慢查询日志 ③ 检查 Redis 缓存命中率 ④ 确认 Ceph RBD 卷的 IOPS 延迟正常(ceph tell osd.* bench)。生产环境建议 Gitaly 使用 Ceph RBD 的 high-performance 存储池。

六、总结

本篇完成了 GitLab 代码托管平台在 K8s 上的完整部署。核心要点回顾:

  1. 架构理解:GitLab 由 Webservice、Sidekiq、Gitaly、PostgreSQL、Redis、MinIO 等多个微服务组成,Gitaly 是 Git 仓库的核心存储组件
  2. Helm 部署:使用官方 gitlab/gitlab Chart,通过 values.yaml 统一配置所有组件的 storageClass: ceph-rbd,实现 Ceph RBD 持久化
  3. 存储规划:Gitaly 100Gi、PostgreSQL 50Gi、MinIO 200Gi、Redis 10Gi,全部挂载到 Ceph RBD 块存储
  4. 运维巡检:通过 kubectl + psql + ceph 命令组合完成 Pod、存储、数据库、日志四维巡检

GitLab 是本系列中组件最复杂的中间件,其多 PVC 持久化需求恰好展示了 Ceph 分布式存储在 K8s 中的核心价值——统一的、高可靠的、可弹性扩展的存储底座。

七、下期预告

第 14 天:K8s 部署 ClickHouse 列式数据库集群(Ceph RBD + 架构设计)

ClickHouse 是 OLAP 分析领域的明星数据库,下篇将部署 ClickHouse 集群,探索列式存储在 Ceph RBD 上的性能表现,包括分片与副本架构设计。

八、系列目录

微信二维码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像 - 恒星
欢迎您留下宝贵的见解!
提交
头像 - 恒星

昵称

取消
昵称表情代码图片快捷回复

    暂无评论内容