第六篇:《GitLab CI 进阶:多环境部署与环境变量管理》 📅 2026/7/15 12:23:48 在上一篇中我们学会了如何用 .gitlab-ci.yml 定义基础的 CI 流水线。但在实际项目中代码需要部署到开发dev、测试staging、生产prod等多个环境每个环境有不同的配置数据库地址、API 密钥、域名等。如果为每个环境维护一份独立的 .gitlab-ci.yml维护成本将不可接受。本文深入讲解 GitLab CI 的多环境部署策略如何通过分支策略实现环境隔离、如何使用 rules 精细控制 Job 触发条件、如何通过 CI/CD 变量管理不同环境的配置以及如何使用 environment 关键字记录部署历史和实现一键回滚。一、多环境部署的典型策略在 GitLab CI 中最常用的多环境部署策略是 “分支即环境”Branch as Environment 这种策略的核心思想是分支决定了代码的去向。推送到不同分支触发不同的部署行为。 替代方案如果不想用分支来区分环境也可以使用 环境变量驱动 的方式——通过同一个分支配合不同的变量值部署到不同环境。但分支策略更直观、更安全天然隔离是 GitLab 官方推荐的做法。二、使用 rules 控制 Job 触发条件在 GitLab CI 12.3 之后官方推荐使用 rules 替代已废弃的 only / except 语法。rules 更灵活、可读性更强支持条件组合和作业级控制。2.1 基础规则按分支匹配# 仅在 main 分支执行deploy-prod:stage:deployscript:-./deploy.sh prodrules:-if:$CI_COMMIT_BRANCH mainwhen:on_success-when:never# 其他分支不执行rules 数组从上到下依次匹配第一条匹配成功的规则生效。末尾的 when: never 确保未匹配的分支不会执行该 Job。2.2 多环境部署配置下面是一个完整的 .gitlab-ci.yml展示了如何通过 rules 实现分支驱动的多环境部署stages:-build-test-deploy-dev-deploy-staging-deploy-prod# 公共构建 Job所有分支都执行build:stage:buildscript:-mvn clean packageartifacts:paths:-target/*.jar# 单元测试所有分支都执行test:stage:testscript:-mvn test# 部署到开发环境develop 分支自动部署deploy-dev:stage:deploy-devscript:-echo 部署到开发环境...-./deploy.sh devenvironment:name:devurl:https://dev.myapp.example.comrules:-if:$CI_COMMIT_BRANCH develop$CI_PIPELINE_SOURCE pushwhen:on_success-when:never# 部署到预发布环境release/* 分支自动部署deploy-staging:stage:deploy-stagingscript:-echo 部署到预发布环境...-./deploy.sh stagingenvironment:name:stagingurl:https://staging.myapp.example.comrules:-if:$CI_COMMIT_BRANCH ~ /^release\/.*/$CI_PIPELINE_SOURCE pushwhen:on_success-when:never# 部署到生产环境main 分支手动触发deploy-prod:stage:deploy-prodscript:-echo 部署到生产环境...-./deploy.sh prodenvironment:name:productionurl:https://myapp.example.comrules:-if:$CI_COMMIT_BRANCH main$CI_PIPELINE_SOURCE pushwhen:manual# 需要人工确认allow_failure:false-when:never关键设计deploy-dev 和 deploy-staging 使用 when: on_success代码推送后自动部署deploy-prod 使用 when: manual需要人工点击按钮确认后才执行$CI_PIPELINE_SOURCE “push” 确保只有代码推送才触发排除合并请求MR等场景2.3 使用 changes 缩小触发范围如果只想在特定文件变更时才触发部署例如只有 src/ 目录变化才构建可以结合 changes 关键字deploy-prod:stage:deploy-prodscript:-./deploy.sh prodrules:-if:$CI_COMMIT_BRANCH mainchanges:-src/**/*-Dockerfilewhen:manual-when:never三、CI/CD 变量环境配置的核心不同环境的差异数据库地址、API 密钥、域名等应该通过 CI/CD 变量Variables 来管理而不是硬编码在 .gitlab-ci.yml 中。3.1 变量的层级与优先级GitLab CI 的变量分为多个层级优先级从高到低依次为手动触发变量通过 API 或 UI 手动触发时传入的变量优先级最高项目级变量在项目 Settings → CI/CD → Variables 中定义组级变量在组级别定义该组下所有项目共享实例级变量在整个 GitLab 实例级别定义流水线级变量在 .gitlab-ci.yml 中使用 variables 关键字定义内置预定义变量GitLab 自动提供的变量如 CI_COMMIT_SHA 实践建议通用配置如 Docker Registry 地址放在组级变量环境敏感信息如生产数据库密码放在项目级变量并开启保护硬编码的默认值放在 .gitlab-ci.yml 的 variables 中。3.2 定义变量在 UI 中添加变量进入项目 → Settings → CI/CD展开 Variables 部分点击 Add variable填写 Key 和 Value关键选项⚠️ 重要提醒Mask 只能隐藏长度 ≥ 8 个字符且不包含特殊字符的值。已在日志中打印过的值无法再设置为 Masked。3.3 在 .gitlab-ci.yml 中使用变量在脚本中通过 $变量名 引用变量deploy-prod:stage:deploy-prodscript:-echo 部署到 $CI_ENVIRONMENT_NAME 环境-curl -H Authorization:Bearer $DEPLOY_TOKEN https://api.example.com/deploy3.4 为不同环境配置不同变量在 GitLab UI 中可以为不同环境定义同名的变量通过 环境范围Environment Scope 区分在 Job 中通过 environment: name 匹配对应的变量值deploy-dev:environment:name:devscript:-echo 数据库地址:$DB_HOST# 自动使用 dev 的值3.5 使用文件类型变量存储证书GitLab CI 支持 文件类型变量File 适合存储证书、私钥等文件内容在 UI 中添加变量时将 Type 选择为 File将证书内容粘贴到 Value 中GitLab 会在 Runner 中自动生成一个临时文件路径通过变量名传递deploy:script:-cat $CERT_FILE# $CERT_FILE 是临时文件路径-curl--cacert $CERT_FILE https://secure-api.example.com3.6 在 Job 间传递动态变量before_script 中声明的变量在后续 Job 中无法直接访问。如果需要跨 Job 传递动态值如动态生成的版本号可以使用 dotenv 报告stages:-build-deploybuild:stage:buildscript:-echo VERSIONv1.0.0version.envartifacts:reports:dotenv:version.env# 将 version.env 中的变量暴露给后续 Jobdeploy:stage:deployscript:-echo 部署版本:$VERSION# 可以读取到 build Job 中设置的 VERSION四、使用 environment 记录部署历史environment 关键字不仅用于变量匹配还能在 GitLab UI 中记录每次部署的历史支持一键回滚。4.1 基本用法deploy-prod:stage:deploy-prodscript:-./deploy.shenvironment:name:productionurl:https://myapp.example.com在 GitLab 项目的 Operations → Environments 页面可以看到每个环境的部署历史时间、版本、提交信息当前部署的版本回滚按钮点击即可回滚到上一个版本4.2 动态环境名称对于动态生成的环境如每个 feature 分支独立部署可以使用预定义变量动态生成环境名deploy-feature:stage:deployscript:-./deploy.shenvironment:name:review/$CI_COMMIT_REF_SLUGurl:https://$CI_COMMIT_REF_SLUG.myapp.example.comrules:-if:$CI_COMMIT_BRANCH ~ /^feature\/.*/$CI_COMMIT_REF_SLUG 是 GitLab 预定义变量会将分支名转换为合法的 URL 友好字符串。五、完整的多环境部署示例下面是一个完整的 .gitlab-ci.yml集成了本文介绍的所有技术stages:-build-test-deploy-dev-deploy-staging-deploy-prodvariables:MAVEN_OPTS:-Dmaven.repo.local.m2/repositoryDOCKER_REGISTRY:registry.gitlab.comcache:paths:-.m2/repository/# 构建 build:stage:buildimage:maven:3.8.4-openjdk-17script:-mvn clean packageartifacts:paths:-target/*.jar# 测试 test:stage:testimage:maven:3.8.4-openjdk-17script:-mvn testartifacts:reports:junit:target/surefire-reports/*.xml# 部署到开发环境 deploy-dev:stage:deploy-devimage:docker:latestservices:-docker:dindscript:-docker build-t $DOCKER_REGISTRY/$CI_PROJECT_PATH:dev .-docker push $DOCKER_REGISTRY/$CI_PROJECT_PATH:dev-kubectl set image deployment/myapp myapp$DOCKER_REGISTRY/$CI_PROJECT_PATH:dev-n devenvironment:name:devurl:https://dev.myapp.example.comrules:-if:$CI_COMMIT_BRANCH develop$CI_PIPELINE_SOURCE pushwhen:on_success-when:never# 部署到预发布环境 deploy-staging:stage:deploy-stagingimage:docker:latestservices:-docker:dindscript:-docker build-t $DOCKER_REGISTRY/$CI_PROJECT_PATH:staging .-docker push $DOCKER_REGISTRY/$CI_PROJECT_PATH:staging-kubectl set image deployment/myapp myapp$DOCKER_REGISTRY/$CI_PROJECT_PATH:staging-n stagingenvironment:name:stagingurl:https://staging.myapp.example.comrules:-if:$CI_COMMIT_BRANCH release$CI_PIPELINE_SOURCE pushwhen:on_success-when:never# 部署到生产环境 deploy-prod:stage:deploy-prodimage:docker:latestservices:-docker:dindscript:-docker build-t $DOCKER_REGISTRY/$CI_PROJECT_PATH:prod .-docker push $DOCKER_REGISTRY/$CI_PROJECT_PATH:prod-kubectl set image deployment/myapp myapp$DOCKER_REGISTRY/$CI_PROJECT_PATH:prod-n productionenvironment:name:productionurl:https://myapp.example.comrules:-if:$CI_COMMIT_BRANCH main$CI_PIPELINE_SOURCE pushwhen:manualallow_failure:false-when:never六、小结多环境策略使用 “分支即环境” 策略develop → dev、release/* → staging、main → prod触发控制使用 rules 替代 only/except按分支、来源、文件变更精细控制 Job 触发变量管理通过 CI/CD 变量存储环境差异利用 Protect 和 Mask 保障安全部署记录使用 environment 关键字记录部署历史支持一键回滚