资讯详情

资讯详情

CentOS 7部署GitLab实战:从502故障排查到高危漏洞修复全解析

一个多月前帮朋友在一台CentOS 7服务器上部署GitLab原以为就是下载RPM、rpm -ivh一把梭结果从系统选型到启动排查整整折腾了大半天。这台机器是台2C2G的“老爷机”装完GitLab CE之后页面直接502后来一步步查日志、调内存、配swap才跑起来。今天把这次完整过程整理出来从硬件准备、安装路线选择、初始配置、启动失败排查到高危漏洞修复一次性讲透。文章适用于两类人一是准备在自己手头的CentOS服务器上搭GitLab的运维同学二是想在虚拟机里练手、但不知道从哪儿下手的新手。1. 先把需求理清楚这台CentOS服务器要准备到什么程度很多人拿到安装教程就急着敲命令结果装到一半发现磁盘不够、内存不足、yum源超时回头再折腾系统反而更慢。我建议动手前先花十分钟确认三件事硬件配置、系统版本、网络和时间同步。1.1 硬件门槛内存、CPU、磁盘的真实建议GitLab官方写的硬件要求不高但实际跑起来你会发现它是个“吃内存大户”。它默认会拉起PostgreSQL、Redis、Puma、Sidekiq、Nginx、Prometheus这些组件一整套下来2G内存根本不够舒服地跑。我按团队规模给一个参考表这是我反复装过的经验值场景配置建议说明个人练手/几人的小团队2核4G内存、40G以上磁盘需要关闭Prometheus并做内存优化否则容易50220人左右团队4核8G内存、100G磁盘比较舒服基本不用折腾50人以上团队8核16G内存、200G以上SSD建议单独挂数据盘给GitLab storage磁盘方面GitLab安装包解压到/opt/gitlab后大概占4~5G仓库数据、日志都放在/var/opt/gitlab。如果你有独立数据盘建议先把数据盘挂到/var/opt/gitlab或者至少给/opt和/var留足空间。别等到gitlab-ctl reconfigure一直卡住一查df -h发现/满了那就很被动了。提示2G内存的机器不是不能装但装完后一定要做两件事加swap、减小Puma并发。这个我在第4章会给出具体做法。1.2 系统版本与GitLab版本匹配为什么我还在用CentOS 7说实话CentOS 7已经停止官方维护了新项目我不太推荐继续用。但现实是很多公司里的老服务器、虚拟机上跑的就是CentOS 7一时半会儿换不了。这篇内容就是围绕CentOS 7展开的所以我默认你的环境是CentOS 7.x minimal。如果你跟我一样用的是minimal版装GitLab前第一件事不是装GitLab而是先确认yum源能不能用。CentOS 7停维护后默认的mirror.centos.org源已经失效会出现类似http://mirrors.aliyun.com/centos/7/os/x86_64/repodata/repomd.xml: [Errno -1]的报错。解决办法是把yum源切换到vault镜像比如清华的centos-vault/7.9.2009/os/x86_64。大致操作是编辑/etc/yum.repos.d/CentOS-Base.repo把baseurl指到vault路径问题就解决了。GitLab官方对系统的支持也有个时间线。我印象里GitLab CE还提供el7的RPM包到16.x这个阶段再往后的新版本官方就不再为CentOS 7发布安装包了。所以在CentOS 7上装GitLab没必要追最新版选一个16.x的补丁版本反而更稳。这个版本选择很重要直接决定后续漏洞修复的升级路径。1.3 网络、域名与时间同步的预先准备安装之前想好GitLab用什么地址访问。如果是内网使用可以直接用IP加端口比如http://192.168.1.10:8090如果买了域名提前把域名DNS解析到这台服务器。external_url这个配置后面第3章会详细说现在只需要记住事先规划好端口。还有一个很多人忽略的点时间同步。GitLab对服务器时间很敏感时间偏差太大会导致登录抛出异常、Git操作报证书或JWT验签失败。刚装的CentOS 7多半没有开启时间同步可以先用timedatectl看一下状态timedatectl status如果NTP synchronized是no就开启NTP同步或者装chronyyum install -y chrony systemctl enable chronyd --now chronyc sources -v看到^*开头的行就说明已同步到上游时间服务器。这一步虽然简单但能让后面少掉很多奇怪的坑尤其是后面要配合个人访问令牌、SSL证书的场景。2. 原生RPM和Docker两条安装路线我最终选了哪条装GitLab社区版主要有两条路线一条是在CentOS上直接用官方/镜像源提供的RPM包装另一条是跑Docker容器。热词里也有人在搜docker安装gitlab我把两条都讲一下并给出我的选择逻辑。2.1 两条路线的资源占用和维护成本对比原生RPM方式是把GitLab作为普通systemd服务安装到系统里由gitlab-ctl统一管理各组件。Docker方式是拉取gitlab/gitlab-ce镜像用容器跑一套完整的GitLab进程。对比项原生RPM安装Docker安装内存占用相对可控高一点容器本身还要占系统资源略高升级方式rpm -Uvh后reconfigure拉新镜像、重建容器备份恢复用gitlab-backup命令稍微繁琐还要处理volume与系统集成直接监听端口Nginx、SSH都原生需要做端口映射SSH端口冲突更明显适合人群服务器上不想再引入容器层追求稳定想隔离环境、换机器方便我最终选了原生RPM。原因很简单这台CentOS 7内存本来就不富裕再套一层Docker会增加开销而且GitLab升级时RPM方式只要换包再reconfigure流程上更成熟。如果你以后打算上K8s或者希望环境完全隔离选Docker也不是不行但新手我还是建议用原生RPM遇到问题好查日志资料也多。2.2 用清华镜像源安装GitLab CE的完整步骤官方推荐的安装方式是把packages.gitlab.com仓库加入yum源。但国内网络访问这个源很慢动不动超时。我的做法是直接用清华的GitLab CE镜像源速度快且稳定。在/etc/yum.repos.d/下新建gitlab-ce.repocat /etc/yum.repos.d/gitlab-ce.repo EOF [gitlab-ce] nameGitLab CE Repository baseurlhttps://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/ enabled1 gpgcheck0 EOF然后执行yum clean all yum makecache yum install -y gitlab-ce安装过程会自动下载所需的依赖包比如policycoreutils、openssh-server等在minimal系统上额外依赖比较多耐心等几分钟。装完以后GitLab相关的文件分布在主程序目录/opt/gitlab配置目录/etc/gitlab数据目录/var/opt/gitlab日志目录/var/log/gitlab注意/etc/gitlab/gitlab.rb是核心配置文件后续external_url、端口、内存参数都在这里改。改完必须执行gitlab-ctl reconfigure才会生效。如果你不想用yum源也可以直接下载RPM包离线安装。去清华镜像的gitlab-ce/yum/el7/目录挑一个16.x的版本比如wget https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/gitlab-ce-16.10.8-ce.0.el7.x86_64.rpm rpm -ivh gitlab-ce-16.10.8-ce.0.el7.x86_64.rpm离线包的好处是可以用u盘或内网传输适合不出网的环境。2.3 通过Docker安装的参考命令与注意事项如果你仍想用DockerCentOS 7上先确保Docker装好并且存储驱动正常。GitLab官方Docker镜像的参考启动命令如下docker run --detach \ --hostname gitlab.example.com \ --publish 8929:80 \ --publish 2289: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 \ gitlab/gitlab-ce:16.10.8-ce.0这里有三个细节容易踩坑--publish 8929:80表示把宿主机的8929端口映射到容器内的80端口访问就用http://IP:8929。SSH端口冲突在容器里更普遍因为容器内22端口已经被gitlab-shell占用了。你要把容器内的22映射成宿主机的其他端口比如2289否则宿主机的SSH功能会被干扰。CentOS 7上Docker的存储驱动建议用overlay2文件系统最好支持d_type否则可能导致容器内文件操作异常。Docker方式最大的优点是环境干净升级时换镜像版本就行卷目录保持不变数据不会丢。但如果你对容器原理不熟出了问题会感觉“隔着一层”日志不好定位所以我个人在CentOS 7上更倾向原生RPM。3. 第一次启动前必须改的配置external_url、防火墙和初始密码安装包装完后还没到“直接访问”的地步。GitLab默认用localhost地址启动你不改配置是没法通过IP访问的。这一步我把它拆成三块改URL、放防火墙、拿初始密码并换token。3.1 修改external_url与SSH端口冲突的解法编辑/etc/gitlab/gitlab.rb找到external_url这一行改成你的实际访问地址external_url http://192.168.1.10:8090如果你有域名就写成http://gitlab.example.com。注意URL结尾不要带斜杠否则reconfigure时Nginx配置会出问题。改完执行gitlab-ctl reconfigure gitlab-ctl restart等一两分钟访问http://192.168.1.10:8090/users/sign_in看是否能出来登录页。这里必须单独提醒一个SSH端口的大坑。GitLab安装完后会自动接管22端口作为Git SSH克隆通道。如果你的服务器本身也是用22端口SSH远程登录的装完GitLab之后你会发现服务器“SSH连不上了”——不是你密码错了是端口被GitLab的openssh占用了。解决办法有两个把系统sshd端口改到其他端口比如2222然后防火墙放行2222远程连接改用ssh -p 2222。保留系统sshd的22端口把GitLab的ssh端口改成别的比如在gitlab.rb里加一行gitlab_rails[gitlab_shell_ssh_port] 2289改完重新reconfigure推代码时SSH URL里就会带:2289。我的习惯是用方案二系统SSH维持22不变GitLab用2289互不干扰。3.2 防火墙放行与SELinux处理CentOS 7默认开了firewalld如果你不开端口外部访问大概率超时。假设你的external_url用的8090端口firewall-cmd --permanent --add-port8090/tcp firewall-cmd --reload firewall-cmd --list-ports如果给GitLab配置了SSH端口2289也一并放行firewall-cmd --permanent --add-port2289/tcp firewall-cmd --reload再一个就是SELinux。CentOS 7默认状态是enforcing虽然GitLab的安装包理论上带SELinux策略但实战中Nginx绑定非标准端口或者反向代理时偶尔会触发AVC拒绝。遇到Nginx起不来的情况又确认端口没被占用不妨先看SELinuxgetenforce如果是enforcing临时放行可以执行setenforce 0。这个方法只是临时重启失效。要彻底关闭就改/etc/selinux/config把SELINUXenforcing改成SELINUXpermissive。更规范的做法是用semanage把自定义端口加进http_port_tyum install -y policycoreutils-python semanage port -a -t http_port_t -p tcp 8090但说实话内部服务器如果对SELinux没硬性要求很多团队都是直接permissive省心。3.3 root初始密码获取、修改和个人访问令牌GitLab从较新版本开始不再使用“默认密码”而是安装时生成一个随机密码保存在/etc/gitlab/initial_root_password文件里。这个文件有效期是24小时24小时后会自动删除。所以拿到登录页后第一件事是去读这个文件cat /etc/gitlab/initial_root_password复制Password:后面的值用root账号登录。登录进去后马上在User Settings - Password里改成自己的密码。改完密码我强烈建议马上创建一个个人访问令牌PAT因为你后面用IDEA、PyCharm或者命令行HTTPS方式推送代码时GitLab会拒绝单纯用密码登录。热词里有“login failed. check api token or gitlab version”这类报错多半就是认证方式不对。创建令牌的位置在User Settings - Access Tokens名称随便填scope勾选api和read_repository过期时间自己设生成后立刻复制保存页面刷新后就不会再显示了。使用方式HTTPS克隆地址的用户名填root或你的用户名密码不是登录密码而是这个访问令牌很多人在IDEA里反复输入登录密码死活连不上就是因为没理解“HTTP克隆用PAT而不是密码”这一点。这个细节我每次都要跟同事强调。4. 启动失败是常态从502到converge卡住的完整排查链路如果你照上面步骤操作大部分能正常跑起来。但GitLab组件多启动失败的概率不低尤其是低配服务器。我把自己踩过的几个典型场景完整还原一遍你按这条链路排查会很快。4.1 内存不足导致502或Sidekiq退出我在2C2G机器上装完GitLab CE后访问首页直接502。先看服务状态gitlab-ctl status输出大概是run: alertmanager: (pid 1234) ... run: gitaly: (pid ...) ... run: postgresql: (pid ...) ... down: sidekiq: ...内存不足时最常见的表现就是sidekiq起不来或者Puma进程反复重启。再看日志tail -n 50 /var/log/gitlab/puma/current日志里全是内存分配失败或者进程被杀掉的记录。解决方案分两步第一步调低并发编辑/etc/gitlab/gitlab.rbpuma[worker_processes] 2 puma[min_threads] 1 puma[max_threads] 8 sidekiq[max_concurrency] 5 prometheus_monitoring[enable] falseprometheus_monitoring关闭后能省下不少内存对小机器非常有效。改完重新reconfigure并重启gitlab-ctl reconfigure gitlab-ctl restart第二步是加swap。2G内存裸跑GitLab实在太勉强给系统补一个2G的swap文件dd if/dev/zero of/swapfile bs1M count2048 chmod 600 /swapfile mkswap /swapfile swapon /swapfile echo /swapfile swap swap defaults 0 0 /etc/fstab这里不要用fallocate去创建swapfile某些文件系统上fallocate生成的文件作为swap会报“swapfile has holes”dd虽然慢一点但更稳。加完swap后再看free -m可用内存会宽裕很多。4.2 reconfigure收敛失败与PostgreSQL起不来的原因运行gitlab-ctl reconfigure时卡在Running handlers或者PostgreSQL相关步骤上是另一类高频问题。先看是不是磁盘满了df -h如果/使用率达到100%GitLab写入数据失败就会导致converge失败。解决办法是清理日志和旧包或者给相关目录扩容。/var/log/gitlab下的日志如果长期不轮转体积会涨得很快可以用journalctl --vacuum-time3d清理systemd日志GitLab自己的日志可以先删掉旧的.log.1这类归档文件。另一个常见原因是PostgreSQL目录权限错误。如果报错里出现Permission denied多半是/var/opt/gitlab/postgresql或/var/opt/gitlab/git-data的属主不对可以重置chown -R git:git /var/opt/gitlab/postgresql chown -R git:git /var/opt/gitlab/git-data然后重新reconfigure。如果PostgreSQL数据目录损坏最粗暴但有效的方案是彻底重新初始化。先确认没有重要数据然后rm -rf /var/opt/gitlab/postgresql/data gitlab-ctl reconfigure它会重新生成一个空的PostgreSQL数据库。这个操作会把所有GitLab内置数据库清空仓库数据如果是以文件形式存在的并不会丢但用户、项目记录都会没所以我只建议在“本来就没数据”的练手环境里做。排错时记得看日志关键日志路径PostgreSQL/var/log/gitlab/postgresql/currentRedis/var/log/gitlab/redis/currentGitLab整体服务管理日志gitlab-ctl命令本身会输出不少信息4.3 时间不同步引发的登录与push异常GitLab的很多操作跟时间戳绑定比如session、JWT以及和Gitaly之间的通信验证。服务器时间错误太离谱时会出现登录页提交后一直转圈或者Git推送时报证书/验签类错误非常容易误判成代码或网络问题。排查方法很简单date -R对比一下是不是跟实际时间差了几分钟以上。如果是就按第1章的做法启用chrony时间同步yum install -y chrony systemctl enable chronyd --now chronyc sources -v如果你的服务器在一个完全隔离的内网chrony连不上外部时间服务器那至少要在内网指定一台可信的时间服务器写入/etc/chrony.confserver 192.168.1.1 iburst然后systemctl restart chronyd。时间问题看起来小实际引发的故障现象很迷惑建议装完GitLab就先确认这一点。4.4 兜底手段备份命令和卸载重装的正确顺序很多人在排查过程中会把GitLab越弄越乱最后干脆卸载重装。卸载不是rm -rf /opt/gitlab就完了顺序很讲究gitlab-ctl stop rpm -e gitlab-ce这样会保留/etc/gitlab和/var/opt/gitlab下的数据。如果确认不需要保留数据再手动删除目录。盲目删目录很容易把后端数据库彻底毁掉后面想恢复都没得恢复。正确的习惯是重装之前先备份gitlab-backup create执行后会在/var/opt/gitlab/backups下生成一个*_gitlab_backup.tar文件。GitLab配置单独备份一份cp /etc/gitlab/gitlab.rb /etc/gitlab/gitlab-secrets.json /root/gitlab-config-backup/gitlab-secrets.json保存了GitLab的加密密钥以后升级迁移、恢复备份时都必须和数据库备份一起使用丢了它即使有备份也恢复不了。这一点我见过不少人栽过。5. 高危漏洞修复与版本升级别让GitLab裸奔装好GitLab不是终点GitLab历史上出过好几个高危远程命令执行和账号接管类漏洞热词里也有人在搜“gitlab高危漏洞修复方案”。这里我必须明确一个态度高危漏洞的修复核心是升级到官方修复版本而不是靠web防火墙或者“改配置”硬扛。5.1 为什么“不升级只改配置”救不了高危漏洞GitLab两次比较著名的高危漏洞CVE-2021-22205影响特定版本的GitLab CE/EE攻击者无需登录就能通过特定上传接口触发远程命令执行属于极其严重的问题。官方在13.10.3等版本中修复。CVE-2023-7028账号接管类漏洞攻击者可以构造密码重置请求把重置链接发给任意未验证邮箱从而实现账号接管。官方在16.x系列中修复。这类漏洞的共同点是“藏在代码逻辑里”不像弱口令那种可以靠修改密码策略缓解。你看再多的访问控制攻击入口还是存在。所以方案只有一条升级到官方声明包含修复的版本。对CentOS 7上的GitLab来说这就回到了第1章的版本选择问题如果你装的是16.x就升到16.x最新的补丁版如果你在生产环境用的是15.x甚至更老则要先规划好升级路径别直接跨大版本。5.2 小版本升级的正确步骤含备份升级前先备份这个习惯必须养成。执行备份gitlab-backup create确认备份完成后下载目标版本的RPM包。比如要升级到16.10.8wget https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/gitlab-ce-16.10.8-ce.0.el7.x86_64.rpm然后用rpm -Uvh更新不是-ivhrpm -Uvh gitlab-ce-16.10.8-ce.0.el7.x86_64.rpm-U会在安装前先处理已存在的旧版本避免版本冲突。升级包安装完成后GitLab会自动触发reconfigure如果没有自动触发就手动执行gitlab-ctl reconfigure gitlab-ctl restart gitlab-ctl status最后验证cat /etc/gitlab-release确认版本号已经是你想要的版本。这时候用浏览器登录简单跑一下“新建项目、提交代码”的流程确认业务正常。5.3 升级和降级都不能跳版本注意跨大版本的边界GitLab有一个很麻烦的约束大版本之间不能随便跳。比如从14.x直接升到17.x中间大概率会因为数据库结构不兼容而失败。正确做法是分段升级先升到14.x最新的补丁版再升到15.x最新的补丁版再升到16.x最新的补丁版需要的话再升到17.x每次升级前都做一次备份。生产环境一定要选在低峰期升级并且通过巡检确认没报错再离开。我自己的习惯是升级前把当前版本、目标版本、路径写成一个简单的检查清单贴在终端旁边一步一步打勾。比如当前版本是多少备份文件是否生成磁盘空间是否足够reconfigure是否正常结束登录、推送是否恢复这套流程看着繁琐但能避免“升级到一半发现数据库迁移失败、又退不回旧版本”的尴尬局面。如果让我给你这条安装链路排优先级我会说先保证内存和磁盘再谈安装速度先解决时间同步再谈登录体验先学会备份再谈升级。把这些基本功练熟之后再去折腾GitLab的各类集成和插件你会发现顺手很多。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →