极狐GitLab

生产环境谁都能点发布?用受保护环境把审批卡在前面

极狐GitLab
2026年10月15日
22481
分享:

生产环境谁都能点发布?用受保护环境把审批卡在前面

定义框:受保护环境(Protected environment)是极狐GitLab CI/CD 中的一类环境级访问控制对象。它在环境之上叠加两层约束——「允许部署」名单限定谁有资格把代码送到这个环境,「审批人 + 审批规则」限定这次部署需要几个人点头才能真正执行。环境本身在基础版即可使用,受保护环境与部署审批属于专业版与旗舰版能力。

为什么「谁能点发布」这件事必须先解决

多数团队对生产环境的管控,最初是靠约定:只有运维组的几个人知道发布脚本怎么跑。这套做法在十几个人的时候有效,一过三十人就崩了——分支保护规则在仓库里,发布密钥在 CI 变量里,审批在群聊里,三者互相对不上。

典型的失控场景是这样的:某位开发者有目标分支的合并权限,他合并了一个合并请求,流水线自动跑到 production 作业,生产环境就被更新了。全程没有任何人"批准"过这次发布,只是因为流水线的默认行为就是一路往下跑。

更麻烦的是变量。默认情况下所有 CI/CD 变量对流水线中所有作业可见,环境范围是 * 通配符。这意味着一个跑在 review/* 评审环境里的测试作业,理论上也能读到本该只给生产部署用的密钥。文档里对这条风险说得很直接:如果作业中的某个测试工具被攻破,它会尝试获取该作业可用的全部变量。

受保护环境解决的正是这两件事——把"谁能部署"和"这次部署谁批准了"从口头约定变成平台上的强制校验。

怎么配:四步把审批卡到发布之前

第一步:在流水线里定义环境

环境的名字与 URL 写在作业的 environment 关键字里。name 决定这个作业部署到哪个环境,url 决定 UI 里点进去跳哪儿。

stages:
  - test
  - deploy

deploy_staging:
  stage: deploy
  script:
    - echo "Deploy to staging server"
  environment:
    name: staging
    url: https://staging.example.com

deploy_prod:
  stage: deploy
  when: manual
  script:
    - echo "Deploying to ${CI_ENVIRONMENT_NAME}"
  environment:
    name: production
    url: https://www.example.com

第二步:给环境加保护

进入 设置 > CI/CD,展开 受保护的环境,选择 保护环境。这里要填两组名单:

  • 允许部署:谁能触发部署。可选维护者、开发者角色,或已邀请到项目里的群组和特定用户。

  • 审批人:谁有资格批准。规则同上,但群组必须是已邀请到项目里的。

还要设置审批规则的数量——需要几个人批准。文档里有一句容易踩的约束:这个数字必须小于或等于规则中的成员数,否则永远凑不齐。

也可以用 API 批量处理,适合几十个项目统一纳管:

curl --header 'Content-Type: application/json' --request POST \
  --data '{"name": "production", "deploy_access_levels": [{"group_id": 9899826}]}' \
  --header "PRIVATE-TOKEN: <your_access_token>" \
  "https://gitlab.cn/api/v4/projects/22034114/protected_environments"

第三步:确认部署层级

极狐GitLab 会按环境名推测部署层级,规则是这几个正则:

环境名匹配

推测层级

`/(dev\

review\

trunk)/i`

development

`/(test\

tst\

int\

ac(ce\

)pt\

qa\

qc\

control\

quality)/i`

testing

`/(st(a\

)g\

mod(e\

)l\

pre\

demo\

non)/i`

staging

`/(pr(o\

)d\

live)/i`

production

不匹配任何一个的名字会落到 other。想绕开这套推测,在作业里显式写 deployment_tier:

deploy_prod:
  stage: deploy
  script:
    - ./deploy.sh
  environment:
    name: custom-portal
    deployment_tier: production

层级不是显示用的标签。群组级受保护环境就是用部署层级当名称的——因为同一个群组下,A 项目叫 production,B 项目叫 gprd,按名字保护根本覆盖不全,按层级保护才能一次生效。

第四步:收紧变量的环境范围

把生产密钥的变量作用域从 * 改成 production,评审环境用 review/* 单独一套。这样即使测试作业被执行了恶意代码,也拿不到生产凭证。

四条实践中会撞上的边界

审批通过不等于部署发生。 文档明确写了:部署作业获得批准后,你必须手动运行该作业。这不是缺陷,是设计——审批和运行被拆成两个动作,避免"批准即放行"带来的误触。如果你的作业是 when: manual,这一步尤其容易被误认为卡死。

默认不允许自审批。 触发流水线的用户不能同时批准这次部署。要放开,去 设置 > CI/CD > 受保护的环境 > 审批选项,勾选 允许流水线触发者批准部署。放开之前想清楚:单人深夜热修的场景确实需要它,但白天正常发布放开它,审批就退化成了走过场。

一个人对一次部署只能给一次审批。 即使这个人同时属于多个审批人组,也只算一票。所以"加三个组凑三票"的如意算盘打不响,凑不够人数部署会一直挂着。

审批人组必须是直接成员。 把群组加进审批人列表时,配置者本人得是该组的直接成员,否则下拉列表里根本看不到这个组。想让继承成员也拿到权限,要么勾选 启用群组继承,要么走 API。

还有一个隐藏项:删除审批规则之后,先前已批准的部署不会再显示是谁批准的。审计信息仍然保留在项目审计事件里,但 UI 上看不到。合规审计依赖这条记录的团队,别随手删规则。

常见问题

问:受保护环境是免费能力吗?

环境本身在基础版可用,但受保护环境与部署审批属于专业版和旗舰版。私有化部署与 JihuLab.com 都支持。

问:为什么 API 调用全部返回 403?

先检查项目的 CI/CD 是否被关闭。项目级 CI/CD 关闭时,受保护环境在 UI 和 API 中都不可用,API 对所有请求(包括列表查询)一律返回 403 Forbidden。

问:能只给人部署权限、不给代码权限吗?

可以,这是"仅部署访问"模式。做法是建一个组,把成员放进去,以报告者角色邀请这个组加入项目,再在受保护环境里授权。这类用户对部署分支没有推送和合并权限,所以只能部署,改不了代码。

什么样的团队不适合立刻上

审批是有成本的。一个五人小组、一天发布十几次的团队上三道审批,只会让所有人学会"先批准再说",最终审批变成橡皮图章,还额外拖慢交付。

受保护环境真正起作用的场景是:组织里已经出现了明确的角色边界,开发者负责构建与测试,运维或 SRE 负责部署与值守;或者有外部合规要求,必须留下"谁批准了这次上线"的可查记录。如果你的团队还处在"谁都能改、谁都能发"的阶段,先解决的应该是分支保护和变量作用域,不是审批。


延伸阅读:部署审批的完整配置项见部署审批文档,环境关键字与环境作用域见环境文档。

想把你现有的发布流程搬到极狐GitLab 上跑一遍? 可以预约一次针对性的环境迁移评估,我们会按你的组织规模给出受保护环境与审批规则的落地方案。欢迎留言说明你当前的发布卡点,一起拆解。