CentOS内网离线部署GitLab与Runner实战指南

发布时间:2026/10/12 9:45:38

CentOS内网离线部署GitLab与Runner实战指南 1. 项目背景与整体设计思路1.1 为什么会有离线部署这个需求做过企业内网交付的朋友应该都有体会很多生产环境压根就不给你连外网的机会。金融、能源、制造这类行业的内网隔离做得非常彻底服务器上连个yum源都指不到公网。但代码管理、CI/CD 流水线又必须得跑起来GitLab 作为一套相对完整的代码托管加流水线平台就成了很多团队的首选。问题在于GitLab 的官方安装脚本默认是要联网拉包的curl | bash那一套在内网里直接歇菜。所以这个项目的核心场景就是在一台完全断网的 CentOS 服务器上把 GitLab 装起来并且把 Runner 也注册好让流水线能正常跑。听起来简单但实际操作里坑不少——依赖包的版本匹配、RPM 包的依赖链、Runner 注册时的 token 获取方式、以及离线环境下 Docker 镜像怎么导入每一步都可能卡住。这篇文章适合两类人看一类是刚接触内网交付、需要快速把 GitLab 跑起来的运维同学另一类是在内网做过 CI/CD 但被依赖问题折腾过的老手可以对照看看有没有遗漏的细节。我会把整个流程拆成几个阶段每个阶段讲清楚为什么这么做、参数怎么选、以及我踩过的坑。1.2 整体方案选型与架构拆解离线安装 GitLab 有几种常见路子一种是直接用官方提供的 RPM 包另一种是 Docker 镜像离线导入。这两种方案各有适用场景我先把选型逻辑讲清楚。RPM 包方案适合物理机或虚拟机直接部署优点是性能损耗小、系统集成度高systemctl直接管理服务日志走journald或/var/log/gitlab。缺点是依赖链比较长CentOS 上需要提前把policycoreutils、openssh-server、postfix这些基础包补齐否则rpm -ivh会报一堆依赖错误。Docker 镜像方案适合已经有容器化基础的团队优点是环境隔离干净、迁移方便把镜像docker save成 tar 包拷进去docker load就行。缺点是内网如果没装 Docker还得先离线装 Docker而且 GitLab 容器对内存要求比较高至少 4GB 起步否则跑起来会各种 502。我这次选的是RPM 包方案原因是目标服务器是一台裸机 CentOS 7.9没有容器环境而且客户明确要求用系统服务管理方便他们自己的监控体系对接。Runner 则用了二进制安装的方式因为 Runner 本身比较轻量二进制包解压就能用没必要再走 RPM。整体架构是这样的一台 CentOS 7.9 作为 GitLab 主节点装 GitLab CE 版本另一台同网段机器作为 Runner 节点装gitlab-runner二进制注册到主节点的 GitLab 实例上。两台机器都不通外网所有安装包通过一个临时的 U 盘或内网文件服务器中转。注意GitLab 的版本选择很关键。CE 和 EE 的区别这里不展开内网用 CE 就够了。版本号建议选一个稳定的 minor 版本比如 16.x 的某个小版本不要追最新因为最新版可能引入新的依赖或者配置变更离线环境下排查成本很高。2. 离线环境下的依赖准备与包管理2.1 先搞清楚缺什么依赖清单梳理在联网机器上先把依赖关系摸清楚这一步偷懒后面会加倍还回来。我的做法是找一台和 target 环境完全一致的 CentOS 7.9 虚拟机联网状态下执行yum install gitlab-ce让 yum 自己把依赖树打出来然后记录所有被安装的包。GitLab CE 的核心依赖大概包括这几类基础系统包policycoreutils、policycoreutils-python、openssh-server、openssh-clients、postfix、cronie、curl、openssl等。Ruby 运行时GitLab 自带 embedded Ruby不需要系统单独装但 RPM 包里会依赖一些 lib 库比如libicu、libcurl、libxml2等。数据库GitLab 默认用 PostgreSQLRPM 包里已经捆绑了gitlab-postgresql不需要额外装系统级的 PostgreSQL。Redis同样捆绑在 RPM 里不需要单独装。这里有个经验不要试图手动一个个去rpm -ivh装依赖那样会陷入依赖地狱。正确做法是在联网机器上用yumdownloader或者repotrack把整个依赖树下载下来然后打包拷到内网。# 在联网机器上执行下载 gitlab-ce 及其所有依赖 yumdownloader --resolve --destdir/tmp/gitlab-offline gitlab-ce-16.11.0-ce.0.el7.x86_64如果yumdownloader不好使可以用repotrackrepotrack gitlab-ce-16.11.0-ce.0.el7.x86_64 -p /tmp/gitlab-offline下载完之后/tmp/gitlab-offline目录里会有几十个 RPM 包包括 GitLab 本体和所有依赖。把这些包全部拷到内网服务器的同一个目录下然后执行cd /tmp/gitlab-offline rpm -ivh *.rpm --nodeps --force注意--nodeps --force是最后手段正常情况下应该让 rpm 自己解析依赖顺序。如果依赖包齐全直接yum localinstall *.rpm更好yum 会自动处理安装顺序。只有在依赖确实齐全但 rpm 顺序报错时才用--nodeps强行装。2.2 系统层面的预配置装包之前有几项系统配置必须先做否则 GitLab 跑起来会出各种奇怪问题。关闭 SELinux。GitLab 的官方文档虽然说支持 SELinux但离线环境下 SELinux 的 policy 包往往不完整容易导致权限拒绝。我一般直接关掉setenforce 0 sed -i s/SELINUXenforcing/SELINUXdisabled/g /etc/selinux/config配置防火墙。GitLab 需要开放 80、443、22 端口。如果 22 端口已经被 sshd 占用可以把 GitLab 的 SSH 端口改成 2222或者直接用 80 端口做 HTTP 访问。内网环境我一般只开 80 和 2222firewall-cmd --permanent --add-port80/tcp firewall-cmd --permanent --add-port2222/tcp firewall-cmd --reload设置主机名和 hosts。GitLab 的external_url会用到主机名如果 DNS 解析不了Runner 注册时会连不上。建议在/etc/hosts里写死echo 192.168.1.100 gitlab.internal /etc/hosts hostnamectl set-hostname gitlab.internal调整系统资源限制。GitLab 对文件描述符和进程数有要求编辑/etc/security/limits.conf* soft nofile 65536 * hard nofile 65536 * soft nproc 65536 * hard nproc 65536这些配置看起来琐碎但少做一项后面就可能卡住。我遇到过因为没改nofile导致 GitLab 启动到一半就挂掉的情况日志里只报too many open files排查了半天。2.3 RPM 包安装与初始化依赖包和系统配置都就绪之后安装 GitLab 本体cd /tmp/gitlab-offline yum localinstall -y gitlab-ce-16.11.0-ce.0.el7.x86_64.rpm如果 yum 报依赖缺失说明前面的依赖包没下全回到联网机器重新repotrack。安装完成后GitLab 会自动创建gitlab-www、git、gitlab-redis、gitlab-psql等用户和组这些不用手动干预。接下来是初始化配置。编辑/etc/gitlab/gitlab.rb核心改这几项external_url http://gitlab.internal gitlab_rails[gitlab_shell_ssh_port] 2222 unicorn[worker_processes] 4 postgresql[shared_buffers] 512MBexternal_url决定了 GitLab 生成的克隆地址和 Web 入口必须和实际访问地址一致。worker_processes根据 CPU 核数来一般是核数加一但内网机器配置不高的话设 2 到 4 就够了。shared_buffers是 PostgreSQL 的内存参数给总内存的 25% 左右比较合适。改完之后执行重配置gitlab-ctl reconfigure这一步会跑 Chef 脚本把所有服务拉起来。第一次跑大概需要 3 到 5 分钟期间会初始化数据库、生成配置、启动 Nginx 和 Unicorn。如果卡住不动看/var/log/gitlab/reconfigure.log里的输出。实操心得reconfigure如果中途失败不要慌先看日志。常见原因是内存不够导致 PostgreSQL 起不来或者端口被占用。解决之后重新跑gitlab-ctl reconfigure即可Chef 是幂等的不会重复初始化。3. Runner 的离线安装与注册3.1 Runner 二进制包的获取与部署GitLab Runner 的安装比 GitLab 本体简单得多因为它是一个 Go 编译的静态二进制没有复杂的依赖链。在联网机器上下载对应的二进制包# 下载 gitlab-runner 二进制 curl -L --output /tmp/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64如果内网对 S3 域名有屏蔽也可以从 GitLab 官方仓库的 RPM 包里提取或者直接用yumdownloader下载gitlab-runner的 RPM 包然后rpm2cpio解压出二进制。把二进制拷到内网 Runner 节点上放到/usr/local/bin/cp gitlab-runner /usr/local/bin/ chmod x /usr/local/bin/gitlab-runner创建 runner 用户和安装服务useradd --comment GitLab Runner --create-home gitlab-runner --shell /bin/bash gitlab-runner install --usergitlab-runner --working-directory/home/gitlab-runner gitlab-runner start这里有个细节--working-directory指定的是 Runner 执行构建任务的工作目录默认在/home/gitlab-runner下。如果构建产物比较大建议把这个目录挂到独立的数据盘上避免把系统盘撑满。3.2 获取注册 Token 的两种方式Runner 注册需要 token这个 token 从 GitLab 那边获取。离线环境下有两种方式方式一项目级 Token。在 GitLab Web 界面进入具体项目Settings-CI/CD-Runners展开之后能看到Registration token。这种方式注册的 Runner 只对当前项目生效适合项目组自己管理。方式二实例级 Token。在 GitLab 的Admin Area-Overview-Runners里获取。这种方式注册的 Runner 对所有项目可用适合平台团队统一管理。我这次用的是实例级 Token因为客户希望所有项目共用一组 Runner方便统一维护。获取到 token 之后在 Runner 节点上执行注册gitlab-runner register \ --non-interactive \ --url http://gitlab.internal/ \ --registration-token 你的token \ --executor shell \ --description internal-runner-01 \ --tag-list build,deploy \ --run-untaggedtrue \ --lockedfalse参数解释一下--executor shell表示用 shell 执行器直接在宿主机上跑构建脚本适合内网环境简单直接。如果构建需要隔离环境可以用docker执行器但那样还得离线装 Docker 和导入镜像复杂度上升。--tag-list是给 Runner 打标签流水线里可以通过tags指定用哪个 Runner。--run-untagged表示没有标签的任务也能跑。注意--registration-token在 GitLab 16.x 之后有变化新版本引入了新的 runner authentication token 机制注册流程略有不同。如果用的是 16.11 之后的版本建议先查一下对应版本的注册文档避免 token 格式不匹配。3.3 验证 Runner 是否正常工作注册完成后在 GitLab 的Admin Area-Runners里应该能看到这个 Runner状态是绿色的online。如果显示offline先检查 Runner 服务是否在跑gitlab-runner status systemctl status gitlab-runner再看 Runner 的日志journalctl -u gitlab-runner -f常见问题是网络不通或者 token 过期。内网环境下确认 Runner 节点能curl通 GitLab 的地址curl -I http://gitlab.internal/如果返回 302 或 200说明网络没问题。如果 token 过期重新在 GitLab 界面生成一个再注册即可。验证 Runner 能跑任务的最简单方式是在项目里加一个.gitlab-ci.ymlstages: - test hello-job: stage: test tags: - build script: - echo Runner is working - hostname - date提交之后看流水线是否触发如果 Runner 正常这个 job 会秒过。如果卡在pending说明没有匹配的 Runner检查 tags 是否对得上。4. 常见问题排查与避坑经验4.1 安装阶段的典型报错离线装 GitLab 最容易出问题的就是依赖。我整理了一个速查表覆盖大部分场景报错信息原因解决方法Failed dependencies: policycoreutils-python is needed缺少 SELinux 管理工具从联网机器下载policycoreutils-python及其依赖error: unpacking of archive failed on file /opt/gitlab磁盘空间不足或权限问题检查/opt分区剩余空间至少留 5GBgitlab-ctl reconfigure卡在ruby_block内存不足PostgreSQL 起不来增加内存到 4GB 以上或调小shared_buffers502 Whoops, GitLab is taking too much time to respondUnicorn 启动超时检查unicorn[worker_timeout]默认 60 秒可调到 120Connection refused访问 80 端口Nginx 没起来看/var/log/gitlab/nginx/error.log通常是端口冲突这里重点说下内存问题。GitLab 官方建议至少 4GB 内存但实际跑起来如果开了 Prometheus 监控内存占用会更高。内网机器如果只有 2GB建议在gitlab.rb里关掉不必要的组件prometheus_monitoring[enable] false grafana[enable] false这两个关掉能省 500MB 左右内存对低配机器很友好。4.2 Runner 注册与执行中的坑Runner 这块我踩过的坑主要集中在网络和权限上。坑一Runner 连不上 GitLab。表现是注册时直接报connection refused或者timeout。排查顺序先ping通不通再curl端口通不通最后看 GitLab 的 Nginx 有没有监听正确端口。内网如果有防火墙策略确认 80 端口放行了。坑二构建任务权限不足。用 shell 执行器时构建脚本是以gitlab-runner用户跑的。如果脚本里要docker build或者写/opt目录权限会不够。解决办法是把gitlab-runner加入docker组或者用sudo提权需要在sudoers里配置免密。坑三构建产物占满磁盘。Runner 默认会保留最近的成功构建产物时间长了磁盘就满了。可以在config.toml里配置清理策略[[runners]] [runners.cache] MaxUploadedArchiveSize 0 [runners.shell] executor shell更彻底的方式是定期跑gitlab-runner的清理命令或者用gitlab-runner的--working-directory指向大容量分区。实操心得内网环境建议把 Runner 的并发数调低。默认concurrent 1如果机器配置一般不要盲目调高否则多个构建同时跑会把 CPU 和内存吃满。可以在/etc/gitlab-runner/config.toml里设置concurrent 2到4根据机器核数来定。4.3 离线升级的注意事项GitLab 的升级在离线环境下比安装还麻烦因为版本跨度不能太大。官方建议每次只升一个 minor 版本比如 16.11 - 16.12 - 16.13不能从 16.11 直接跳到 17.0。离线升级的步骤是在联网机器上下载目标版本的 RPM 包和依赖。备份当前 GitLab 数据gitlab-backup create。停止 GitLabgitlab-ctl stop。安装新版本 RPMrpm -Uvh gitlab-ce-新版本.rpm。重新配置gitlab-ctl reconfigure。启动gitlab-ctl start。升级过程中如果报数据库迁移错误看/var/log/gitlab/gitlab-rails/database_migrations.log。大部分情况是迁移脚本执行超时可以手动跑gitlab-rake db:migrate这个命令会重新执行未完成的迁移跑完再gitlab-ctl reconfigure即可。5. 内网 CI/CD 的后续扩展思路5.1 缓存与制品的离线管理内网 Runner 跑构建时如果每次都要从外网拉依赖那肯定不现实。常见的做法是在内网搭一个私有的包仓库比如 Nexus 或者 Artifactory把常用的 npm、Maven、PyPI 包缓存进去。Runner 的构建脚本里把源地址指向内网仓库这样既快又稳。GitLab 自带的 CI/CD 缓存功能也可以利用起来。在.gitlab-ci.yml里配置cache关键字把node_modules、.m2这些目录缓存到 Runner 本地cache: key: $CI_COMMIT_REF_SLUG paths: - node_modules/ - .m2/repository/这样第二次构建就能直接复用缓存不用重新下载依赖。注意缓存目录不要太大否则上传下载也耗时。5.2 多 Runner 的标签规划当 Runner 数量多起来之后标签规划就很重要。我的建议是按用途分build负责编译、打包。deploy负责部署到测试或生产环境。docker专门跑 Docker 构建的 Runner装了 Docker 环境。shell通用 shell 执行器跑一些简单的脚本任务。在.gitlab-ci.yml里通过tags指定deploy-job: stage: deploy tags: - deploy script: - ./deploy.sh这样不同任务会路由到不同的 Runner 上避免资源争抢。内网环境 Runner 数量有限标签规划清楚能省不少事。5.3 监控与日志的离线方案GitLab 自带的 Prometheus 在离线环境下其实也能用只是没法接外部的告警通道。我的做法是把 Prometheus 的数据保留周期调短然后通过gitlab-ctl自带的gitlab-ctl status和gitlab-ctl tail做日常巡检。如果需要更细的监控可以在内网搭一个 Grafana数据源指向 GitLab 的 Prometheus。Grafana 的离线安装和 GitLab 类似下载 RPM 包和依赖yum localinstall即可。Dashboard 可以用官方的 GitLab 模板导入 JSON 就行。日志方面GitLab 的日志默认在/var/log/gitlab/下按组件分目录。排查问题时我一般先看gitlab-rails/production.log和nginx/gitlab_access.log这两个覆盖了大部分 Web 请求和业务逻辑的异常。整个离线部署流程走下来最深的体会是准备工作比安装本身重要得多。依赖包下全、系统配置做对、token 提前拿到这三件事做好了安装过程基本就是一路回车。反过来如果依赖缺一个可能就要在rpm的报错里绕半天。内网环境没有搜索引擎可以随时查所以每一步都要提前想清楚把可能的问题扼杀在准备阶段。
延伸阅读

