如何阻止单个GitLab项目的CI流水线并发执行?
解决GitLab单项目流水线并发冲突的方案
刚好碰到过类似的场景,针对你说的这个项目CI不能容忍流水线并发(存在Kubernetes外部副作用),但全局设置Runner的concurrent=1会影响其他项目的问题,这里有几个实用的解决方案,完全不影响其他项目的正常运行:
1. 项目级流水线并发限制(最省心的官方方案)
GitLab本身就支持在单个项目层面限制同时运行的流水线数量,步骤很简单:
- 进入项目的 Settings > CI/CD > General pipelines 页面
- 找到「Maximum concurrent pipelines」选项,把数值设为
1 - 保存之后,这个项目同一时间只会有一条流水线在执行,新推送触发的流水线会自动排队,等当前的跑完再启动
这个方法是官方推荐的,零脚本改动,对其他项目完全无干扰,优先推荐用这个。
2. 用resource_group控制特定Job的并发(更精细的控制)
如果不需要限制整个流水线,只是特定的阶段(比如部署Job)不能并发,可以用GitLab的resource_group功能,在.gitlab-ci.yml里给需要锁的Job加上这个配置:
deploy-to-k8s: stage: deploy script: - # 你的K8s部署脚本 resource_group: project-deployment-lock
这样所有标记了resource_group: project-deployment-lock的Job,同一时间只会有一个在跑,其他同组的Job会进入等待队列,其他不涉及这个资源组的Job不受影响。
3. 自定义脚本实现排队逻辑(适配旧版本GitLab)
如果你的GitLab版本比较老,不支持上面两个功能,可以用自定义脚本结合CI变量来实现简单的排队机制:
- 先在项目的CI/CD变量里创建一个
PIPELINE_RUNNING变量,初始值设为false - 在流水线的第一个Job里加检查逻辑:
# 循环等待,直到没有正在运行的流水线 while [[ "$PIPELINE_RUNNING" == "true" ]]; do echo "当前有流水线在运行,等待30秒后重试..." sleep 30 # 调用GitLab API拉取最新的变量值(需要CI_JOB_TOKEN有API权限) PIPELINE_RUNNING=$(curl --header "PRIVATE-TOKEN: $CI_JOB_TOKEN" "$CI_API_V4_URL/projects/$CI_PROJECT_ID/variables/PIPELINE_RUNNING" | jq -r '.value') done # 标记当前流水线为运行中 curl --request PUT \ --header "PRIVATE-TOKEN: $CI_JOB_TOKEN" \ --header "Content-Type: application/json" \ --data '{"value": "true"}' \ "$CI_API_V4_URL/projects/$CI_PROJECT_ID/variables/PIPELINE_RUNNING"
- 然后在流水线的最后一个Job(不管成功还是失败)里,把
PIPELINE_RUNNING重置回false:
curl --request PUT \ --header "PRIVATE-TOKEN: $CI_JOB_TOKEN" \ --header "Content-Type: application/json" \ --data '{"value": "false"}' \ "$CI_API_V4_URL/projects/$CI_PROJECT_ID/variables/PIPELINE_RUNNING"
注意:这个方法要确保CI Job有访问GitLab API的权限,还要处理好异常情况(比如流水线意外中断时,手动重置变量)。
内容的提问来源于stack exchange,提问作者Tobias Hermann
相关产品推荐
相关产品推荐

