ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

GitLab Runner 生产级部署与 dotnet8 CI/CD 实战指南

GitLab Runner 生产级部署与 dotnet8 CI/CD 实战指南 1. 为什么今天还要亲手部署 gitlab-runner它早不是“装个包就完事”的玩具gitlab-runner 这个词最近半年在我们团队的站会上出现频率直逼 daily standup 的“阻塞项”——不是因为它难而是因为太多人把它当成 CI/CD 流水线里一个可有可无的“搬运工”直到某次生产环境镜像构建失败、dotnet8 应用发布卡在 job pending 状态超过47分钟运维同事翻遍 GitLab UI 才发现那个标着“shared-runner”的节点其实在三个月前就被误删了系统证书而新注册的 runner 始终没通过 TLS 验证。那一刻我才意识到gitlab-runner 不是配置文件里一行tags: [docker]就能自动跑起来的黑盒它是整个 pipeline 的物理执行层是代码从 commit 到容器上线之间唯一踩在真实机器上的那只脚。你搜到的“gitlab-runner 自动化部署 dotnet8”“docker 镜像构建与自动化部署实践”这些热词背后藏着一个被严重低估的事实90% 的 CI/CD 故障根源不在.gitlab-ci.yml的语法错误而在 runner 本身的执行环境失配、权限错位或资源隔离失效。比如 dotnet8 构建要求 host 系统安装 .NET SDK 8.0.300但默认 Ubuntu 22.04 的 apt 源只提供 6.0再比如用 docker executor 时runner 宿主机的 Docker daemon 若未启用--userns-remapjob 容器内 root 用户会直接映射为宿主机 root这在金融类项目中属于一票否决的安全红线。这些细节官方文档不会主动提醒你GitLab UI 更不会弹窗警告——它只会安静地把 job 挂在 pending 状态等你花三小时查日志。所以这篇不是“手把手教你注册 runner”的入门指南。它是我在过去18个月里为5个不同行业客户含两个等保三级系统部署、调优、排障 gitlab-runner 的实战笔记。我会告诉你什么时候该用 shell executor 而不是 docker为什么concurrent 1在高并发流水线里反而是最优解如何让 runner 在不暴露宿主机 Docker socket 的前提下安全构建镜像以及最关键的——当 pipeline 显示 “This job is stuck because you don’t have any active runners that can execute it” 时真正该检查的三个冷门位置。如果你正被 ISP pipeline 的超时问题困扰或者刚升级 dotnet8 后所有 build job 都报dotnet: command not found那接下来的内容就是你省下明天上午两小时排查时间的钥匙。2. 核心设计逻辑为什么必须放弃“一键安装”回归手动部署本质2.1 三种 executor 的底层差异决定了你的部署策略gitlab-runner 的 executor 不是功能开关而是执行模型的根本切换。很多人以为选 docker 就是“更现代”选 shell 就是“过时”这种认知直接导致后续所有配置走偏。shell executorrunner 进程以指定用户身份如gitlab-runner直接在宿主机执行命令。它的优势在于零虚拟化开销、完全继承宿主机环境变量和 PATH特别适合 dotnet8 这类需要全局 SDK 的场景。但代价是所有 job 共享同一套系统状态一个 jobapt install -y nodejs可能污染下一个 job 的依赖树。因此我只在两类场景强制用 shell一是等保要求禁止容器化构建的政务系统二是需要 GPU 加速训练模型的 AI pipeline因为 nvidia-docker 插件在某些 kernel 版本下与 docker executor 冲突。docker executor这是当前最主流的选择但它的核心陷阱在于“你以为的隔离其实并不彻底”。runner 启动的 job 容器默认使用--networkhost模式除非显式配置network_mode这意味着容器内localhost指向的是宿主机网络栈而非容器自身。我们曾遇到一个 bugJava 应用在 job 中调用http://localhost:8080访问本地 mock server结果请求被路由到宿主机的 nginx而非容器内的 wiremock。解决方案不是改代码而是在config.toml中强制设置network_mode bridge并为每个 job 分配独立子网。kubernetes executor适合大规模多租户场景但它的复杂度呈指数级增长。光是 service account 的 RBAC 权限配置就足够写一篇独立文档。我们给某电商客户部署时发现其 k8s 集群启用了 Pod Security AdmissionPSA而默认 runner 的 pod template 没有设置securityContext.runAsNonRoot: true导致所有 job 创建失败。这类问题无法通过gitlab-runner register交互式流程解决必须手动编辑config.toml的kubernetessection。提示不要被“executor 类型”迷惑。真正决定部署方式的是你的执行上下文约束——是必须复用宿主机已有的 dotnet8 SDK还是需要严格隔离的构建环境或是已有 k8s 集群需统一纳管先回答这三个问题再选 executor否则后续所有优化都是空中楼阁。2.2 注册模式选择shared vs. specific本质是权限边界的划分GitLab 提供两种 runner 注册方式shared所有项目可见和 specific绑定单个项目。很多团队盲目追求 shared认为“省事”结果埋下巨大隐患。shared runner 的致命缺陷在于tag 绑定失效。当你在.gitlab-ci.yml中写tags: [dotnet8, linux]GitLab 会将 job 分发给所有同时匹配这两个 tag 的 runner。但如果某个 shared runner 的config.toml中漏配了dotnet8tag它仍会接收 job只是执行时因找不到 dotnet 命令而失败。更糟的是GitLab UI 的 runner 列表页不会高亮显示“缺失 tag”你只能靠肉眼比对。specific runner 则完全不同。它与项目强绑定注册时生成的 token 仅对该项目有效。这意味着权限最小化runner 只能访问该项目的仓库、变量、密钥配置可追溯每个项目的 runner 配置独立存储升级 dotnet8 时只需更新对应项目的 runner不影响其他项目故障隔离某个项目 pipeline 卡住不会拖垮整个 shared pool。我们在某银行核心系统迁移时将 12 个微服务拆分为 12 个 specific runner每个 runner 独立安装对应版本的 JDK、Maven、Node.js。当其中一个服务需紧急升级 Node.js 18我们只重启该 runner其余 11 个服务完全不受影响。这种“分而治之”的思路比任何高可用架构都更可靠。2.3 并发模型concurrent 参数不是性能指标而是资源闸门config.toml中的concurrent 10常被误解为“支持 10 个 job 并行”。实际上它定义的是 runner 进程最多创建多少个执行器实例executor instances而每个实例的资源消耗由 executor 类型决定shell executor每个 instance 占用一个 shell 进程内存开销约 5MBCPU 占用取决于 job 本身docker executor每个 instance 启动一个容器除容器自身外Docker daemon 还需额外 100MB 内存管理容器生命周期kubernetes executor每个 instance 创建一个 podk8s apiserver 和 scheduler 会产生可观的 API 负载。我们曾在线上环境将concurrent设为 20结果发现 runner 进程频繁 OOM kill。排查后发现docker executor 下20 个并发容器启动时Docker daemon 的内存峰值达 3.2GB远超宿主机 4GB 总内存。最终方案是将concurrent降为 4并在[[runners]]section 中添加[runners.docker] # 限制每个容器最大内存防止单个 job 耗尽资源 memory 1g memory_swap 2g # 强制使用 cgroups v2避免旧版内核的资源隔离缺陷 cgroup_parent gitlab-runner.slice这个配置让 runner 主动做资源守门员而不是等系统 kill。3. 实操细节从零开始部署一个生产级 gitlab-runner以 docker executor 为例3.1 环境准备操作系统与依赖的隐形门槛别急着curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh | sudo bash。这个一键脚本在生产环境有三大隐患第一它默认安装最新版 runner而 GitLab CE 15.11 与 runner 16.0 存在 TLS handshake 兼容性问题第二它将二进制文件放在/usr/bin/gitlab-runner但 systemd service 文件却硬编码了/usr/local/bin/gitlab-runner路径第三它忽略内核参数调优导致高并发下fork()失败。我们采用手动部署步骤如下选择稳定版本根据 GitLab 版本查兼容矩阵。例如 GitLab CE 16.2 对应 runner 最佳版本是 16.1.0非最新 16.3.0。下载地址https://gitlab-runner-downloads.s3.amazonaws.com/v16.1.0/debian/bullseye/arm64/gitlab-runner_16.1.0_arm64.deb注意架构匹配。预检内核参数docker executor 重度依赖 overlayfs 存储驱动而 Debian 11 默认使用 btrfs。执行# 检查当前存储驱动 docker info | grep Storage Driver # 若非 overlay2需修改 /etc/default/grub # GRUB_CMDLINE_LINUX... overlay2.override_kernel_check1 # 然后 update-grub reboot创建专用用户与组避免使用 root 或 gitlab-runner 默认用户。sudo useradd -m -s /bin/bash -c GitLab Runner gitlab-runner-prod # 创建 runner 工作目录属主设为该用户 sudo mkdir -p /var/lib/gitlab-runner-prod sudo chown gitlab-runner-prod:gitlab-runner-prod /var/lib/gitlab-runner-prod安装 Docker CE 24.0.5不是最新版而是经过验证的 LTS 版本。关键点在于禁用containerd的systemdcgroup 驱动改用cgroupfs# 编辑 /etc/containerd/config.toml [plugins.io.containerd.grpc.v1.cri.containerd.runtimes.runc] # 注释掉 systemd_cgroup true # 添加 [plugins.io.containerd.grpc.v1.cri.containerd.runtimes.runc.options] SystemdCgroup false sudo systemctl restart containerd注意这一步常被跳过但它是解决 “docker: Error response from daemon: cgroups: cannot find cgroup mount destination” 的根本原因。systemd cgroup 驱动在某些云厂商定制内核下存在路径解析缺陷。3.2 注册 runner交互式注册的五个致命陷阱sudo gitlab-runner register看似简单但每个选项都暗藏玄机Please enter the gitlab-ci coordinator URL必须输入 GitLab 实例的内部网络可达地址而非浏览器访问的域名。例如 GitLab 运行在10.10.20.5:8080即使你通过https://gitlab.example.com访问这里也必须填http://10.10.20.5:8080。否则 runner 会因 DNS 解析失败卡在 registration 步骤。Please enter the gitlab-ci token这个 token 在 GitLab 项目 Settings CI/CD Runners 页面获取。切记shared runner token 在 Admin Area Overview Runners而 specific runner token 在项目级页面。混用会导致 403 Forbidden。Please enter the gitlab-ci description不要填 “runner-01”。按用途命名如 “dotnet8-builder-prod” 或 “docker-build-node16”。GitLab UI 的 runner 列表页按 description 排序清晰命名能避免误操作。Please enter the gitlab-ci tags这是最易出错的环节。多个 tag 用英文逗号分隔不能有空格。正确dotnet8,linux,prod错误dotnet8, linux, prod空格会导致 tag 匹配失败。我们曾因此浪费 2 小时排查为何 job 总是 pending。Please enter the executor选择docker后系统会问Default Docker image。这里填什么填alpine:latest是新手常见错误。alpine 缺少 glibc而 dotnet8 runtime 依赖它。正确答案是mcr.microsoft.com/dotnet/sdk:8.0-jammy-amd64Ubuntu 22.04 基础镜像预装 dotnet8 SDK。注册完成后/etc/gitlab-runner/config.toml自动生成。但此时还不能启动必须手动编辑。3.3 config.toml 深度调优让 runner 真正“生产就绪”默认生成的config.toml是开发环境配置生产环境需至少修改以下七处# 全局配置 concurrent 4 check_interval 10 # 关键禁用默认的 cache s3 backend改用本地路径 [cache] type s3 # 注释掉 s3 配置启用本地 cache [cache.s3] # server_address s3.amazonaws.com [cache] # 重定义为本地 type directory path /var/lib/gitlab-runner-prod/cache [[runners]] name dotnet8-builder-prod url http://10.10.20.5:8080 token xxx executor docker # 关键限制 job 超时避免无限循环占用资源 timeout 3600 # 关键设置工作目录避免 job 在 /root 下执行 working_directory /home/gitlab-runner-prod/builds [runners.docker] # 必须指定基础镜像覆盖注册时的 default image mcr.microsoft.com/dotnet/sdk:8.0-jammy-amd64 # 关键禁用 privileged 模式除非绝对必要 privileged false # 关键挂载宿主机 docker socket 时使用只读 volumes [/cache, /var/run/docker.sock:/var/run/docker.sock:ro] # 关键设置容器 ulimit防止 fork bomb ulimits [ {name nofile, hard 65536, soft 65536}, {name nproc, hard 4096, soft 4096} ] # 关键启用 health check自动剔除失联容器 health_check true # 关键设置 dns避免容器内域名解析失败 dns [10.10.20.1, 8.8.8.8] [runners.cache] # 启用本地 cache加速 nuget restore Type local Path /var/lib/gitlab-runner-prod/cache其中volumes [/var/run/docker.sock:/var/run/docker.sock:ro]是 docker executor 的灵魂。:ro表示只读挂载这是安全底线——runner 可以调用 Docker API 构建镜像但无法删除宿主机的容器或修改 daemon 配置。3.4 dotnet8 专项适配解决 SDK 版本与运行时冲突部署 dotnet8 pipeline 时.gitlab-ci.yml常见写法build: stage: build image: mcr.microsoft.com/dotnet/sdk:8.0-jammy-amd64 script: - dotnet restore - dotnet publish -c Release -o ./publish但实际运行时可能报错The specified framework Microsoft.NETCore.App, version 8.0.0 was not found.。原因在于SDK 镜像包含编译工具链但未预装 runtime。解决方案有两个在 job 中显式安装 runtime推荐script: - apt-get update apt-get install -y dotnet-runtime-8.0 - dotnet restore - dotnet publish -c Release -o ./publish自定义基础镜像更优FROM mcr.microsoft.com/dotnet/sdk:8.0-jammy-amd64 RUN apt-get update apt-get install -y dotnet-runtime-8.0 # 复制 nuget.config 加速 restore COPY nuget.config /root/.nuget/NuGet/NuGet.Config构建并推送到私有 registry然后在config.toml中设image your-registry/dotnet8-builder:1.0我们选择方案2因为避免每次 job 都执行apt-get install节省 45 秒nuget.config预配置了公司内部 feedrestore 速度提升 3 倍镜像层缓存使后续构建更快。4. pipeline 实战从 gitlab-ci.yml 到镜像推送的全链路解析4.1 一个真实的 dotnet8 pipeline 示例以下是某支付网关服务的.gitlab-ci.yml它完整覆盖了构建、测试、镜像打包、安全扫描、部署全流程stages: - build - test - package - deploy variables: # 全局变量避免硬编码 DOCKER_REGISTRY: registry.example.com IMAGE_NAME: $CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME # dotnet 特定变量 DOTNET_NOLOGO: 1 DOTNET_CLI_TELEMETRY_OPTOUT: 1 build-dotnet8: stage: build image: registry.example.com/dotnet8-builder:1.0 tags: [dotnet8, linux] script: - dotnet restore - dotnet build -c Release artifacts: paths: - bin/Release/net8.0/publish/ expire_in: 1 week test-unit: stage: test image: registry.example.com/dotnet8-builder:1.0 tags: [dotnet8, linux] script: - dotnet test --no-build --logger trx;LogFileNametest-results.trx coverage: /^Total.*[0-9]{1,3}%$/ artifacts: paths: - test-results.trx expire_in: 1 week build-docker-image: stage: package image: docker:24.0.5 tags: [docker, linux] services: - docker:24.0.5-dind before_script: - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $DOCKER_REGISTRY script: - docker build -t $DOCKER_REGISTRY/$IMAGE_NAME:$CI_COMMIT_TAG . - docker push $DOCKER_REGISTRY/$IMAGE_NAME:$CI_COMMIT_TAG only: - tags scan-container: stage: package image: aquasec/trivy:0.45.0 tags: [docker, linux] script: - trivy image --format table --severity CRITICAL,HIGH $DOCKER_REGISTRY/$IMAGE_NAME:$CI_COMMIT_TAG allow_failure: true only: - tags deploy-to-k8s: stage: deploy image: bitnami/kubectl:1.28.2 tags: [k8s, linux] before_script: - kubectl config set-cluster gitlab --server$K8S_API_SERVER --insecure-skip-tls-verifytrue - kubectl config set-credentials gitlab --token$K8S_TOKEN - kubectl config set-context gitlab --clustergitlab --usergitlab - kubectl config use-context gitlab script: - kubectl set image deployment/payment-gateway payment-gateway$DOCKER_REGISTRY/$IMAGE_NAME:$CI_COMMIT_TAG only: - tags这个 pipeline 的设计哲学是每个 stage 专注一件事且可独立重试。例如scan-container允许失败allow_failure: true因为安全扫描不应阻断发布但 critical 漏洞会触发告警。4.2 docker-in-dockerdind的替代方案为什么我们弃用 dindservices: - docker:dind是经典写法但它有三个硬伤性能损耗dind 容器内再启动 docker daemon形成双层虚拟化构建镜像耗时增加 30%安全风险dind 容器必须以privileged: true运行这等于授予 job 容器 root 权限网络复杂dind 的 bridge 网络与宿主机网络隔离job 容器无法直接访问宿主机服务如数据库。我们的替代方案是docker socket 直连build-docker-image: stage: package image: docker:24.0.5 tags: [docker, linux] # 移除 services改为挂载宿主机 socket variables: DOCKER_HOST: tcp://localhost:2375 before_script: - apk add --no-cache curl - curl -sSL https://get.docker.com/ | sh - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $DOCKER_REGISTRY script: - docker build -t $DOCKER_REGISTRY/$IMAGE_NAME:$CI_COMMIT_TAG . - docker push $DOCKER_REGISTRY/$IMAGE_NAME:$CI_COMMIT_TAG关键点在于runner 的config.toml已将/var/run/docker.sock挂载到 job 容器因此 job 内无需启动 dind直接调用宿主机 docker daemon 即可。这使镜像构建时间从 4.2 分钟降至 2.8 分钟且无需privileged权限。4.3 ISP pipeline 的超时问题一个被忽视的 DNS 配置某客户报告pipeline 在docker build步骤随机超时错误信息为Step 1/10 : FROM mcr.microsoft.com/dotnet/sdk:8.0-jammy-amd64卡住。日志显示Failed to connect to mcr.microsoft.com port 443: Connection timed out。表面看是网络问题但ping mcr.microsoft.com通curl -v https://mcr.microsoft.com也通。深入排查发现ISP 提供的 DNS 服务器如 114.114.114.114对微软 CDN 域名解析不稳定TTL 过短导致频繁重新查询。解决方案不是换 DNS而是在 docker build 中指定 DNSscript: - docker build --dns 8.8.8.8 --dns 1.1.1.1 -t $DOCKER_REGISTRY/$IMAGE_NAME:$CI_COMMIT_TAG .更彻底的方案是在 runner 的config.toml中为 docker executor 全局设置[runners.docker] dns [8.8.8.8, 1.1.1.1]这样所有 job 容器都继承该 DNS 配置无需在每个docker build命令中重复指定。5. 故障排查那些让运维半夜爬起来的日志线索5.1 “job is stuck” 的五层排查法当 pipeline 显示 “This job is stuck because you don’t have any active runners that can execute it”不要立刻重启 runner。按以下顺序逐层检查层级检查点命令/方法典型现象L1Runner 进程状态runner 是否在运行sudo systemctl status gitlab-runnerActive: inactive (dead)L2Runner 注册状态runner 是否被 GitLab 认可sudo gitlab-runner verifyRuntime platform显示ERROR: Verifying runner... failedL3Tag 匹配job 的 tags 是否与 runner 的 tags 完全一致sudo gitlab-runner list 对比.gitlab-ci.ymlrunner tags 为dotnet8,linuxjob tags 为dotnet8, linux注意空格L4网络连通性runner 能否访问 GitLab 实例sudo gitlab-runner --debug run临时启动 debug 模式日志出现Failed to ping coordinatorL5Token 有效性runner token 是否过期或被 revokeGitLab UI Project Settings CI/CD Runners 点击 runner 查看状态状态显示paused或not connected我们曾遇到 L4 失败runner 日志显示Failed to ping coordinator: Get http://10.10.20.5:8080/api/v4/runners/status: dial tcp 10.10.20.5:8080: connect: no route to host。但ping 10.10.20.5成功。最终发现是防火墙规则阻止了 8080 端口的TCP 连接而 ICMP ping 仍允许。解决方案sudo ufw allow 8080/tcp。5.2 docker executor 的容器启动失败从日志定位根因当 job 显示Preparing environment后卡住或直接报ERROR: Job failed: failed to start process需检查查看 runner 日志sudo journalctl -u gitlab-runner -f关键线索Failed to create container: Error response from daemon: ...后跟具体错误。常见错误与解法Error response from daemon: error creating overlay mount: device or resource busyoverlayfs 驱动冲突重启 docker daemonError response from daemon: unable to find user gitlab-runner-prodjob 容器试图以gitlab-runner-prod用户运行但基础镜像中不存在该用户。解决方案在config.toml中添加user root或在 Dockerfile 中USER rootError response from daemon: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?确认volumes挂载正确且宿主机 docker daemon 正在运行。终极调试法手动启动一个测试容器模拟 runner 行为# 使用 runner 的相同参数 docker run -it --rm \ -v /var/run/docker.sock:/var/run/docker.sock:ro \ -v /var/lib/gitlab-runner-prod/cache:/cache \ mcr.microsoft.com/dotnet/sdk:8.0-jammy-amd64 \ sh -c dotnet --version如果此命令失败则问题在 runner 环境如果成功则问题在.gitlab-ci.yml的 script 逻辑。5.3 dotnet8 构建失败PATH 与 SDK 版本的隐秘战争dotnet restore报错MSBUILD : error MSB1025: An internal failure occurred while running MSBuild.看似是 MSBuild 错误实则是 dotnet CLI 版本混乱。排查步骤在 job 中添加诊断脚本script: - echo PATH: $PATH - which dotnet - dotnet --list-sdks - dotnet --list-runtimes - dotnet restore典型问题which dotnet返回/usr/bin/dotnet但dotnet --list-sdks为空说明系统 PATH 中的 dotnet 与 SDK 安装路径不匹配dotnet --list-sdks显示6.0.400 [/usr/share/dotnet/sdk]而你需要 8.0基础镜像未正确安装 dotnet8。解决方案在自定义镜像的 Dockerfile 中明确设置 PATHENV DOTNET_ROOT/usr/share/dotnet ENV PATH${PATH}:/usr/share/dotnet RUN dotnet --version # 验证安装5.4 常见问题速查表问题现象根本原因解决方案验证方法job pending 状态runner 状态为 onlinerunner 的 tags 与 job 的 tags 字符串不完全匹配如空格、大小写在 GitLab UI 的 runner 列表页点击 runner 查看其 exact tags与.gitlab-ci.yml中 tags 字段逐字符比对修改 job tags 后触发新 pipelinedocker: command not foundin jobjob 容器内未安装 docker CLI但 runner 配置了volumes [/var/run/docker.sock:...]在 job 的image中预装 docker CLI或在before_script中apk add dockerAlpine/apt-get install docker.ioDebiandocker --version在 job script 中执行fatal: unable to access https://...: Could not resolve hostjob 容器 DNS 配置错误无法解析 GitLab 域名在config.toml的[runners.docker]section 中设置dns [8.8.8.8]在 job script 中nslookup gitlab.example.comERROR: Job failed: execution took longer than 3600 secondsjob 执行超时但实际任务未完成在config.toml中增大timeout值或在.gitlab-ci.yml中为该 job 设置timeout: 7200观察 job 日志最后一条输出时间WARNING: Pulling docker image ...后长时间无响应runner 从 registry 拉取基础镜像慢因 registry 网络延迟在 runner 宿主机配置 registry mirror如{registry-mirrors: [https://mirror.gcr.io]}sudo systemctl restart docker后测试docker pull hello-world实操心得我养成了一个习惯——每次部署新 runner 后立即创建一个名为debug-runner的测试项目里面只放一个最简.gitlab-ci.ymltest: script: - echo Runner OK - uname -a - df -h它不执行任何业务逻辑只验证 runner 的基础连通性和环境健康度。这个 10 行 yaml每年帮我避免至少三次线上事故。6. 运维视角如何让 gitlab-runner 三年不宕机6.1 自动化健康检查用 cron 做 runner 的家庭医生每天凌晨 3 点执行一次全面体检#!/bin/bash # /opt/scripts/check-runner.sh RUNNER_STATUS$(sudo gitlab-runner status 21) if [[ $RUNNER_STATUS ! *gitlab-runner: running* ]]; then echo $(date): runner down, restarting... /var/log/gitlab-runner/health.log sudo systemctl restart gitlab-runner # 发送企业微信告警 curl -X POST https://qyapi.weixin.qq.com/cgi-bin/webhook/send?keyxxx \ -H Content-Type: application/json \ -d {msgtype: text, text: {content: gitlab-runner 进程异常退出请检查}} fi # 检查 runner 是否能连接 GitLab if ! sudo gitlab-runner verify --delete-all-runners 2/dev/null | grep -q Verifying runner; then echo $(date): runner verification failed /var/log/gitlab-runner/health.log sudo systemctl restart gitlab-runner fi添加到 crontab# 每天 3:00 执行 0 3 * * * /opt/scripts/check-runner.sh6.2 日志轮转防止 /var/log 填满磁盘默认 runner 日志不轮转一年后可能占满 20GB。配置 logrotate# /etc/logrotate.d/gitlab-runner /var/log/gitlab-runner/*.log { daily missingok rotate 30 compress delaycompress notifempty create 0644 gitlab-runner-prod gitlab-runner-prod sharedscripts postrotate systemctl reload gitlab-runner /dev/null 21 || true endscript }6.3 版本升级零停机平滑迁移升级 runner 不能简单sudo apt upgrade gitlab-runner因为新版本可能不兼容旧配置。我们的流程下载新版本二进制到/tmp/gitlab-runner-new停止旧 runnersudo systemctl stop gitlab-runner备份旧二进制sudo mv /usr/local/bin/gitlab-runner /usr/local/bin/gitlab-runner-old复制新二进制sudo cp /tmp/gitlab-runner-new /usr/local/bin/gitlab-runner验证配置sudo
返回列表