1. 为什么要在鲲鹏架构上折腾GitLab
第一次在鲲鹏服务器上装GitLab的人,大概率会经历一个"以为十分钟搞定,结果折腾一整天"的过程。原因很简单:GitLab官方提供的安装包和镜像,绝大多数是面向x86_64架构的,而鲲鹏服务器跑的是aarch64(也就是ARM64)架构。这两者的指令集完全不同,x86的二进制包在鲲鹏上根本跑不起来,直接报"cannot execute binary file"或者"Exec format error"。
所以这件事的核心矛盾就一句话:你要在一个官方支持不完善的架构上,跑一个组件极其复杂的Ruby on Rails应用。GitLab不是一个单一程序,它是一整套服务栈——PostgreSQL、Redis、Nginx、Gitaly、Sidekiq、Puma等等十几个组件打包在一起,由omnibus-gitlab统一管理。任何一个组件在aarch64上出问题,整个安装就会卡住。
这篇文章适合三类人看:一是手里有鲲鹏服务器、需要自建代码托管平台的运维或开发;二是正在做国产化替代、需要把x86上的服务迁移到ARM架构的团队;三是对ARM生态感兴趣、想搞清楚"为什么有些软件在ARM上装起来这么费劲"的技术爱好者。我会把整个安装过程拆开讲,包括每一步为什么这么做、哪些地方最容易翻车、以及我实际踩过的坑。
需要提前说明的是,鲲鹏服务器上装GitLab,最稳妥的路线是用Docker跑官方或社区维护的aarch64镜像,而不是硬啃源码编译或者找rpm包。源码编译GitLab的依赖链长得离谱,光是Ruby、Node、Go、PostgreSQL的编译就能耗掉大半天,而且版本稍有不对就各种报错。下面我会以Docker方案为主线,同时把裸机安装的坑也讲清楚,方便你根据实际情况选择。
2. 动手前的环境盘点与架构确认
2.1 先确认你的机器到底是不是aarch64
很多人拿到服务器第一件事就是直接开装,结果装到一半发现架构不对。所以第一步永远是确认架构。登录服务器后执行:
uname -m如果输出是aarch64,那恭喜你,确实是ARM64架构。如果输出x86_64,那这篇文章的大部分内容你不需要看,直接按官方文档装就行。另外还可以用lscpu看更详细的信息:
lscpu | grep -i "architecture\|model name\|cpu(s)"鲲鹏920这类处理器,通常会显示ARMv8架构、几十个核心。这里有个细节要注意:鲲鹏的CPU核心数往往很多(比如48核、64核),但GitLab默认配置并不会自动吃满这些核心,后面配置的时候需要手动调整worker数量,否则就是浪费硬件。
2.2 操作系统与内核版本的选择
鲲鹏服务器上常见的系统有openEuler、麒麟、统信UOS、Ubuntu的ARM版本、CentOS的ARM版本等。我的建议是:优先选openEuler或者Ubuntu 20.04/22.04的ARM64版本,这两个系统的软件源对aarch64支持最完整,Docker安装也最省事。
内核版本建议5.10以上。低版本内核(比如4.x)在跑容器时,cgroup v2的支持不完整,会导致Docker资源限制失效,GitLab这种吃内存的大户很容易把整机拖垮。检查内核:
uname -r如果低于5.4,建议先升级内核再往下走。这一步别偷懒,我见过太多"装到一半容器莫名被杀"的案例,最后都是内核太老导致的。
2.3 硬件资源的底线要求
GitLab官方对硬件的要求是:最低4核8G内存,但那是x86的"能跑起来"标准。在鲲鹏上,由于部分组件的性能表现和x86有差异,我建议的底线是:
| 资源项 | 最低配置 | 推荐配置 | 说明 |
|---|---|---|---|
| CPU | 4核 | 8核以上 | 鲲鹏核心多,但单核性能弱于同代x86 |
| 内存 | 8GB | 16GB以上 | GitLab全家桶很吃内存,8G勉强 |
| 磁盘 | 50GB | 100GB SSD | 仓库和CI产物增长很快 |
| Swap | 4GB | 8GB | 内存不足时的救命稻草 |
特别提醒:内存低于8G基本别想跑起来,Puma和Sidekiq启动阶段就会OOM。如果只有8G,务必配好Swap,并且把GitLab的worker数量调低。
2.4 依赖环境的准备
不管走哪条路线,这些基础依赖都得先装好:
# openEuler / CentOS系 sudo dnf install -y curl policycoreutils openssh-server openssh-clients \ postfix cronie git wget vim # Ubuntu / Debian系 sudo apt update sudo apt install -y curl openssh-server ca-certificates tzdata \ postfix git wget vim时间同步也很关键,GitLab的token、证书校验都依赖准确的时间:
sudo timedatectl set-timezone Asia/Shanghai sudo systemctl enable --now chronyd # 或 systemd-timesyncd提示:如果服务器在内网、无法访问外网时间服务器,至少保证集群内所有节点时间一致,否则GitLab的CI runner注册会莫名其妙失败。
3. Docker路线:鲲鹏上最省心的安装方式
3.1 为什么Docker是首选
前面说了,GitLab官方omnibus包基本只发x86_64。虽然社区有人维护aarch64的rpm/deb包,但版本更新滞后、依赖容易冲突。而Docker镜像的好处是:镜像里已经把aarch64的二进制都编译好了,你只需要拉下来跑。目前gitlab/gitlab-ce官方镜像从某个版本开始已经提供了arm64的manifest,docker pull时会自动拉对应架构的版本。
先确认你的Docker能正确识别架构:
docker version docker info | grep -i "architecture"如果显示aarch64,说明Docker本身没问题。如果Docker还没装,openEuler上可以这样装:
sudo dnf install -y docker sudo systemctl enable --now dockerUbuntu上:
curl -fsSL https://get.docker.com | sudo sh sudo systemctl enable --now docker3.2 拉取镜像时的架构陷阱
这里有个非常隐蔽的坑:有些镜像虽然名字一样,但manifest里没有arm64版本。你docker pull的时候不会报错,但拉下来的是x86镜像,跑起来直接exec format error。所以拉完镜像后,一定要验证:
docker inspect gitlab/gitlab-ce:latest | grep -i architecture如果输出"Architecture": "amd64",那就说明拉错了,需要指定带arm64标签的版本,或者换用社区维护的ARM镜像。我实测下来,gitlab/gitlab-ce较新的tag基本都有arm64支持,但保险起见还是验证一下。
3.3 目录规划与数据持久化
容器化部署最忌讳的就是数据放在容器里,容器一删数据全没。所以先把宿主机目录规划好:
sudo mkdir -p /srv/gitlab/{config,logs,data} sudo chmod -R 755 /srv/gitlab这三个目录分别对应:
config:GitLab的主配置文件gitlab.rb,改配置就改这里logs:所有服务的日志,排错全靠它data:仓库数据、数据库、上传文件,这个最重要,必须定期备份
3.4 启动容器的完整命令与参数解读
sudo docker run --detach \ --hostname gitlab.example.internal \ --publish 443:443 --publish 80:80 --publish 2222:22 \ --name gitlab \ --restart always \ --volume /srv/gitlab/config:/etc/gitlab \ --volume /srv/gitlab/logs:/var/log/gitlab \ --volume /srv/gitlab/data:/var/opt/gitlab \ --shm-size 512m \ gitlab/gitlab-ce:latest逐个参数解释一下,这些都不是随便写的:
--hostname:这个值会写进GitLab的配置,影响克隆地址。一旦设定,后期修改很麻烦,所以一开始就要想好是用域名还是IP。--publish 2222:22:把容器的SSH端口映射到宿主机2222,因为宿主机22端口通常被系统sshd占用了。后面git clone走SSH时,地址会变成ssh://git@host:2222/...。--shm-size 512m:这个参数在鲲鹏上尤其重要。默认容器共享内存只有64M,PostgreSQL在ARM上跑的时候对共享内存更敏感,不调大会频繁报错。--restart always:服务器重启后容器自动拉起,生产环境必加。
3.5 首次启动的等待与验证
容器起来后别急着访问,GitLab首次启动要初始化数据库、编译资源,在鲲鹏上这个过程可能比x86慢不少,10到20分钟都正常。用这个命令盯进度:
sudo docker logs -f gitlab看到类似gitlab Reconfigured!的字样,基本就好了。然后浏览器访问服务器IP,会跳转到设置root密码的页面。如果页面打不开,先检查:
# 容器是否在跑 sudo docker ps | grep gitlab # 端口是否监听 sudo ss -tlnp | grep -E "80|443|2222" # 健康检查 sudo docker exec -it gitlab gitlab-ctl status4. 裸机安装路线与那些绕不开的坑
4.1 什么时候不得不走裸机
Docker虽然省心,但有些场景确实用不了:比如公司安全策略禁止容器、或者需要极致性能不想有容器开销、又或者要深度定制某些组件。这时候就得走裸机安装。裸机安装aarch64版GitLab,主要有两条路:用社区维护的aarch64 rpm/deb包,或者从源码编译。
社区包的好处是省事,坏处是版本可能落后、更新不及时。源码编译的好处是可控,坏处是——真的非常折腾。我建议优先找社区包,实在找不到匹配版本再考虑编译。
4.2 依赖链的完整梳理
GitLab omnibus在aarch64上安装,底层依赖包括:
- Ruby:GitLab主体是Rails应用,需要特定版本(比如3.x)
- PostgreSQL:数据库,版本要和GitLab要求匹配
- Redis:缓存和队列
- Node.js:前端资源编译
- Go:Gitaly、GitLab Shell等组件是Go写的
- Git:版本不能太老,否则某些功能不支持
这些依赖如果一个个手动装,版本冲突能让人崩溃。所以omnibus包的价值就在于它把这些都打包好了。但aarch64的omnibus包,社区维护的版本往往只覆盖部分GitLab版本,选版本时要看清楚。
4.3 编译安装的实操要点
如果真要编译,核心步骤大致是:
# 1. 装基础编译工具 sudo dnf groupinstall -y "Development Tools" sudo dnf install -y cmake libicu-devel openssl-devel libcurl-devel \ libxml2-devel libxslt-devel readline-devel zlib-devel # 2. 编译Ruby(以3.1为例) wget https://cache.ruby-lang.org/pub/ruby/3.1/ruby-3.1.4.tar.gz tar -xzf ruby-3.1.4.tar.gz && cd ruby-3.1.4 ./configure --disable-install-doc --enable-shared make -j$(nproc) && sudo make install # 3. 编译Go、Node等 # ...(略,每个都要单独处理)这里的关键经验是:make -j$(nproc)在鲲鹏上要慎用。鲲鹏核心多,全开并行编译会瞬间吃满内存,导致编译进程被OOM Killer干掉。建议用-j8或者-j16这种保守值,宁可慢一点也别崩。
4.4 裸机安装后的服务管理
裸机装完后,服务管理靠gitlab-ctl:
sudo gitlab-ctl status # 查看所有服务状态 sudo gitlab-ctl reconfigure # 重新加载配置 sudo gitlab-ctl restart # 重启全部 sudo gitlab-ctl tail # 实时看日志裸机模式下最容易出问题的是权限。GitLab涉及多个系统用户(git、gitlab-www、gitlab-redis等),如果目录权限不对,会出现"服务显示running但功能不可用"的诡异情况。排查时重点看/var/log/gitlab/下各服务的日志。
5. 性能调优:让鲲鹏跑得更顺
5.1 针对ARM架构的worker数量调整
GitLab默认的worker数量是按x86的核数经验值设的,在鲲鹏上直接套用会出问题。编辑/srv/gitlab/config/gitlab.rb(Docker路线)或/etc/gitlab/gitlab.rb(裸机路线),调整:
# Puma worker数量,建议设为CPU核数的一半到三分之二 puma['worker_processes'] = 8 # Sidekiq并发,ARM上单核弱,别设太高 sidekiq['max_concurrency'] = 16 # PostgreSQL共享缓冲区,按内存的1/4设 postgresql['shared_buffers'] = "4GB" # 数据库最大连接数 postgresql['max_connections'] = 300改完执行gitlab-ctl reconfigure生效。注意:reconfigure过程在鲲鹏上可能要好几分钟,别以为卡死了就中断。
5.2 内存与Swap的配合策略
GitLab是内存大户,16G内存跑起来,日常占用大概在8到12G之间。如果内存紧张,除了加Swap,还可以关掉一些非必需组件:
# 不用容器镜像仓库就关掉 registry['enable'] = false # 不用K8s集成就关掉 gitlab_kas['enable'] = false # 不用Prometheus监控就关掉 prometheus_monitoring['enable'] = false关掉这些能省下2到3G内存。但Prometheus关掉后,GitLab自带的监控面板就没数据了,这个取舍要自己权衡。
5.3 磁盘IO的优化
GitLab对磁盘IO很敏感,尤其是Gitaly读写仓库的时候。如果用的是机械盘,建议:
- 把
/var/opt/gitlab单独挂一块SSD - 调整文件系统挂载参数,加上
noatime - 定期清理CI产物和旧的备份文件
# 查看磁盘IO情况 iostat -x 2 # 如果 %util 长期接近100%,说明IO是瓶颈6. 踩坑实录:那些让我熬夜的问题
6.1 容器启动后一直重启
这是最常见的现象。docker ps看到容器状态是Restarting,日志里反复刷某个错误。排查顺序:
- 先看内存:
free -h,如果内存耗尽,容器会被杀 - 再看日志:
docker logs gitlab,找第一个ERROR - 检查目录权限:
ls -la /srv/gitlab/data,属主不对会导致初始化失败
我遇到过一次,原因是宿主机/srv/gitlab/data目录属主是root,但容器内GitLab用git用户写,权限不够。改成chown -R 998:998 /srv/gitlab/data(998是容器内git用户的UID)就好了。
6.2 502错误与Puma超时
访问页面报502,通常是Puma没起来或者超时。先看Puma日志:
sudo docker exec -it gitlab tail -f /var/log/gitlab/puma/puma_stdout.log如果是启动超时,可以在配置里加大超时时间:
puma['worker_timeout'] = 120ARM上Puma启动确实比x86慢,默认60秒有时候不够。
6.3 Git clone走SSH失败
这个坑很典型。容器把22端口映射到了2222,但GitLab生成的克隆地址默认还是22端口。解决办法有两个:一是改配置里的gitlab_rails['gitlab_shell_ssh_port'] = 2222,二是让用户手动用2222端口。前者更友好,改完reconfigure即可。
6.4 备份恢复时的架构差异
如果你是从x86的GitLab备份,想恢复到鲲鹏上,理论上可行,但要注意:备份文件里包含数据库dump和仓库数据,这些是架构无关的,所以能恢复。但恢复后要重新reconfigure,让所有二进制重新适配aarch64。我实测过跨架构恢复,只要GitLab版本一致,基本没问题。
7. 日常维护与升级的注意事项
7.1 备份策略
GitLab自带备份命令:
sudo docker exec -it gitlab gitlab-backup create备份文件默认在/var/opt/gitlab/backups,对应宿主机/srv/gitlab/data/backups。注意:这个命令不备份配置文件,gitlab.rb和gitlab-secrets.json要单独备份,否则恢复后密钥对不上,用户登录会出问题。
7.2 升级路径
GitLab升级不能跨大版本,必须按官方升级路径一步步来。在鲲鹏上升级,Docker路线相对简单:拉新镜像、停旧容器、用同样的volume起新容器。但升级前一定要备份,而且升级后要留足时间让数据库迁移完成,ARM上迁移可能比x86慢一倍。
7.3 监控要点
日常盯这几个指标就够了:
| 指标 | 查看方式 | 告警阈值 |
|---|---|---|
| 内存使用 | free -h | 超过85% |
| 磁盘使用 | df -h | 超过80% |
| 容器状态 | docker ps | 非Up状态 |
| 服务健康 | gitlab-ctl status | 有down |
我个人在实际维护中的体会是,鲲鹏上跑GitLab,最大的敌人不是性能不够,而是内存和IO的突发峰值。平时看着很稳,一到多人同时push大仓库或者跑CI,内存瞬间飙高。所以监控和Swap配置一定要提前做好,别等出事了再补。
最后分享一个小技巧:如果团队规模不大(十几个人),其实可以考虑用Gitea这类轻量级方案替代GitLab,在鲲鹏上跑起来轻松得多,资源占用可能只有GitLab的十分之一。但如果需要完整的CI/CD、代码审查、制品库这些企业级功能,那GitLab还是绕不开的选择,把上面的调优做扎实,鲲鹏一样能扛得住。