更多相关文章

2026/10/12 9:40:38

sklearn数据预处理与Pipeline实战:38维小样本建模避坑指南

1. 这个Kaggle老题到底在考什么:从数据形态反推建模逻辑“data-science-london-scikit-learn”这个标题乍看平平无奇,甚至有点拗口——它不像“Titanic生存预测”那样自带故事感,也不像“House Prices”那样直击业务痛点。但恰恰是这种看似“…

2026/10/12 9:40:38

OpenHarmony从零开发记事本:ArkTS状态管理与数据持久化实战

最近花了一个周末,在 OpenHarmony 上从零写了一个记事本 APP。开始之前,我以为这只是个“列表 输入框 本地存储”的小练习,真动手以后才发现,光是把 ArkTS 的状态管理、Stage 模型的生命周期和数据持久化串起来,就够…

2026/10/12 9:40:38

从时序预测到模型轻量化:工业AI落地的算法实战

1. 这件事为什么值得说:BPAA工业赛道到底考察什么先说说这次拿奖的背景。雪浪云在世界人工智能大会的BPAA(Best Practice in AI Application,即AI应用最佳实践)算法大赛工业赛道拿下全球十强。很多人听到这个奖项,第一…

2026/10/12 16:37:43

PyCharm手写BP神经网络求解Iris分类实战

