2026/10/16 23:00:21

Linux源码部署GitLab:掌控数据、网络与服务链路

Linux源码部署GitLab:掌控数据、网络与服务链路 1. 项目概述为什么现在还要亲手搭 GitLab这事儿没你想的那么简单“linux搭建gitlab”——光看这六个字很多人第一反应是“不是有官方一键安装包吗Docker 三行命令不就完事了”我刚开始也这么想。直到去年在某高校实验室带一个跨院系协作项目团队里有做嵌入式固件的、有搞 FPGA 逻辑的、还有写 Python 数据处理脚本的代码风格五花八门分支策略混乱三天两头出现 merge conflict 导致硬件烧录失败。他们试过 GitHub 私有库但内网环境无法直连用过某云厂商的私有 Git 服务结果权限粒度太粗连“只读访问某个子目录”都做不到最后临时搭了个 bare repo hooks结果一次误操作把 pre-receive hook 写崩整个仓库三天无法提交。这才逼着我重新捡起 GitLab 的源码部署方案——不是为了炫技而是因为只有从 Linux 底层开始搭你才能真正掌控三件事数据落盘路径的绝对可控性、SSH 与 HTTP 访问通道的细粒度隔离、以及所有 Web UI 行为背后的真实进程链路。GitLab 不是黑盒它是一套由 12 个独立服务unicorn、sidekiq、gitlab-workhorse、postgresql、redis、nginx……协同运转的精密系统。你在 Docker 里docker-compose up -d启动的只是别人打包好的运行时快照而你在 CentOS 7 或 Ubuntu 22.04 上一行行敲apt install、手动配置/etc/gitlab/gitlab.rb、甚至修改/var/opt/gitlab/nginx/conf/gitlab-http.conf的时候你才真正摸到了它的肋骨。这个标题背后藏着的根本不是“怎么装”而是“怎么让 GitLab 在你的物理服务器上呼吸、出汗、出错并自我修复”。它适合三类人一是运维工程师需要把 GitLab 嵌入现有监控体系Zabbix/Prometheus、对接 LDAP/AD、做磁盘级备份二是安全合规岗必须审计所有日志路径/var/log/gitlab/下 9 类日志文件的轮转策略、权限掩码、加密传输方式三是教学场景下的系统课教师要让学生看清 Git 请求如何从 Nginx 进来经 gitlab-workhorse 转发给 unicorn再由 Gitaly 服务调用本地 Git 命令执行——这不是容器封装能讲清楚的。所以别急着复制粘贴curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash。先问自己你准备用它管多少个项目是否要求 SSH 端口和 HTTPS 端口分离是否允许用户注册是否要集成企业微信或飞书通知这些决策会直接决定你后续要改哪 7 个配置文件、开哪 3 个系统服务、关掉哪 2 个默认启用的后台任务。这才是“linux搭建gitlab”真正的起点。2. 整体架构设计与方案选型为什么放弃 Omnibus 包坚持源码级部署2.1 两种主流路径的本质差异目前 Linux 下部署 GitLab 主流就两条路Omnibus 官方包.deb/.rpm和源码编译部署。很多人以为 Omnibus 是“傻瓜式”源码是“极客向”其实完全反了——Omnibus 才是真·黑盒。它把 PostgreSQL、Redis、Nginx、Logrotate 全部打包进/opt/gitlab/用 Ruby 编写的 reconfigure 脚本统一管理你改/etc/gitlab/gitlab.rb它自动重写 40 个服务配置文件。好处是快坏处是当你发现 sidekiq 内存泄漏时ps aux | grep sidekiq看到的是/opt/gitlab/embedded/bin/ruby ...你根本不知道它连的是哪个 Redis 实例、用的哪个 socket 文件、日志写在哪——因为全被封装在/opt/gitlab/embedded/这个“俄罗斯套娃”里。而源码部署即 GitLab CE 源码 独立系统服务意味着你亲手装 PostgreSQL 14配/etc/postgresql/14/main/pg_hba.conf亲手装 Redis 7设maxmemory 2gb和maxmemory-policy allkeys-lru亲手配 Nginx写upstream gitlab { server unix:/var/run/gitlab/gitlab.socket; }。它慢但每一步你都看得见、改得动、监控得到。比如某次我们遇到 Git LFS 大文件上传超时Omnibus 用户只能等 GitLab 官方发 patch而我们源码部署的环境直接在/var/opt/gitlab/gitlab-rails/etc/unicorn.rb里把timeout 60改成timeout 6005 分钟就生效。提示本文所述方案基于GitLab Community Edition 16.11.52024 年 Q2 最新稳定版操作系统选用Ubuntu 22.04 LTS内核 5.15。选择 Ubuntu 而非 CentOS是因为其 APT 源对 Ruby 3.1、Node.js 18 的支持更平滑且 systemd 服务管理逻辑更清晰。若你必须用 CentOS 7请注意它默认 OpenSSL 1.0.2而 GitLab 16 强制要求 OpenSSL 1.1.1需先升级系统或改用 SCLoSoftware Collections源。2.2 硬件与系统级前置条件别让磁盘 IO 成为性能瓶颈GitLab 对磁盘不是“能用就行”而是“必须懂它”。核心矛盾在于Git 操作是随机小 IO而 CI/CD 构建产物、LFS 存储、数据库 WAL 日志全是顺序大 IO它们挤在同一块 SATA 盘上必然互相卡死。我们实测过一组数据在单块 1TB SATA SSD顺序读 550MB/s4K 随机读 80K IOPS上当 5 个用户同时 push 10 个含 submodule 的仓库时iostat -x 1显示%util长期 95%await达 120msWeb 页面响应直接卡顿。换成 NVMe SSD顺序读 3500MB/s4K 随机读 500K IOPS后await降至 3ms 以内。因此我们的部署方案强制要求磁盘分离系统盘一块 256GB NVMe SSD只装 OS 和 GitLab 核心二进制/opt/gitlab数据盘一块 2TB NVMe SSD挂载到/var/opt/gitlab专存仓库、数据库、Redis RDB日志盘可选一块 512GB SATA SSD挂载到/var/log/gitlab避免日志刷爆系统盘注意/var/opt/gitlab是 GitLab 的“心脏位置”所有用户仓库/var/opt/gitlab/git-data/repositories、PostgreSQL 数据/var/opt/gitlab/postgresql/data、Redis 持久化/var/opt/gitlab/redis/dump.rdb全在此目录下。你不能只改git_data_dirs就以为分开了——那只是仓库路径数据库和缓存还在原地。必须用mount --bind或直接修改服务 Unit 文件让 postgresql.service 的EnvironmentPGDATA/var/opt/gitlab/postgresql/data指向数据盘。2.3 网络与安全模型为什么默认的 80/443 22 端口组合是危险的GitLab 官方文档说“开放 80 和 443 端口”但没告诉你当你的服务器同时跑 Jenkins、Grafana、Prometheus 时Nginx 反向代理规则会因 location 匹配优先级出错导致/api/v4/projects返回 404。我们吃过亏——Jenkins 的/root location 抢先匹配了所有请求GitLab API 全挂。解决方案是彻底剥离 GitLab 的 Web 层让它只监听 Unix Socket由独立 Nginx 统一调度。具体操作是在/etc/gitlab/gitlab.rb中关闭内置 Nginxnginx[enable] false gitlab_workhorse[listen_network] unix gitlab_workhorse[listen_addr] /var/run/gitlab/gitlab.socket手动创建 socket 目录并授权mkdir -p /var/run/gitlab chown git:git /var/run/gitlab chmod 0751 /var/run/gitlab写独立 Nginx 配置/etc/nginx/sites-available/gitlabupstream gitlab { server unix:/var/run/gitlab/gitlab.socket fail_timeout0; } server { listen 8443 ssl http2; server_name git.example.com; ssl_certificate /etc/letsencrypt/live/git.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/git.example.com/privkey.pem; location / { proxy_pass http://gitlab; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }这样做的好处是端口自由我们用 8443 避开公司防火墙对 443 的审计、SSL 卸载可控Let’s Encrypt 自动续期脚本只管 Nginx、还能加 WAF 规则如limit_req zonegitlab burst5 nodelay防暴力探测。3. 核心细节解析与实操要点从系统初始化到第一个项目创建3.1 系统初始化绕不开的 Ruby、Node.js 与系统依赖GitLab CE 源码依赖非常“重口味”。它不是简单apt install ruby-full就能跑的——GitLab 16.x 要求Ruby 3.1.4带--enable-shared编译选项、Node.js 18.17.0必须用nvm或nodesource源Ubuntu 默认nodejs包是 12.x、libicu-dev、libkrb5-dev、libxml2-dev、libxslt1-dev等 17 个 dev 包。漏一个bundle install就报cannot load such file -- openssl或gyp ERR! stack Error: Cant find Python executable python。我们踩过的坑Ubuntu 22.04 默认 Python 是 3.10但 GitLab 的assets:precompile脚本硬编码调用python2.7。解决方法不是装 python2已废弃而是创建软链接sudo ln -s /usr/bin/python3 /usr/bin/python2.7但这只是权宜之计。更稳妥的做法是在~/.bashrc里加export NODE_ENVproduction export RAILS_ENVproduction export PYTHON/usr/bin/python3并在gitlab/config/gitlab.yml中显式指定production: # ... node_options: --max_old_space_size4096实操心得别信网上“一键安装脚本”。我们试过 3 个 GitHub 上 star 过千的自动化脚本全部在bundle exec rake gitlab:setup步骤失败——原因全是 Ruby gem 版本冲突。GitLab 官方Gemfile.lock锁死了omniauth-google-oauth2必须是1.1.2但某脚本强行bundle update升到2.0.0导致 OAuth 登录白屏。永远用 GitLab 源码根目录下的Gemfile.lock执行bundle install --deployment --without development test这是唯一可靠路径。3.2 数据库与缓存服务PostgreSQL 14 的 5 个关键参数调优GitLab 的 PostgreSQL 不是“装上就能用”它有 5 个参数直接决定并发能力参数名默认值推荐值为什么调shared_buffers128MB4GBGitLab 重度依赖 shared memory 缓存表页 2GB 会导致频繁 disk readwork_mem4MB64MB复杂查询如合并请求 diff需大量 sort memory太小会写 temporary fileeffective_cache_size4GB12GB告诉查询规划器“系统有多少内存可用”影响 join 策略选择maintenance_work_mem64MB2GBVACUUM和CREATE INDEX时用GitLab 每天自动 vacuum太小会卡住max_connections100200GitLab 本身占 50 连接剩余 150 给 sidekiq、rails console、backup修改方法编辑/etc/postgresql/14/main/postgresql.conf然后重启sudo systemctl restart postgresql sudo gitlab-ctl reconfigure # 让 GitLab 重新读取 DB 配置注意shared_buffers不能超过物理内存的 25%。如果你只有 16GB 内存4GB 就是极限。超过会触发 OOM Killer 杀掉 postgres 进程。我们曾因设成 6GB半夜被 kill第二天早上所有项目页面显示 “502 Bad Gateway”。3.3 GitLab 核心服务启停逻辑理解gitlab-ctl背后的 systemd 本质gitlab-ctl start看似简单实则启动了 12 个 systemd 服务。你可以用systemctl list-dependencies gitlab-runsvdir.service查看完整依赖树。其中最关键的三个是gitlab-sidekiq-default.service处理异步任务发送邮件、更新搜索索引、CI job 调度。它不是单进程而是sidekiq-cluster默认启 3 个 worker。如果 CI 队列积压别急着加 worker 数先看 Redis 内存——redis-cli info memory | grep used_memory_human超 1.5GB 就要redis-cli config set maxmemory 2gb。gitlab-unicorn.serviceRails 应用服务器接收来自 gitlab-workhorse 的 HTTP 请求。它的unicorn.rb配置在/var/opt/gitlab/gitlab-rails/etc/unicorn.rb。关键参数worker_processes 4 # CPU 核数 - 14 核机器设 3 更稳 timeout 60 # 请求超时LFS 大文件上传建议 600 listen /var/run/gitlab/unicorn.socket, backlog: 1024gitlab-gitaly.service替代旧版gitlab-git-http-server的新服务所有 Git 操作clone/push/fetch都走它。它通过 gRPC 协议与 Rails 通信端口默认 8075。这是性能瓶颈高发区。如果git clone很慢先检查sudo gitlab-ctl tail gitaly是否有context deadline exceeded错误——说明 gRPC 超时需在/var/opt/gitlab/gitaly/config.toml中调大[storage] [storage.default] path /var/opt/gitlab/git-data/repositories [grpc] listen_addr localhost:8075 tls_listen_addr [grpc.keepalive] time 10s timeout 3s4. 实操过程与核心环节实现从零到第一个项目上线的完整流水线4.1 安装流程分 7 步每步附验证命令我们摒弃所有“一键脚本”坚持手动分步执行确保每一步都可验证、可回滚。以下是 Ubuntu 22.04 上的精确操作序列以 root 用户执行Step 1系统更新与基础工具安装apt update apt upgrade -y apt install -y curl wget gnupg2 ca-certificates software-properties-common # 验证lsb_release -a 应显示 Ubuntu 22.04Step 2添加 GitLab 官方 APT 源curl -fsSL https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash # 验证cat /etc/apt/sources.list.d/gitlab_gitlab-ce.list 应含 deb https://packages.gitlab.com/gitlab/gitlab-ce/ubuntu/ jammy mainStep 3安装 GitLab CE 包不启动apt install -y gitlab-ce16.11.5-ce.0 # 关键加版本号避免 apt upgrade 自动升到不稳定版 # 验证dpkg -l | grep gitlab-ce 应显示 16.11.5-ce.0Step 4生成初始配置gitlab-ctl reconfigure # 此步会生成 /etc/gitlab/gitlab.rb 并启动所有服务 # 验证gitlab-ctl status 应显示所有服务为 run无 downStep 5修改外部 URL 与 SSH 端口编辑/etc/gitlab/gitlab.rbexternal_url https://git.example.com gitlab_rails[gitlab_ssh_host] git.example.com gitlab_rails[gitlab_shell_ssh_port] 2222 # 避开系统 SSH 的 22 端口然后重载gitlab-ctl reconfigure gitlab-ctl restart # 验证curl -I https://git.example.com 应返回 302且 Location 头含 loginStep 6初始化管理员密码首次访问https://git.example.com页面会强制跳转到密码重置页。此时需用命令行生成初始密码sudo gitlab-rake gitlab:password:reset[admin] # 按提示输入新密码至少 8 位含大小写字母数字 # 验证用 admin / 你设的密码登录 Web UIStep 7创建第一个项目并测试 SSH 连接# 在客户端机器执行 ssh-keygen -t ed25519 -C your_emailexample.com cat ~/.ssh/id_ed25519.pub # 复制公钥粘贴到 GitLab Web UI 的 Profile SSH Keys # 测试 ssh -T -p 2222 gitgit.example.com # 应返回Welcome to GitLab, username!4.2 CI/CD 流水线实战用 .gitlab-ci.yml 实现嵌入式固件自动编译我们拿一个真实场景举例某嵌入式团队用 STM32CubeIDE 开发固件每次提交都要生成.bin文件供硬件测试。传统做法是开发者本地编译后git add firmware.bin极易遗漏。用 GitLab CI 可全自动完成。在项目根目录新建.gitlab-ci.ymlstages: - build - test - deploy variables: GIT_SUBMODULE_STRATEGY: normal build-stm32: stage: build image: armcc/gcc-arm-none-eabi:latest before_script: - apt-get update apt-get install -y make gcc-arm-none-eabi script: - cd Firmware make clean make all - cp Build/STM32F4xx_Discovery_Firmware.bin $CI_PROJECT_DIR/ artifacts: paths: - STM32F4xx_Discovery_Firmware.bin expire_in: 1 week test-firmware: stage: test image: python:3.9 script: - pip install pytest - pytest tests/ --tbshort allow_failure: true # 测试失败不阻断部署 deploy-to-hardware: stage: deploy image: alpine:latest before_script: - apk add openssh-client script: - scp -o StrictHostKeyCheckingno -P 2222 STM32F4xx_Discovery_Firmware.bin admin192.168.1.100:/tmp/ - ssh -o StrictHostKeyCheckingno -p 2222 admin192.168.1.100 flash_tool /tmp/STM32F4xx_Discovery_Firmware.bin only: - main实操心得CI runner 必须用dockerexecutor且config.toml中concurrent 44 核 CPU 最多跑 4 个 job。我们曾设concurrent 10结果 5 个 job 同时编译 GCC内存爆到 16GB系统直接 OOM。GitLab CI 不是无限资源池它和你的物理机共享内存、CPU、磁盘 IO。4.3 备份与恢复比gitlab-backup create多做的 3 件事gitlab-backup create只是基础。生产环境必须做三件事1. 备份 PostgreSQL 的物理文件WAL 归档编辑/etc/postgresql/14/main/postgresql.confarchive_mode on archive_command cp %p /var/opt/gitlab/backups/wal/%f这样即使 GitLab 备份损坏也能用pg_basebackup WAL 恢复到任意秒级时间点。2. 备份 Gitaly 的仓库元数据Gitaly 用 Protocol Buffer 存储仓库信息gitlab-backup不包含它。需手动备份rsync -avz --delete /var/opt/gitlab/git-data/repositories/ /backup/git-repos/3. 加密备份文件GitLab 备份包含数据库明文含用户密码 hash必须加密gitlab-backup create gpg --symmetric --cipher-algo AES256 /var/opt/gitlab/backups/168xxxxxx_gitlab_backup.tar # 输入密码后生成 .tar.gpg 文件恢复时顺序严格先解密gpg -d backup.tar.gpg backup.tar再gitlab-backup restore BACKUP168xxxxxx最后rsync恢复 Gitaly 仓库。5. 常见问题与排查技巧实录那些官方文档不会写的现场经验5.1 502 Bad Gateway不只是 Nginx 的锅现象Web 页面打开是 502但gitlab-ctl status显示所有服务都是 run。排查链路必须按顺序查 gitlab-workhorse 日志sudo gitlab-ctl tail gitlab-workhorse如果看到dial unix /var/opt/gitlab/gitlab-workhorse/socket: connect: no such file or directory说明 workhorse 没起来。原因是/var/opt/gitlab/gitlab-workhorse/socket目录权限不对执行sudo chown git:git /var/opt/gitlab/gitlab-workhorse sudo chmod 0751 /var/opt/gitlab/gitlab-workhorse sudo gitlab-ctl restart gitlab-workhorse查 unicorn 日志sudo gitlab-ctl tail unicorn如果看到E, [2024-05-20T10:22:33.123456 #12345] ERROR -- : worker0 PID:12345 timeout (60s 60s), killing说明 unicorn worker 卡死。此时不要restart先kill -USR2 12345发送优雅重启信号再看日志是否恢复。查 PostgreSQL 连接数sudo gitlab-psql -c SELECT * FROM pg_stat_activity WHERE state active;如果返回 200 行说明连接打满。立刻执行sudo gitlab-psql -c SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE state idle in transaction;注意gitlab-ctl restart是“核武器”它会杀掉所有进程再拉起可能导致正在运行的 CI job 中断、数据库事务回滚。日常维护优先用gitlab-ctl hup service平滑重启或gitlab-ctl kill service只杀进程不删 socket。5.2 Git Clone 慢90% 是 DNS 和 TCP 参数问题git clone https://git.example.com/group/project.git卡在Receiving objects: 1%。别急着怀疑网络先做三件事1. 检查 DNS 解析延迟GitLab 的gitlab-shell会反向解析客户端 IP 做访问控制。如果 DNS 服务器慢git clone就卡。在服务器上执行time nslookup 192.168.1.50 # 你的客户端 IP如果 500ms立刻在/etc/gitlab/gitlab.rb中禁用反向解析gitlab_rails[rack_attack_git_basic_auth] { enabled true, ip_whitelist [127.0.0.1], maxretry 300, findtime 60, bantime 3600 } gitlab_shell[check_ip] false # 关键禁用 IP 反查2. 调整 TCP keepaliveLinux 默认tcp_keepalive_time72002 小时而 GitLab 的 gitlab-workhorse 默认keepalive_timeout5秒。连接空闲 5 秒就被断客户端重连。在/etc/sysctl.conf加net.ipv4.tcp_keepalive_time 600 net.ipv4.tcp_keepalive_intvl 60 net.ipv4.tcp_keepalive_probes 3然后sysctl -p生效。3. 禁用 IPv6如果不用很多内网环境没配 IPv6 DNSgit clone会先试 IPv6超时后再切 IPv4白白浪费 3 秒。在/etc/gitlab/gitlab.rb加gitlab_rails[trusted_proxies] [127.0.0.1, 192.168.0.0/16] gitlab_rails[env] { DISABLE_IPV6 true }5.3 用户邮箱收不到激活邮件SMTP 配置的 4 个致命细节现象新用户注册后邮箱没收到激活链接/var/log/gitlab/gitlab-rails/production.log里有Net::SMTPAuthenticationError。不是密码错了而是四个细节Gmail/Outlook 等服务商要求 App Password不是账户密码。必须去 Google Account Security App passwords 生成 16 位密码。端口必须用 587TLS或 465SSL。用 25 端口会被大多数云厂商封。gitlab_rails[smtp_enable_starttls_auto] true必须设为 true。否则 Gmail 会拒收。发信域名必须和external_url一致。如果你external_url是https://git.example.com但 SMTPaddress设成smtp.gmail.comGmail 会认为是钓鱼邮件。正确配置示例Gmailgitlab_rails[smtp_enable] true gitlab_rails[smtp_address] smtp.gmail.com gitlab_rails[smtp_port] 587 gitlab_rails[smtp_user_name] yournamegmail.com gitlab_rails[smtp_password] abcd efgh ijkl mnop # 16 位 App Password含空格 gitlab_rails[smtp_domain] gmail.com gitlab_rails[smtp_authentication] login gitlab_rails[smtp_enable_starttls_auto] true gitlab_rails[smtp_tls] false gitlab_rails[smtp_openssl_verify_mode] peer实操心得测试邮件功能别用 Web UI 的“Test Settings”它只测连通性。要用 Rails console 真实发一封sudo gitlab-rails console Notify.test_email(testexample.com, Test Subject, Test Body).deliver_now如果报错console 会直接打印 SMTP 协议交互全过程比日志精准十倍。5.4 备份失败gitlab-backup create卡住的 3 个隐藏原因现象执行gitlab-backup create后终端无输出ps aux | grep backup显示进程存在但 CPU 为 0。原因往往不在 GitLab而在底层1./var/opt/gitlab/backups目录磁盘满df -h /var/opt/gitlab/backups查看。GitLab 备份时会先tar打包到内存 buffer再写磁盘。如果只剩 1GB 空间tar会卡死。解决方案清理旧备份find /var/opt/gitlab/backups -name *.tar -mtime 7 -delete。2. PostgreSQL 正在 autovacuumsudo gitlab-psql -c SELECT * FROM pg_stat_progress_vacuum;。如果返回一行说明 vacuum 正在进行gitlab-backup会等它结束。此时不要中断等vacuum完成通常几分钟。3. Gitaly 仓库文件被其他进程占用lsof D /var/opt/gitlab/git-data/repositories。如果看到git进程正clone或push备份会等待。生产环境建议在低峰期凌晨 2 点执行备份并加锁flock -x /tmp/gitlab-backup.lock -c gitlab-backup create6. 性能调优与扩展实践当用户数突破 500 时的 5 项必做改造6.1 数据库读写分离用 PgBouncer 降低连接风暴GitLab 16.x 默认每个 Rails 进程建 5 个 DB 连接10 个 unicorn worker 就是 50 连接。当用户数超 500sidekiq、CI runner、API 请求并发上来PostgreSQLmax_connections200很快打满。解决方案不是盲目加max_connections会吃光内存而是引入连接池 PgBouncer。安装 PgBouncerapt install -y pgbouncer配置/etc/pgbouncer/pgbouncer.ini[databases] gitlabhq_production host127.0.0.1 port5432 dbnamegitlabhq_production [pgbouncer] listen_addr 127.0.0.1 listen_port 6432 auth_type md5 auth_file /etc/pgbouncer/userlist.txt pool_mode transaction max_client_conn 1000 default_pool_size 20然后在/etc/gitlab/gitlab.rb中指向 PgBouncerpostgresql[enable] false gitlab_rails[db_host] 127.0.0.1 gitlab_rails[db_port] 6432 gitlab_rails[db_database] gitlabhq_production为什么用transaction模式因为 GitLab 的 SQL 都是短事务 100mstransaction模式复用连接最高效。session模式会为每个会话独占连接反而加剧连接耗尽。6.2 Gitaly 分布式部署把仓库存储搬到 NFS 或 Ceph单机 Gitaly 有上限当仓库数超 5000git fsck检查会拖慢整个系统。解决方案是 Gitaly Cluster——把 Gitaly 服务拆成多个节点用 Gitaly Server Gitaly Client 架构。拓扑如下Gitaly Server 1/data/gitaly-01存 group A 的仓库Gitaly Server 2/data/gitaly-02存 group B 的仓库GitLab Rails 节点不存仓库只通过 gRPC 调用两个 Server配置/var/opt/gitlab/gitaly/config.toml[[storage]] name default path /var/opt/gitlab/git-data/repositories [[storage]] name group-a path /data/gitaly-01 [[storage]] name group-b path /data/gitaly-02 [git] custom_hooks_dir /var/opt/gitlab/git