如何将GitLab Runner关联绑定到指定物理服务器与对应部署环境
独立物理服务器环境下的GitLab Pipeline路由实现方案
核心基础原理
GitLab根本没在Environments页面放Runner绑定的配置入口,因为Runner的任务调度完全靠标签匹配规则,Environments功能本身和任务路由是完全解耦的。Environments只用来记录部署历史、提供回滚入口、展示各环境的当前版本状态,根本不负责调度任务。
之前觉得“打标签会在dev服务器重跑全Pipeline”的顾虑,本质是之前所有Runner共用了通用标签、没做调度权限隔离导致的,不是打标签这个机制本身的问题。
第一步:完成各服务器的Runner基础配置
从调度源头做隔离,从根本上避免任务被错误的Runner接走:
- 在每台物理服务器上独立安装对应版本的GitLab Runner,注册到同一个GitLab实例
- 给每台Runner配置唯一、不重叠的专属标签,绝对不要加
shell、linux这种通用标签:- dev服务器上的Runner:仅绑定
dev-shell标签 - staging服务器上的Runner:仅绑定
staging-shell标签 - 后续prod服务器的Runner:仅绑定
prod-shell标签
- dev服务器上的Runner:仅绑定
- 每台Runner注册完成后,在GitLab的Runner编辑页面,关闭「运行未打标签作业」的开关,杜绝兜底调度的权限漏配。
第二步:调整.gitlab-ci.yml的作业逻辑
实现“合并main自动跑dev部署、手动触发跑staging部署”的流程,且完全不会跨服务器执行任务:
按下面的逻辑拆分作业,每个作业只匹配对应服务器Runner的专属标签:
- dev环境自动部署作业
- 标签配置:
tags: [dev-shell],这个标签只有dev服务器的Runner持有,从调度层面保证只有dev服务器能接这个任务 - 触发规则:设置为
only: [main],只要有提交合并到main分支就自动运行 - 作业内容:原有的dev环境更新、基础测试执行的shell脚本
- 标签配置:
- staging环境手动部署作业
- 标签配置:
tags: [staging-shell],这个标签只有staging服务器的Runner持有,dev服务器的Runner因为没有这个标签,根本不会匹配到这个作业 - 触发规则:设置为
when: manual,流水线启动后这个作业默认处于待点击状态,需要开发者在GitLab Pipelines界面手动确认运行 - 作业依赖:可以配置
needs: [deploy_dev],只有当dev环境的部署和基础测试全部通过后,手动触发按钮才会被点亮,避免没通过测试的提交被直接部署到staging - 环境关联:加上
environment: name: staging配置,让GitLab自动把这个作业的部署记录关联到staging环境,在环境页面能看到版本历史
- 标签配置:
- 核心配置结构参考(仅展示逻辑片段):
# 自动部署到dev的作业 deploy_dev: stage: deploy tags: [dev-shell] only: [main] script: - ./scripts/update_dev_env.sh environment: name: development # 手动部署到staging的作业 deploy_staging: stage: deploy tags: [staging-shell] only: [main] when: manual needs: [deploy_dev] allow_failure: false script: - ./scripts/update_staging_env.sh environment: name: staging
常见避坑提醒
- 绝对不要给Runner加跨环境通用的标签,否则会出现任何带通用标签的作业被所有带这个标签的Runner随机调度的问题
- 不要通过给commit打版本标签的方式触发staging部署,这种方式会重新生成一条独立的流水线,必然会触发dev服务器的Runner重新跑全流程测试,和当前需求不符
- 不需要在Environments页面做任何Runner绑定操作,所有调度逻辑靠专属标签和Runner权限就能完全实现
- 所有作业的标签一定要和对应Runner的标签严格一一匹配,避免漏配导致的调度失败
整个流程跑通后,执行链路是:提交合并到main -> GitLab把dev部署作业调度到dev服务器的Runner,自动完成dev环境更新和基础测试 -> 测试通过后,界面出现staging部署的手动按钮 -> 开发者点击按钮后,GitLab把staging部署作业调度到staging服务器的Runner,全程没有跨服务器的任务执行,也不会在dev服务器上重复跑staging相关的流程。
内容的提问来源于stack exchange,提问作者displayNameGoesHere
相关产品推荐
相关产品推荐

