2. GitLab CI/CD 与 Review Apps 集成架构
Review Apps 的核心并不在于“多部署一套环境”,而在于把 GitLab CI/CD 的流水线、GitLab 的环境模型和动态环境生命周期三者绑定在一起。理解这一集成架构,关键要抓住三个对象:environment 关键字负责把一次 Job 的产物登记为某个环境;动态环境命名负责让每个分支或合并请求拥有独立环境;on_stop 与 auto_stop负责在分支合并、MR 关闭或超时后回收环境。三者缺一,Review Apps 就会退化成“手工部署一堆临时环境”。
一、environment 关键字:把 Job 变成可追踪的环境
在 .gitlab-ci.yml 中,environment 是连接流水线与 GitLab 环境页面的桥梁。它至少包含 name,可选 url、on_stop、auto_stop_in、action 等字段。一个典型的部署 Job 如下:
deploy_review:
stage: deploy
script:
- ./deploy.sh --env "$CI_ENVIRONMENT_SLUG" --ref "$CI_COMMIT_REF_SLUG"
environment:
name: review/$CI_COMMIT_REF_SLUG
url: https://$CI_ENVIRONMENT_SLUG.review.example.com
on_stop: stop_review
auto_stop_in: 3 days
rules:
- if: $CI_MERGE_REQUEST_ID
这里 name 决定环境在 GitLab 中的标识,url 决定环境页面上的“打开”按钮指向哪里,on_stop 指向负责销毁环境的 Job,auto_stop_in 则给出自动回收的宽限期。需要特别注意:environment 只是声明,真正的创建、更新、停止动作仍由 script 中的命令完成。GitLab 负责记录状态和触发停止 Job,不负责替你执行部署逻辑。
二、动态环境命名:让每个分支/MR 拥有独立环境
动态命名的本质是用 CI/CD 预定义变量拼接环境名。常用变量包括 CI_COMMIT_REF_SLUG(分支名转小写、非字母数字替换为连字符)、CI_ENVIRONMENT_SLUG(由 environment name 生成的合法 slug)、CI_MERGE_REQUEST_IID(MR 内部编号)。命名策略通常有三种:
- 按分支名:
review/$CI_COMMIT_REF_SLUG,适合长期分支和功能分支,可读性好,但分支名过长时 URL 会很长。 - 按 MR 编号:
review/mr-$CI_MERGE_REQUEST_IID,短且稳定,适合以 MR 为中心的团队,但同一分支多次开 MR 会产生多个环境。 - 混合式:
review/$CI_COMMIT_REF_SLUG-$CI_MERGE_REQUEST_IID,兼顾可读性与唯一性,代价是名称较长。
命名一旦确定,就要保证 name、url 和部署脚本中的环境标识三者一致。例如 url: https://$CI_ENVIRONMENT_SLUG.review.example.com 依赖 GitLab 自动生成的 slug,而部署脚本若使用 $CI_COMMIT_REF_SLUG 作为命名空间,两者必须能对应,否则环境页面上的链接会指向错误地址。实践中建议在 Job 内先 echo 出这两个变量,确认映射关系后再执行部署。
三、on_stop 与 auto_stop:环境生命周期的收口
Review Apps 最大的运维风险是环境泄漏——分支已合并,环境仍在运行,持续消耗集群资源。GitLab 提供两条回收路径:
- on_stop:当环境被停止时(手动点击停止、分支删除、MR 关闭等触发),GitLab 会运行
on_stop指定的 Job。该 Job 必须声明environment: action: stop,否则 GitLab 不会把它识别为停止动作。 - auto_stop_in:为环境设置空闲超时,例如
3 days、1 week。超时后 GitLab 自动触发停止流程,同样会调用on_stopJob。
stop_review:
stage: cleanup
script:
- ./destroy.sh --env "$CI_ENVIRONMENT_SLUG"
environment:
name: review/$CI_COMMIT_REF_SLUG
action: stop
rules:
- if: $CI_MERGE_REQUEST_ID
when: manual
注意 stop_review 的 environment.name 必须与部署 Job 完全一致,否则 GitLab 无法把停止动作关联到同一个环境。此外,action: stop 的 Job 通常设为 when: manual,既允许人工提前回收,也允许 GitLab 在 MR 关闭或超时时自动调用。若希望 MR 关闭即自动销毁,可结合 rules 与 when: on_success,但需评估销毁失败时的重试与告警策略。
四、集成架构中的关键约束与排障要点
把上述三部分串起来后,实际落地时最容易踩的坑集中在四处。第一,environment.name 与 on_stop Job 的 environment.name 不一致,导致停止动作找不到目标环境,环境页面一直显示“可用”。第二,url 使用了未定义的变量或与部署脚本的域名规则不一致,环境链接 404。第三,auto_stop_in 只写在部署 Job 上,但停止 Job 未声明 action: stop,超时后 GitLab 无法执行销毁。第四,动态命名中使用了 CI_COMMIT_REF_NAME 而非 CI_COMMIT_REF_SLUG,分支名含大写或斜杠时环境名非法,GitLab 会拒绝创建环境。
CI_ENVIRONMENT_SLUG 与 CI_COMMIT_REF_SLUG 的实际取值;再检查 GitLab 项目 Operate → Environments 中环境是否出现、状态是否为 available;最后在 MR 关闭或手动停止后观察 stop_review Job 是否被触发、日志中销毁命令是否成功返回。
五、一个可复用的最小集成骨架
下面给出一个可直接改造的最小骨架,覆盖部署、停止、动态命名和自动回收四个要素。示例中的域名、超时时间和脚本路径均为教学假设,实际使用时替换为团队真实值。
stages:
- build
- test
- deploy
- cleanup
deploy_review:
stage: deploy
script:
- echo "env=$CI_ENVIRONMENT_SLUG ref=$CI_COMMIT_REF_SLUG"
- ./deploy.sh --env "$CI_ENVIRONMENT_SLUG"
environment:
name: review/$CI_COMMIT_REF_SLUG
url: https://$CI_ENVIRONMENT_SLUG.review.example.com
on_stop: stop_review
auto_stop_in: 3 days
rules:
- if: $CI_MERGE_REQUEST_ID
stop_review:
stage: cleanup
script:
- ./destroy.sh --env "$CI_ENVIRONMENT_SLUG"
environment:
name: review/$CI_COMMIT_REF_SLUG
action: stop
rules:
- if: $CI_MERGE_REQUEST_ID
when: manual
这份骨架的价值在于:deploy_review 与 stop_review 共享同一个 environment.name 表达式,保证环境身份一致;on_stop 把两者显式关联;auto_stop_in 提供兜底回收;rules 限定只在 MR 场景运行,避免主干分支误建 Review 环境。掌握这四点,就掌握了 GitLab CI/CD 与 Review Apps 集成架构的主干。