GitLab Self-Managed 生产部署、升级、备份与灾难恢复
GitLab Self-Managed 同时承载代码、CI/CD、制品、镜像、Wiki、Issue和身份权限。它不是单一Web应用,而是由Puma、Sidekiq、Gitaly、PostgreSQL、Redis、对象存储、Runner等组件组成。任何一个共享依赖异常,都可能影响整个研发流程。
一、先画出组件边界
用户与Git客户端
↓
负载均衡 / Nginx / Workhorse
↓
Puma Web API
↓
PostgreSQL、Redis、Gitaly、对象存储
异步任务:Sidekiq
流水线执行:GitLab Runner
监控:Prometheus、日志与健康检查
部署前明确:
- 用户数、仓库数和增长;
- Git LFS、Artifact、Package、Registry用量;
- CI并发与Runner类型;
- RPO/RTO;
- 单机、参考架构还是Geo;
- 身份源、MFA和访问边界。
二、容量规划
容量不能只看仓库目录。还包括:
- PostgreSQL数据库;
- Gitaly仓库和对象池;
- LFS;
- Job Artifact;
- Package Registry;
- Container Registry;
- Upload和Pages;
- 备份临时空间;
- 日志和监控;
- Runner缓存。
监控增长率并设置分级水位。备份时通常需要额外空间,磁盘接近满才开始扩容往往来不及。
三、部署模式
单节点Omnibus
适合中小规模,运维简单,但故障域集中。必须有外部备份、快速重建文档和备用容量。
多节点参考架构
拆分Web、Sidekiq、Gitaly、PostgreSQL、Redis和入口。复杂度明显上升,需要负载均衡、故障切换和组件级监控。
Kubernetes部署
适合已有成熟Kubernetes能力的团队。Stateful组件、对象存储、数据库和升级仍需独立治理,不能因为使用Helm就忽略数据恢复。
四、PostgreSQL与Redis
PostgreSQL保存项目元数据、权限、Issue和流水线状态;Redis承担缓存、会话和队列协调。两者备份和高可用边界不同。
检查:
- 数据库连接、慢SQL和膨胀;
- Sidekiq队列和Redis内存;
- 连接池;
- 复制延迟;
- 备份恢复;
- 数据库版本与GitLab兼容矩阵。
升级GitLab时不能随意单独跨越不受支持的PostgreSQL版本。
五、Gitaly与仓库
Gitaly提供Git仓库访问。生产关注:
- 存储容量和inode;
- 磁盘延迟;
- 仓库数量与大仓库;
- Loose Object和Pack;
- Repository Check;
- Praefect一致性与虚拟存储;
- 网络和RPC延迟;
- 维护任务。
不要在GitLab运行时直接移动仓库目录或手工修改内部路径。使用官方迁移和仓库管理接口。
六、Sidekiq队列
Sidekiq负责邮件、导入、仓库维护、Webhook等异步任务。积压会表现为“页面操作成功但后台一直未完成”。
监控:
- 队列长度和最老任务年龄;
- 失败与重试;
- Worker并发;
- Redis延迟;
- 特定队列热点;
- 任务执行时间。
不要简单无限增加并发,它可能把压力转移到数据库、Gitaly或外部服务。
七、Runner安全
Runner执行仓库代码,应视为不可信执行环境。
- 受保护项目和普通项目使用不同Runner;
- Fork/MR不能获得生产凭据;
- 优先临时Runner;
- 禁止不受信任务使用宿主机Docker Socket;
- 限制云元数据和内网;
- 任务后清理工作区;
- Runner Token和注册权限受控;
- Shell Executor风险最高。
八、对象存储
将Artifact、LFS、Upload、Package、备份等放入对象存储可降低本地盘压力,但需要:
- 生命周期策略;
- 版本与删除保护;
- 加密;
- 凭据最小权限;
- 跨区域复制;
- 请求和带宽监控;
- 恢复验证。
对象存储数据必须与数据库元数据一致恢复。
九、备份范围
GitLab备份不仅是仓库:
- PostgreSQL;
- Git仓库;
- Upload、Artifact、LFS、Pages;
- Package和Registry;
- 配置文件;
gitlab-secrets.json;- TLS证书;
- SSH Host Key;
- 外部对象存储策略和凭据记录。
配置和Secrets通常不包含在普通应用数据备份中,必须单独保护。缺失Secrets可能导致加密数据无法解密。
十、执行备份
Omnibus示意:
sudo gitlab-backup create
sudo gitlab-ctl backup-etc
备份任务应记录版本、大小、耗时、失败组件和目标位置。备份文件移出GitLab主机,防止主机损坏或勒索时一并丢失。
大型实例需要评估备份对Gitaly、数据库和磁盘的影响,并考虑组件级备份和对象存储原生保护。
十一、恢复演练
恢复通常要求目标GitLab版本与备份版本一致。
流程:
- 准备隔离服务器;
- 安装相同版本;
- 恢复配置与Secrets;
- 恢复应用备份;
- 验证数据库迁移;
- 检查仓库、LFS、Artifact和Registry;
- 测试登录、Clone、Push、Pipeline和Webhook;
- 记录实际RTO和缺失项。
不要等事故发生时第一次尝试恢复。
十二、版本升级策略
GitLab升级通常存在必经版本。升级前查阅官方Upgrade Path,不能随意跨大版本。
升级清单:
- 当前版本、Edition和安装方式;
- 必经版本;
- PostgreSQL、Redis、Gitaly和Runner兼容;
- 后台迁移是否完成;
- 磁盘和备份空间;
- 插件、LDAP、SAML和Webhook;
- 回滚边界;
- 维护窗口。
十三、升级实施
- 完成并校验备份;
- 检查健康、后台迁移和Sidekiq;
- 禁止新变更或进入维护窗口;
- 按必经版本逐级升级;
- 每级等待数据库迁移完成;
- 验证Web、Git、Runner和Registry;
- 观察错误率和队列;
- 再进入下一版本。
回滚常常需要恢复备份,而不是简单降级软件包。
十四、健康与日志
重点端点和日志:
- Readiness、Liveness;
- Puma、Workhorse、Nginx;
- Sidekiq;
- Gitaly/Praefect;
- PostgreSQL、Redis;
- Registry;
- Runner。
为请求、用户操作、仓库RPC和后台任务建立时间关联。日志中避免泄露Token、Cookie、私有仓库内容和变量。
十五、常见502/503
排查顺序:
- 入口是否能连接Workhorse/Puma;
- Puma Worker和内存;
- PostgreSQL连接;
- Redis和Sidekiq;
- Gitaly RPC;
- 磁盘和inode;
- 最近升级和配置变更;
- 反向代理超时。
不要只重启全部组件。先定位单个依赖,保留日志和进程现场。
十六、CI任务排队
区分:
- 无可用Runner;
- Tag不匹配;
- Runner离线;
- 并发上限;
- 资源配额;
- 镜像拉取慢;
- 缓存或制品服务异常;
- Job规则未满足。
按项目、Runner池和执行器监控队列年龄,而不是只看总任务数。
十七、Container Registry
治理:
- 存储和对象生命周期;
- Tag保护;
- 垃圾回收;
- 大镜像和重复层;
- TLS;
- 漏洞扫描;
- 删除与保留;
- 与GitLab数据库的一致性。
垃圾回收前确认版本和模式,避免在不支持的在线状态直接操作存储。
十八、身份与权限
- 管理员最小化并启用MFA;
- LDAP/SAML中断时保留受控应急账号;
- Access Token设置过期和范围;
- Deploy Token、Runner Token和Webhook Secret定期轮换;
- 禁止把Personal Token写入流水线;
- 审计Group Owner、管理员和Protected Branch变更。
十九、灾难恢复与Geo
Geo可提供跨站点复制,但仍不是历史备份。需要监控复制状态、对象存储、数据库和仓库一致性,并演练提升Secondary和回切。
灾备Runbook包含:
- DNS/入口切换;
- 身份源;
- 数据库和仓库;
- 对象存储;
- Runner接入;
- Webhook和外部集成;
- 证书与SSH Host Key;
- 业务确认。
二十、监控与上线清单
- [ ] 组件拓扑、容量和故障域清晰;
- [ ] PostgreSQL、Redis、Gitaly和对象存储分别监控;
- [ ] Sidekiq队列、最老任务和失败任务有告警;
- [ ] Runner按信任边界隔离;
- [ ] 配置、Secrets和应用数据均有备份;
- [ ] 相同版本隔离恢复演练已通过;
- [ ] 升级遵循必经版本并等待后台迁移;
- [ ] Token、管理员和外部身份最小权限;
- [ ] 仓库、Registry、LFS和Artifact有保留策略;
- [ ] 主机、数据库、存储和站点故障均有Runbook。
二十一、结语
GitLab是研发基础设施,不应按普通网站运维。可靠性来自组件级容量、Runner隔离、完整备份、版本化升级和恢复演练。最重要的不是“每天备份成功”,而是能在一台干净服务器上恢复相同版本,并完成登录、Clone、Push、Pipeline和制品下载的完整验证。
参考资料
- GitLab Administration:https://docs.gitlab.com/administration/
- GitLab Backup and Restore:https://docs.gitlab.com/administration/backup_restore/