生产环境谁都能点发布?用受保护环境把审批卡在前面
生产环境谁都能点发布?用受保护环境把审批卡在前面
定义框:受保护环境(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 上跑一遍? 可以预约一次针对性的环境迁移评估,我们会按你的组织规模给出受保护环境与审批规则的落地方案。欢迎留言说明你当前的发布卡点,一起拆解。

