基于GitLab+Jenkins的持续集成实践指南

发布于:2025-04-06 ⋅ 阅读:(31) ⋅ 点赞:(0)

架构设计原则

分层自动化策略

  • 基础层: 代码提交触发自动构建(100%自动化)
  • 中间层: 制品生成与验证(自动化+人工审核)
  • 发布层: 环境部署(受控手动触发)

工具定位矩阵

工具 核心职责 关键优势
GitLab 源码管理+MR流程 精细的权限控制
Jenkins 流水线编排+任务调度 插件生态丰富
Nexus 制品生命周期管理 版本追踪能力强大
  • 核心动作:自动编译(构建)、生成制品(如JAR包、Docker镜像等)、推送到 Nexus(制品管理仓库)。
  • 符合 CI 的核心目标:
    • 快速验证代码:确保每次提交能成功构建,避免集成错误。
    • 生成可靠制品:将构建产物存储到 Nexus,为后续流程(如测试、部署)提供基础。

流程设计

持续集成CI

CI-3

其实一般不应该有snapshot-uat和snapshot-prod分支,根据大家开发环境修改吧。

持续发布CD

cd

概要说明

关于构建

  1. 自动持续集成流程
    代码提交至 GitLab 后,通过 WebHook 自动触发 Jenkins Pipeline,依次执行以下操作:拉取代码 → 编译打包 → 将构建产物推送至 Nexus 仓库,完成 自动化持续集成

  2. 镜像构建与项目发布流程
    镜像构建与部署操作 通过 Jenkins 手动触发,避免每次代码提交都生成镜像,造成资源浪费。这样也减少了不必要的版本推送,防止开发中的中间版本影响测试环境,提高整体流程的可控性。

新增Job简要流程

简要描述下环境配置好后(具体参考详细说明),新增Job的流程

  1. 在 GitLab 上配置 WebHook
    设置 WebHook 地址为:

    http://<JENKINS_URL>/generic-webhook-trigger/invoke
    

    同时随机生成一个 Secret Token,用于后续在 Jenkins 中配置对应的触发器。

  2. 准备 Jenkinsfile 与 Dockerfile
    在项目根目录下新增 Jenkinsfile。如果是模块化应用项目,应在对应模块根目录下新增 Dockerfile,以便后续构建镜像。

  3. 编写并修改 Jenkinsfile 配置
    根据实际项目需求调整 Jenkinsfile,例如配置构建模块名称(DOCKER_MODULE)、填写 GenericTrigger 的 Token 值(应与 GitLab WebHook 中设置的 Secret Token 保持一致)。

  4. 在 Jenkins 中创建 Pipeline Job
    登录 Jenkins,新建一个类型为 Pipeline 的 Job。
    在 Pipeline 配置中选择 Pipeline script from SCM,填写项目 Git 仓库地址,并配置 Jenkinsfile 所在分支(Branch Specifier)。

  5. 验证配置,执行测试构建
    保存 Job 后,点击 Build Now,测试是否可以正确拉取代码及 Jenkinsfile。成功后,补充其他构建参数与逻辑,完善整个 CI 流程。

代码文件目录样例

foo-center/                         # 项目根目录
├── pom.xml                         # 父POM文件,定义公共依赖和模块聚合
├── Jenkinsfile                     # Jenkins流水线配置文件
├── foo-center-api/                 # API模块(接口定义/DTO)
│   ├── pom.xml                     # 模块POM文件
│   ├── src/
│   │   ├── main/
│   │   │   ├── java/               # Java源代码
│   │   │   └── resources/          # 配置文件
│   │   └── test/                   # 测试代码
├── foo-center-service/             # Service模块(业务逻辑)
│   ├── pom.xml
│   ├── src/
│   │   ├── main/
│   │   │   ├── java/
│   │   │   └── resources/
│   │   └── test/
└── foo-center-boot/                # Boot模块(启动入口)
    ├── pom.xml
    ├── Dockerfile                  # Docker镜像构建文件
    ├── src/
    │   ├── main/
    │   │   ├── java/               # Spring Boot启动类
    │   │   └── resources/          # 应用配置文件
    │   └── test/
    └── target/                     # 构建输出目录(自动生成)
        └── foo-center-boot.jar     # 可执行JAR