简介:本资源是一份面向机器学习初学者与高校课程实践者的BP神经网络入门级实战项目,聚焦Iris经典数据集的三分类任务,完整呈现从理论理解到PyCharm环境编码实现的全流程。压缩包共4个文件(2个Python源码、1份Word实验报告、1个CSV…

2026/10/12 16:37:43

从动作游戏宏设置到模拟器调优:输入与渲染的底层逻辑

最近在玩家群和论坛里看到的几个高频话题,恰好都让我手痒:一是《仁王3》的情报出来之后,群里讨论得最热闹的居然不是难度设计,而是宏设置;二是《浪人崛起》和《战神3》这两款新旧动作游戏,总有人拿着各种模…

2026/10/12 16:37:43

Notepad++绿色版配置迁移与插件管理避坑指南

简介:这份资源是面向开发者与运维人员的 Notepad 工具包,适合需要频繁编辑项目配置文件、脚本与代码片段的技术人员使用。Notepad 体积轻巧、启动迅速,配合语法高亮与插件扩展,能显著提升日常文本处理与配置维护效率。压缩包共收录…

2026/10/12 16:32:42

MCS-51单片机硬件结构详解:从架构到实战的底层逻辑

1. 为什么还要啃MCS-51的硬件结构很多人一听“MCS-51”就皱眉,觉得这玩意儿是上个世纪的产物,现在都什么年代了,还讲它干嘛。我刚开始接触嵌入式的时候也是这个心态,觉得直接上手STM32或者ESP32多好,性能强、外设多、资…

2026/10/11 0:02:13

Python调用Gemini Structured Outputs实现工单路由门禁

客服工单最怕的不是模型“答错一句话”,而是它给出一段看起来合理的说明,程序却从中猜错优先级。通俗做法是:要求模型只交 JSON(JavaScript Object Notation,轻量数据格式),再让代码验证它。Gem…

2026/10/12 12:01:26

Spring Boot超市进销存系统毕设实战:从需求拆解到答辩通关

最近带的一个学生项目组里,有A同学跑来问我:选什么毕设题目最稳妥,既能让评审老师觉得工作量够,又不会在答辩时被问到语无伦次。我第一反应就是推荐基于Spring Boot的超市仓库管理系统——也就是超市进销存系统。这个题目乍一看平…

2026/10/12 12:54:07

Flutter StatefulWidget 生命周期核心解析

很多刚开始接触 Flutter 的朋友,在看完一堆“Hello World”和基础组件之后,大概率都会撞上同一堵墙:StatefulWidget 里那堆 initState、build、dispose 方法,到底什么时候被调用?为什么顺序是那样?在里面到…

2026/10/12 0:04:22

绝缘子缺陷检测数据集清洗与工业级训练实战指南

简介:本资源是面向电力AI研发人员、工业视觉工程师及智能巡检系统开发者的绝缘子缺陷检测专用YOLO格式数据集,解决无人机航拍场景下绝缘子破损、污闪、积雪等9类典型缺陷的精准识别与定位难题。数据集共2139张真实巡检图像(含训练/验证/测试集…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