Gitlab CICD流水线设计

带人工确认的生产部署流水线

.gitlab-ci.yml

============================================

1. 定义流水线阶段,按顺序执行

============================================

stages:

  • build # 第1阶段:编译 + 打包(install 会下载依赖并打包成 jar/war)

  • test # 第2阶段:单元测试 + 集成测试(并行执行)

  • deploy # 第3阶段:部署到各环境

============================================

2. 全局变量,所有 job 都可以引用

============================================

variables:

APP_NAME: "my-app" # 应用名称

DOCKER_IMAGE: "registry.example.com/{APP_NAME}:{CI_COMMIT_SHA}" # Docker 镜像地址(带提交SHA唯一标识)

MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository" # Maven 本地仓库路径(利用 CI cache 加速)

DOCKER_DRIVER: overlay2 # Docker 存储驱动(Runner 机器配置)

============================================

3. Build 阶段 - 编译 + 打包 + 构建 Docker 镜像

============================================

build:

stage: build # 属于 build 阶段

image: maven:3.9-openjdk-17 # Maven + JDK 17 运行环境

services: # 关联 Docker 服务(让 Maven 能够运行 Docker 命令)

  • docker:24-dind # Docker-in-Docker,Runner 内运行 Docker

script: # 核心执行命令

---------- 编译打包 ----------

  • mvn clean package -DskipTests # 编译代码 + 跳过测试打包 jar(Dockerfile 需要)

  • ls -la target/*.jar # 确认 jar 包生成成功(调试用)

---------- Docker 登录 ----------

  • echo "CI_REGISTRY_PASSWORD" \| docker login -u "CI_REGISTRY_USER" --password-stdin $CI_REGISTRY # 登录镜像仓库

---------- 构建镜像 ----------

  • docker build -t ${DOCKER_IMAGE} . # 根据 Dockerfile 构建镜像,标签为本次提交SHA # ---------- 推送镜像 ----------

  • docker push ${DOCKER_IMAGE} # 推送到镜像仓库,供 K8s 部署使用

artifacts: # 产物:下游 job 可以使用

paths:

  • target/*.jar # 打包产物(如果需要传递给其他 job)

expire_in: 1 hour # 产物过期时间

reports: # 可选:SonarQube 代码质量报告

junit: target/surefire-reports/*.xml

cache: # 缓存 Maven 依赖,加速下次构建

key: "${CI_COMMIT_REF_SLUG}" # 按分支缓存,避免分支间互相覆盖

paths:

  • .m2/repository # Maven 本地仓库(下载一次后复用)

only: # 触发条件

  • main # 仅 main 分支 push 时执行# ============================================

4. Test 阶段 - 单元测试

============================================

test_unit:

stage: test # 属于 test 阶段

image: maven:3.9-openjdk-17 # Maven + JDK 17 运行环境

script: # 执行命令

  • mvn test # 运行 src/test/java 下的单元测试

artifacts: # 产物:测试报告(GitLab UI 直接查看)

when: always # 即使失败也生成报告

paths:

  • target/surefire-reports/ # Maven Surefire 测试报告(XML 格式)

reports: # 解析为标准格式,供 GitLab 展示

junit: target/surefire-reports/TEST-*.xml # GitLab 自动解析,显示测试通过/失败数

coverage_report: # 可选:JaCoCo 覆盖率报告

coverage_format: cobertura

path: target/site/jacoco/jacoco.xml

coverage: '/Total.*?([0-9]{1,3})%/' # 从日志中提取覆盖率百分比

needs: [build] # 等待 build job 完成后才执行(从 build 的 artifacts 继承)

cache:

key: "${CI_COMMIT_REF_SLUG}"

paths:

  • .m2/repository

only:

  • main

============================================

5. Test 阶段 - 集成测试

============================================

test_integration:

stage: test # 属于 test 阶段(与 test_unit 并行)

image: maven:3.9-openjdk-17 # Maven + JDK 17 运行环境

services: # 集成测试需要依赖真实中间件

  • postgres:13 # PostgreSQL 数据库容器(测试时连接)

- redis:7 # Redis 缓存容器(如果项目用到)

variables: # Job 局部变量,覆盖全局变量

---------- Spring Boot 测试配置(通过系统属性注入) ----------

SPRING_DATASOURCE_URL: "jdbc:postgresql://postgres:5432/testdb" # 数据库连接地址(postgres 是 service 名称)

SPRING_DATASOURCE_USERNAME: "test" # 数据库用户名

SPRING_DATASOURCE_PASSWORD: "test" # 数据库密码

script:

---------- 集成测试(使用 Spring Boot Test) ----------

  • mvn verify -Dspring.profiles.active=ci # 运行集成测试(激活 ci 配置,排除本地文件依赖)

---------- 可选:运行指定集成测试类 ----------

- mvn test -Dtest=OrderServiceIntegrationTest

artifacts:

when: always

paths:

  • target/surefire-reports/ # Maven Surefire 报告

  • target/failsafe-reports/ # Maven Failsafe 集成测试报告(如果用 failsafe 插件)

reports:

junit: target/surefire-reports/TEST-*.xml # GitLab 解析测试结果

needs: [build] # 等待 build 完成

cache:

key: "${CI_COMMIT_REF_SLUG}"

paths:

  • .m2/repository

allow_failure: true # ⚠️ 允许失败,不阻塞后续流程(根据业务决定)

only:

  • main

============================================

6. Deploy 阶段 - 部署到测试环境(自动化,无需人工确认)

============================================

deploy_test:

stage: deploy # 属于 deploy 阶段

image: bitnami/kubectl:latest # kubectl 操作 K8s

before_script: # 执行 script 前的准备工作

  • kubectl config use-context test-cluster # 切换到测试集群上下文

script:

---------- 替换镜像版本 ----------

  • kubectl set image deployment/{APP_NAME} app={DOCKER_IMAGE} # 更新 K8s Deployment 的镜像版本

---------- 等待滚动更新 ----------

  • kubectl rollout status deployment/${APP_NAME} --timeout=300s # 等待滚动更新完成,超时5分钟

---------- 确认版本 ----------

  • kubectl rollout history deployment/${APP_NAME} # 查看滚动历史(调试用)

  • kubectl get pods -l app=${APP_NAME} # 查看 pod 状态(确认启动成功)

environment: # 声明环境,GitLab UI 追踪部署历史

name: test # 环境名称

url: https://test.example.com # 测试环境访问地址

needs: [test_unit, test_integration] # 等待两个测试 job 都完成

only:

  • main

============================================

7. Deploy 阶段 - 部署到预发布环境(自动化)

============================================

deploy_staging:

stage: deploy # 属于 deploy 阶段

image: bitnami/kubectl:latest # kubectl 操作 K8s

before_script:

  • kubectl config use-context staging-cluster # 切换到预发布集群

script:

  • kubectl set image deployment/{APP_NAME} app={DOCKER_IMAGE} # 更新镜像版本

  • kubectl rollout status deployment/${APP_NAME} --timeout=300s # 等待滚动更新完成

  • kubectl get pods -l app=${APP_NAME} # 确认 Pod 运行正常

environment:

name: staging # 环境名称

url: https://staging.example.com # 预发布环境地址

on_stop: rollback_staging # 🔑 环境停止时触发回滚 job

needs: [test_unit, test_integration] # 等待测试完成

only:

  • main

============================================

8. 预发布环境人工审批(关键卡点:确保验收通过后再上生产)

============================================

approve_staging: # job 名称(纯人工审批节点)

stage: deploy # 同一 deploy 阶段(不占 Runner 资源)

script:

---------- 无实际命令,GitLab UI 会显示 Play 按钮 ----------

  • echo "✅ 预发布环境验收通过,等待生产部署审批" # GitLab 日志中显示提示信息

environment:

name: staging # 关联到 staging 环境

action: prepare # 🔑 暂停预发布环境,等待后续操作

needs: [deploy_staging] # 必须等预发布部署完成

when: manual # 🔑 核心:人工手动点击才触发,不自动执行

allow_failure: false # 不允许失败

only:

  • main

============================================

9. 生产环境部署(最高风险:人工确认 + 前置审批通过)

============================================

deploy_production: # job 名称

stage: deploy # 属于 deploy 阶段

image: bitnami/kubectl:latest # kubectl 操作生产 K8s 集群

before_script:

  • kubectl config use-context prod-cluster # 切换到生产集群(⚠️ 操作需谨慎)

script:

---------- 正式部署 ----------

  • kubectl set image deployment/{APP_NAME} app={DOCKER_IMAGE} # 更新生产镜像版本

  • kubectl rollout status deployment/${APP_NAME} --timeout=600s # 等待滚动更新完成(生产超时可设更长)

---------- 健康检查确认 ----------

  • kubectl get pods -l app=${APP_NAME} # 确认所有 Pod 运行成功

  • kubectl describe deployment ${APP_NAME} | grep -A5 "RollingUpdateStrategy:" # 查看滚动策略

---------- 记录部署信息 ----------

  • echo "🚀 生产环境部署完成!镜像:{DOCKER_IMAGE},提交:{CI_COMMIT_SHA}"

environment:

name: production # 环境名称

url: https://www.example.com # 生产环境地址

on_stop: rollback_production # 🔑 环境停止时触发回滚 job

needs: [approve_staging] # 🔑 关键:必须等预发布审批通过

when: manual # 🔑 核心:必须人工点击,不自动执行

allow_failure: false # 不允许失败,失败则阻塞流水线

only:

  • main

resource_group: production # 🔑 可选:生产环境加锁,防止多人同时触发

============================================

10. 生产环境回滚(快速回退到上一稳定版本)

============================================

rollback_production: # job 名称

stage: deploy # 同一 deploy 阶段

image: bitnami/kubectl:latest # kubectl 操作 K8s

before_script:

  • kubectl config use-context prod-cluster # 切换到生产集群

script:

---------- 回滚到上一版本 ----------

  • kubectl rollout undo deployment/{APP_NAME} # 🔑 kubectl 内置回滚命令,秒级回退 - kubectl rollout status deployment/{APP_NAME} --timeout=300s # 等待回滚完成

---------- 确认回滚成功 ----------

  • kubectl rollout history deployment/${APP_NAME} # 查看当前版本历史

  • kubectl get pods -l app=${APP_NAME} # 确认 Pod 恢复

  • echo "⏪ 生产环境已回滚到上一版本"

environment:

name: production # 关联生产环境

action: stop # 🔑 标记环境为停止状态

when: manual # 🔑 手动触发,不自动执行

only:

  • main

============================================

11. 预发布环境回滚

============================================

rollback_staging: # job 名称

stage: deploy

image: bitnami/kubectl:latest

before_script:

  • kubectl config use-context staging-cluster # 切换到预发布集群

script:

  • kubectl rollout undo deployment/${APP_NAME} # 回滚到上一版本

  • kubectl rollout status deployment/${APP_NAME} --timeout=300s # 等待回滚完成

  • kubectl get pods -l app=${APP_NAME} # 确认 Pod 恢复

  • echo "⏪ 预发布环境已回滚"

environment:

name: staging action: stop # 停止预发布环境

when: manual # 手动触发

only:

  • main
相关推荐
MinterFusion2 天前
如果openKylin 2.0 SP2主机的IPv4地址改变,如何让GitLab正常运行
运维·gitlab·系统配置·系统维护·明德融创
Elivs.Xiang2 天前
ubuntu20中安装gitlab
linux·ubuntu·gitlab
csdn_aspnet2 天前
Gemini实战:用AI写CI/CD脚本,分享Gemini辅助编写GitLab CI、GitHub Actions等运维脚本的硬核技巧
人工智能·ci/cd·ai·gitlab·gemini·辅助编程
Cyber4K3 天前
【DevOps专项】GitLab 与 Jenkins 介绍及部署持续集成环境
运维·ci/cd·gitlab·jenkins·devops
IT布道3 天前
[GitLab] 项目源码迁移踩坑记
运维·gitlab
极小狐4 天前
PingCode × 极狐GitLab 用AI打通需求到交付全链路,研发管理与工程交付真正一体化
人工智能·gitlab·pingcode
qq_452396236 天前
【工程实战】第九篇:持续集成 —— Jenkins 与 GitLab CI:构建无人值守的自动化流水线
ci/cd·gitlab·jenkins
angushine8 天前
gitlab跨服务器备份
服务器·gitlab·github
蜡台9 天前
Git 常用配置:修改地址 ,提交模板配置
git·gitlab·template·git commit·gitbash