GitLab 运维实战:部署、权限模型与备份恢复
GitLab 运维实战:部署、权限模型与备份恢复
第一次接手 GitLab 是入职第二个月,前任运维交接时说了一句”这平台平时不用管,坏了再说”。结果第三周磁盘就写满了——仓库备份和日志把根分区撑爆,全组开发停工半天。从那以后我给 GitLab 定了两条规矩:磁盘单独挂盘并设监控,备份每天跑并且每月做一次恢复演练。这篇就是这套维护工作的完整记录。
一、运维和开发在 Git 上不是一回事
同样是用 Git,职责完全不同:
| 维度 | 开发工程师 | 运维工程师 |
|---|---|---|
| 角色 | Git 的使用者 | 平台的维护者 + 规范制定者 |
| 日常 | 写代码、提交、分支、合并、解冲突 | 部署维护 GitLab、管权限、备份恢复、配 Runner |
| 关心点 | 我的代码能不能提交合并 | 平台稳不稳、权限对不对、能不能审计 |
| 典型操作 | add / commit / push / merge | gitlab-ctl、gitlab-rake、备份恢复 |
| 输出 | 业务代码 | 流水线模板、分支规范、审计记录 |
落到日常工作里,运维侧大概有这几块:
- GitLab 平台运维:安装升级、备份恢复、磁盘监控;
- 用户与权限:对接 LDAP/AD,配置群组和项目权限;
- Runner 管理:注册执行器、打标签、区分不同环境的构建;
- 代码质量门禁:分支保护、强制 MR 审批、必须通过流水线才能合并;
- CI/CD 建设:写
.gitlab-ci.yml模板、管构建产物、配 CI/CD 变量; - 发布与回滚:合并 main 自动部署,出问题 revert 回滚;
- 规范设计:分支模型、MR 审查流程、
.gitignore与 Git LFS 管理。
二、先看清 GitLab 的组件地图
GitLab 是一个 Ruby/Rails 应用,单机安装也含七八个组件,排障的时候知道”哪个症状对应哪个组件”能省掉一半时间:
| 组件 | 作用 | 运维关注点 |
|---|---|---|
| nginx | 静态 Web 入口 | external_url 决定访问地址和端口 |
| gitlab-workhorse | 轻量反向代理 | 大文件上传 / 下载加速 |
| unicorn / puma | Rails 应用服务 | 502 的常见来源,先看它的日志 |
| postgresql | 主数据库 | 备份恢复的核心 |
| redis | 缓存 / 队列 | Sidekiq 依赖它 |
| sidekiq | 异步后台任务 | 队列堆积会拖慢全站 |
| gitaly | Git 仓库存储(RPC) | 占磁盘大头,git 操作慢先查它 |
三、部署与关键配置
生产环境建议起步 4C8G,磁盘按仓库增长规划——我吃过的亏就是没给仓库单独挂盘。
1 | # 1. 环境准备 |
然后是 /etc/gitlab/gitlab.rb 里几个必改项:
1 | external_url 'http://10.0.8.200:8090' # 访问地址和端口 |
1 | # 3. 生效并自检 |
初始密码在 /etc/gitlab/initial_root_password,24 小时后会被自动删除,第一次登录必须马上改密码,否则就只能 gitlab-rake "gitlab:password:reset" 来救了。
还有一个容易漏的开关:Webhook 要回调内网地址时,需要在”管理中心 → 设置 → 网络”里允许本地网络请求,否则推送事件根本发不出去。
四、代码怎么进 GitLab
两种常见方式,第一条是克隆空仓库再放代码,日常最省事:
1 | # 方式一:克隆空仓库 → 拷贝代码 → 提交推送(克隆自带远程地址) |
SSH 公钥贴到”右上角头像 → Preferences → SSH Keys”,之后就免密推送了。
五、权限模型:用户 → 组 → 项目
GitLab 的权限核心是”用户 → 组 → 项目”三层,角色分 5 级:
| 角色 | 权限 | 典型对象 |
|---|---|---|
| Guest | 只能看 Issue,看不了代码 | 客户、外包旁观 |
| Reporter | 看代码、提 Issue | 测试、产品 |
| Developer | 推分支、提 MR,不能直接推 main | 开发 |
| Maintainer | 管项目设置、合并 MR、打 Tag | 技术组长 |
| Owner | 项目全部权限 | 项目负责人 / 运维 |
生产环境的落地姿势:
- 按部门建组,比如 ops 组、dev 组,再在组内建项目,项目权限默认继承组;
- 开发给 Developer、组长 Maintainer、运维 Owner/Admin;
- 对接 LDAP/AD,账号统一从企业目录同步,禁止手工建号;
- main 分支开保护(Protected branches),开发推 main 直接拒绝,必须走 MR。
一个完整协作流程的样子(用 dev 账号走一遍):
1 | # dev 用户在自己机器上克隆并配置提交身份 |
这个”先被拒绝、再走 MR”的流程我建议在给新人开账号时当面演示一次,比发文档有效——自己撞一次分支保护,比看十遍规则记得牢。另外注意克隆方式:git@ 走 SSH 免密,http:// 方式每次要输账号密码,给部署脚本用的时候别搞混。
六、代码审计:这份活到底谁干
“审计开发的提交是不是运维的活”这个问题,分工是清楚的:运维搭平台和流程,代码内容由技术组长 / 资深开发审查。
| 审计层面 | 谁负责 | 做什么 |
|---|---|---|
| 代码内容审查(Code Review) | 技术组长 / 资深开发 | 审查 MR 的代码质量、逻辑、安全 |
| 提交规范审计 | 运维 + 自动检查 | 提交信息格式、禁止密钥入库、限制大文件 |
| 操作行为审计(Audit Events) | 运维 | 谁登录了、谁改了权限、谁删了分支 |
| 合规审计 | 运维 | 审计日志留存、操作留痕可追溯 |
运维侧要落地的几件事:
1 | # 1. 审计事件:管理中心 → 审计事件,登录、权限变更、项目删除、分支保护变更都能查 |
七、备份与恢复:每月必须演练一次
备份这件事的定义很简单:没验证过能恢复的备份等于没有备份。
1 | # 1. 手动备份(仓库 + 数据库 + 附件) |
三个必须记住的坑:
- 备份不包含
/etc/gitlab/gitlab.rb,配置文件要单独备份; - 跨版本恢复不行,升级前先备份,恢复前确认版本号一致;
backup_keep_time控制保留份数,磁盘要按备份量规划——建议备份目录单独挂盘。
我的实际做法是:每天自动备份,每周人工看一眼备份文件大小是否正常,每月在测试环境恢复一次确认数据完整。第三步才是真正兜底的那步。
八、升级与 HA 的取舍
升级的官方硬规矩:只能跨 2 个次要版本。14.x 要先升 15.x 再升 16.x,不能一步跳过去。
1 | # 升级流程 |
HA 方面的建议就一条:不要一上来就堆 HA。单机版撑 500 用户以内没问题;规模上来再考虑 PostgreSQL/Redis 外置、应用多节点、Gitaly 集群。复杂度上去了,故障模式也跟着翻倍,先把”备份 + 恢复演练”做扎实,比什么高可用都实在。
九、常见故障排查
| 故障 | 常见原因 | 处理路径 |
|---|---|---|
| 页面 502 | unicorn/puma 挂了、内存不足、磁盘满 | gitlab-ctl status → tail unicorn → free -h / df -h |
| git 操作超时卡死 | Gitaly 异常、仓库过大、磁盘 IO 高 | tail gitaly → df -h → du -sh 仓库目录 |
| 提交被拒 | 分支保护、无推送权限 | 查分支保护规则,改走 MR |
| Runner 离线 | 机器故障、token 失效、网络不通 | gitlab-runner verify → 重新 register |
| 克隆报 Permission denied | SSH 密钥没配或换了机器 | ssh -T 测试 → 重新贴公钥 |
| 仓库越来越大 | 大文件入库、没跑 GC | git gc、配置 Git LFS、限制 push 大小 |
| 磁盘满告警 | 备份/日志/仓库增长 | df -h 定位 → 清理旧备份 → 日志轮转 |
排障三板斧,顺序别乱:
1 | gitlab-ctl status # 1. 先看哪个组件 down 了 |
最后
维护 GitLab 这类平台,日常动作其实不多,但每一项都要按规矩来:权限最小化、备份加演练、升级别跳版本、排障先看 status 和日志。平台本身不难,难的是把这些动作坚持成习惯——这类基础设施出一次事,全组都跟着停摆。