注意事项

  • 避免多个 Job 共享 WebHook Token
    每个 Jenkins Job 应使用独立的 WebHook Token,以确保 WebHook 请求能正确匹配对应的 Job,避免误触发多个流水线。

  • 确保 Jenkinsfile 分支配置正确
    如果 Jenkinsfile 存储在 Git 仓库中,请确保 Branch Specifier 所指定的分支下存在该文件。
    Jenkinsfile 可保存在 SCM,也可直接写在 Jenkins 页面,按团队偏好选择。

  • 修改 GenericTrigger 配置时的注意点
    若需调整 GenericTrigger 的参数(如过滤规则),仅修改 Jenkinsfile 并不会生效。必须进入 Jenkins 页面,手动更新对应 Job 的配置,清除旧的触发器设置后,新的 Jenkinsfile 配置才会生效。

  • WebHook 地址需精确填写
    在 GitLab 中配置 WebHook 时,地址需设置为:

    http://<JENKINS_URL>/generic-webhook-trigger/invoke
    

    否则 Jenkins 无法正确接收触发请求。

  • Nexus 上的 Snapshot 仓库建议按环境隔离
    为每个环境(如 devtestuatprod)单独创建对应的 Snapshot 仓库,例如:

    • snapshot-dev
    • snapshot-test
    • snapshot-uat
    • snapshot-prod

    这样做的好处包括:

    • 避免环境间快照版本相互覆盖 防止测试串库;
    • 便于追溯各环境使用的构建版本 排查问题更有据可依;
    • 可为不同环境配置独立的清理策略 (如 dev 环境快照保留3天,prod 保留30天),提升存储管理效率;
    • 支持按环境维度做权限隔离 比如 prod 仓库只允许发布脚本写入。
  • 预生产/生产环境建议从源码 uat/prod 分支离线构建部署
    出于稳定性和可审计性考虑,生产发布应避免直接使用 SNAPSHOT 包或从 Jenkins 自动流水线部署,推荐流程如下:

    • 使用 uat/prod 分支进行代码审查与合并
    • 在受控环境下手动拉取 prod 分支源码
    • 通过构建机或 CI 工具进行离线构建并生成 Release 版本
    • 制品上传至 release-prod 仓库,供部署系统使用

补充说明
快照包是开发过程中的中间构建产物,频繁更新且非最终版本。通过仓库隔离,不仅清晰了每个环境的使用边界,也避免了因重复部署 SNAPSHOT 包带来的版本不一致或缓存污染问题。

核心实现细节

Nexus配置

多环境制品管理

Nexus仓库策略

仓库类型 命名规范 保留策略
Snapshot {project}-snapshot-{环境} 建议保留最后3个
Release {project}-release 永久保留
在Nexus创建项目snapshot镜像存储仓库

参考如下,提醒 Repository Policysnapshot

项目的Maven多环境配置

jar包推送配置应该是属于项目的,所以相关推送nexus的配置放于项目的pom.xml中,参考如下

<project>

    ....

    <!-- 定义环境变量对应的 Profile -->
    <profiles>
        <profile>
            <id>dev</id>
            <properties>
                <env>dev</env>
            </properties>
            <!-- 默认激活条件 -->
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
        </profile>
        <profile>
            <id>test</id>
            <properties>
                <env>test</env>
            </properties>
        </profile>
        <profile>
            <id>uat</id>
            <properties>
                <env>uat</env>
            </properties>
        </profile>
        <profile>
            <id>prod</id>
            <properties>
                <env>prod</env>
            </properties>
        </profile>
    </profiles>

    <!-- 定义不同环境的部署仓库(通过 Maven 属性动态切换) -->
    <distributionManagement>
        <snapshotRepository>
            <id>nexus-snapshots-${env}</id>  <!-- 使用属性 ${env} 动态替换 -->
            <!--suppress UnresolvedMavenProperty -->
            <url>http://192.168.1.100:8080/nexus/content/repositories/nexus-snapshots-${env}/</url>
        </snapshotRepository>
        <repository>
            <id>nexus-releases</id>
            <url>http://192.168.1.100:8080/nexus/content/repositories/releases/</url>
        </repository>
    </distributionManagement>
    
    ....
    
</project>

Jenkins

插件安装
  • Generic Webhook Trigger: https://plugins.jenkins.io/generic-webhook-trigger/ 允许 Jenkins 通过 ​HTTP Webhook 接收外部系统的触发请求(如 GitLab、GitHub、JIRA 等),并动态提取请求中的参数,实现高度灵活的自动化构建。
Docker相关配置
配置docker仓库地址

使用全局变量存储docker仓库地址配置

​进入Jenkins管理界面:
Dashboard → Manage Jenkins → System → Global properties → 勾选Environment variables

添加环境变量:

  • DOCKER_REGISTRY : Docker镜像仓库地址
  • DOCKER_REGISTRY_ORG : 组织(按需设置)​
配置docker镜像仓库账号密码

指定id为 docker-creds 方便后续使用

新建项目目录

因为项目比较多,用目录管理每个模块的 Pipeline Job

新增nexus的settings文件

参考settings.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" 
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
  <servers>
    <server>
      <id>nexus-snapshots-dev</id>
      <username>nexus_deploy</username>
      <password>abc123</password>
    </server>
    <server>
      <id>nexus-snapshots-test</id>
      <username>nexus_deploy</username>
      <password>abc123</password>
    </server>
    <server>
      <id>nexus-snapshots-uat</id>
      <username>nexus_deploy</username>
      <password>abc123</password>
    </server>
    <server>
      <id>nexus-snapshots-prod</id>
      <username>nexus_deploy</username>
      <password>abc123</password>
    </server>
    <server>
      <id>nexus-releases</id>
      <username>nexus_deploy</username>
      <password>abc123</password>
    </server>
  </servers>
  <!-- 公共仓库配置 -->
  <profiles>
    <profile>
      <id>global-public-repos</id>
      <repositories>
        <repository>
          <id>nexus-public</id>
          <url>http://192.168.1.100:8080/nexus/content/groups/public/</url>
          <releases>
            <enabled>true</enabled>
          </releases>
          <snapshots>
            <enabled>false</enabled>
          </snapshots>
        </repository>
      </repositories>
      <pluginRepositories>
        <pluginRepository>
          <id>nexus-public</id>
          <url>http://192.168.1.100:8080/nexus/co