zl程序教程

您现在的位置是:首页 >  工具

当前栏目

Jenkins + GitLab 自动化构建部署项目

2023-09-27 14:29:04 时间

在测试环境部署这块, 经历过以下几个阶段:

阶段一

有一台测试服务器把项目放上面测试, 当初也没有什么相关的经验, 每次改完代码本地打包上传到服务器上, 然后一顿命令启动项目, 完成了最原始的部署。

这种方式构建和部署全靠人肉, 项目简单的时候还好说, 项目一多配置一多 ( 比如微服务 ) 中间哪个环节粗心出点错那简直就是灾难。

同时还要专门有人对运维相关的技术比较了解, 不然哪天我不在测试工作就完全停滞了。

阶段二

既然都是重复工作, 那就整理下步骤写个脚本

从 SVN 拉代码

Maven 构建打包

重启 Tomcat

每次执行下脚本就搞定了。看着挺不错的, 不过实际执行时的情况总会复杂许多 ( 服务器帐号权限、测试人员对 Linux 的熟悉程度、项目启动依赖复杂等等问题 ) 。

阶段三

了解到 Jenkins 是个不错的工具, 那就把脚本的内容迁移到 Jenkins 上, 不管是开发还是测试只要在 web 界面上点击一下按钮即可完成构建部署, 很 easy。

阶段四

容器化: 使用 Docker 来部署项目, 这样就可以干掉原来服务器上散落各地参差不齐的 Tomcat ( 不同项目依赖不同 ) , 利用 Docker Compose 对项目进行编排, 提供一种规范的构建配置 ( 同时也是一份文档 ) , 大大减小了后期维护和交接的成本。

阶段五

上面的阶段已经能解决日常需求了, 但是还有一点问题就是每次提交完代码还要手动去 Jenkins 上发布, 能更自动点就更好了 ( 嗯, 就是懒 ) 。

于是就引出了本文的目标 —— 自动持续构建, 不需要人工操作 ( 留人工操作用于处理特殊情况 )

方案流程


流程图

开发提交代码

开发对需要发布的版本打上 Tag

触发 GitLab 的 tag push 事件, 调用 Webhook

Webhook 触发 Jenkins 的构建任务

Jenkins 构建完项目可以按版本号上传到仓库、部署、通知相关人员等等

安装 GitLab
GitLab 官方文档 已经介绍的比较详细了, 这里不再赘述, 下面给出最终调整过的 Docker Compose 配置:

 

gitlab:
  image: "twang2218/gitlab-ce-zh:11.0.2"
  restart: always
  hostname: 'gitlab'
  ports:
    - "10022:22"
    - "10080:10080"
    # postgresql 端口
    - "5432:5432"
  volumes:
    - ./gitlab/data:/var/opt/gitlab
    - ./gitlab/log:/var/log/gitlab
    - ./gitlab/config:/etc/gitlab
  environment:
    GITLAB_OMNIBUS_CONFIG: |
      # 仓库路径, 填写宿主机的域名或 IP
      external_url 'http://192.168.xxx.xxx:10080'
      # 调整工作进程数减小内存占用,最小为 2
      unicorn['worker_processes'] = 2
      gitlab_rails['time_zone'] = 'Asia/Shanghai'
 
      # 邮箱配置
      gitlab_rails['gitlab_email_from'] = '<your_email>'
      gitlab_rails['gitlab_email_display_name'] = '<your_email_name>'
      gitlab_rails['smtp_enable'] = true
      gitlab_rails['smtp_address'] = 'smtp.163.com'
      gitlab_rails['smtp_port'] = 25
      gitlab_rails['smtp_user_name'] = "<your_email_account>"
      gitlab_rails['smtp_password'] = "<your_email_password>"
      gitlab_rails['smtp_domain'] = 'smtp.163.com'
      gitlab_rails['smtp_tls'] = false
      gitlab_rails['smtp_openssl_verify_mode'] = 'none'
      gitlab_rails['smtp_enable_starttls_auto'] = false
      gitlab_rails['smtp_ssl'] = false
      gitlab_rails['smtp_force_ssl'] = false
 
      # 数据库配置
      gitlab_rails['db_host'] = '127.0.0.1'
      gitlab_rails['db_port'] = 5432
      gitlab_rails['db_username'] = "gitlab"
      gitlab_rails['db_password'] = "gitlab"
      
      postgresql['listen_address'] = '0.0.0.0'
      postgresql['port'] = 5432
      postgresql['md5_auth_cidr_addresses'] = %w()
      postgresql['trust_auth_cidr_addresses'] = %w(0.0.0.0/0)
      postgresql['sql_user'] = "gitlab"
      postgresql['sql_user_password'] = Digest::MD5.hexdigest "gitlab" << postgresql['sql_user']
 
      # 备份设置-保留7天
      gitlab_rails['backup_keep_time'] = 604800
    GITLAB_BACKUPS: "daily"
    GITLAB_SIGNUP: "true"
    GITLAB_ROOT_PASSWORD: "lb80h&85"
    GITLAB_GRAVATAR_ENABLED: "true"
说明:

这里使用 汉化版 镜像, 如果不适应可以换回 官方原版 镜像 gitlab/gitlab-ce:11.0.2-ce.0

项目初始配置 + 启动很慢, 需要一段时间, 日志中出现 Reconfigured 时表示启动成功

192.168.xxx.xxx 替换为宿主机的 IP 地址

初始管理员帐号密码: root / lb80h&85 ( 自行修改配置文件中的密码 )

该配置为 乞丐版 , 内存占用 2G+ ( worker_processes 越多内存占用越大, 默认为 8G )

postgresql 为容器中内置的数据库 ( 帐号: gitlab / gitlab ) , 没必要就不用暴露端口了

邮箱填写用于发送找回密码和通知的发件人帐号 ( 收不到邮件? ) , 不想配置就删掉相关配置好了, 不影响正常使用

安装 Jenkins
为了测试方便, 使用 Docker 化的 Jenkins , 如果需要调用一些特殊的命令或脚本就不是很方便, 实际使用过程中可以换成普通版的。

Docker Compose 配置如下:

 

version: '3'
services:
  jenkins:
    image: jenkins/jenkins:2.151
    container_name: jenkins
    networks:
    - net
    user: "root"
    restart: always
    ports:
    - 9000:8080
    environment:
    - JAVA_OPTS="-Duser.timezone=Asia/Shanghai"
    volumes:
    - /etc/localtime:/etc/localtime:ro
    - ./data:/var/jenkins_home:rw
    - ./backup:/var/jenkins_backup:rw
# 网络配置
networks:
  net:
    driver: bridge
    ipam:
      driver: default
      config:
      - subnet: 172.23.0.0/16
说明:

初次启动请打印日志, 日志中有管理员帐号的初始密码, 第一次登陆的时候需要用到

为了方便, 使用 root 帐号启动容器, 如果使用默认帐号启动需要修改本地目录 ( data、backup ) 的权限

配置 GitLab
注册账号什么的就不赘述了, 建一个测试项目 test , 随便 commit 几条内容

新建测试项目

按下图步骤创建账号的 access token , 用于 Jenkins 调用 GitLab 的 API

创建 access token

获取 access token

记下这里生成的 access token ( gRCtwVWU8cxwHdxxVZJD ) , 后面要用到。

配置 Jenkins
安装插件 ( 安装过程可能会失败,多试几次就好了 )

Git Parameter ( 用于参数化构建中动态获取项目分支 )

Generic Webhook Trigger ( 用于解析 Webhook 传过来的参数 )

GitLab ( 用于推送构建结果给 GitLab )

添加 GitLab 凭据

首页 -> 凭据 -> 系统 -> 全局凭据 -> 添加凭据, 把上面 GitLab 中生成的 access token 填进去

配置 GitLab 连接

首页 -> 系统管理 -> 系统设置 -> Gitlab 配置项, 填入 GitLab 相关的配置, 后面配置项目时用到

新建项目 test

Jenkins项目完整配置

勾选 参数化构建过程, 添加 Git Parameter 类型的参数 ref , 这样构建的时候就可以指定分支进行构建。

Source Code Management 选择 Git , 添加项目地址和授权方式 ( 帐号密码 或者 ssh key ) , 分支填写构建参数 $ref。

Build Triggers 选择 Generic Webhook Trigger 方式用于解析 GitLab 推过来的详细参数 ( jsonpath 在线测试 ) 。其他触发方式中: Trigger builds remotely 是 Jenkins 自带的, Build when a change is pushed to GitLab 是 GitLab 插件 提供的, 都属于简单的触发构建, 无法做复杂的处理。

虽然 Generic Webhook Trigger 提供了 Token 参数进行鉴权, 但为了避免不同项目进行混调 ( 比如 A 项目提交代码却触发了 B 项目的构建) , 还要对请求做下过滤。Optional filter 中 Text 填写需要校验的内容 ( 可使用变量 ) , Expression 使用正则表达式对 Text 进行匹配, 匹配成功才允许触发构建。

Build 内容按自己实际的项目类型进行调整, 使用 Maven 插件 或 脚本 等等。

GitLab Connection 选择上面添加的 GitLab 连接 ( Jenkins ) , Post-build Actions 添加 Publish build status to GitLab 动作, 实现构建结束后通知构建结果给 GitLab。

回到 GitLab 的项目页面中, 添加一个 Webhook ( http://JENKINS_URL/generic-webhook-trigger/invoke?token=<上面 Jenkins 项目配置中的 token> ) , 触发器选择 标签推送事件。因为日常开发中 push 操作比较频繁而且不是每个版本都需要构建, 所以只针对需要构建的版本打上 Tag 就好了。

gitlab添加 Webhook

创建完使用 test 按钮 先测试下, 可能会出现下面的错误

Hook execution failed: URL 'http://192.168.xxx.xxx:9000/generic-webhook-trigger/invoke?token=d63ad84eb18cb04d4459ec347a196dce' is blocked: Requests to the local network are not allowed

解决办法: 允许 GitLab 本地网络发送 Webhook 请求

测试效果
可以在 GitLab 直接添加 Tag , 不过我觉得用 IDEA 上操作更方便点, 就把代码拉下来在本地操作

针对每个commit添加tag

然后使用快捷键 Ctrl + Shift + K 调出 Push 窗口 , 把 Tag 推送到 GitLab 中

push tag

回到 GitLab 页面可以看到触发了 Webhook , View details 查看请求详情, Response body 中 triggered 字段值为 true 则表示成功触发了 Jenkins 进行构建

Webhook 触发历史

再看下构建结果

gitlab 查看构建结果 — 流水线

gitlab 中查看构建结果 — commits

注意: 每添加一个 Tag 就会触发一次事件, 不管是不是一起 push 的。所以一次 push 多个 Tag 会触发 Jenkins 进行多次构建。不过 Jenkins 已经做了处理, 默认串行执行任务 ( 一个任务结束再执行下一个 ) , 而且在构建前有一个 pending 状态, 此时被多次触发会进行合并, 并取首次触发的参数, 如下图所示:

同时触发多次事件

关于 Tag 的几点说明
推送 Tag 到远端的时候, 远端已存在 ( 同名 ) 的 Tag 不会被添加到远端

拉取远端的 Tag 时, 本地已存在 ( 同名 ) 的 Tag 不会添加到本地

拉取远端的 Tag 时, 本地不会删除远端已删除的 Tag , 需要同步远端的 Tag 可以先删除本地所有 Tag 再 pull

删除 Tag 也会推送事件, 要做好过滤 ( 上面配置中已使用 commitsId 字段进行过滤 )

未完待续
通过上面的步骤已经初步实现了想要的效果, 还有几个点后续可以再考虑下:

上文只包含自动构建的内容, 对于项目的部署可以考虑几种方式: 手动选择指定的版本进行发布、构建任务结束后直接触发部署任务、定时部署最新版本 ( 根据实际需求调整 )。

测试发版的频率会比较高, 会生成大量的 Tag , 可以约定 Tag 的格式, 比如 test 0.0.1 表示触发测试环境的项目构建, online 1.0.0 表示触发正式版本构建, 隔离之后可以方便后续的维护和清理。

构建部分可以整合 Docker , 把构建结果打包到 Docker 镜像中 ( 代码版本库的 Tag 正好可以作为镜像的 Tag ) , 再上传到 Docker 镜像仓库 ( 私服 或者第三方仓库 ) 中, 后续部署就可以直接从镜像仓库拉取镜像直接运行了。

集成自动化测试 , 比如 这个

尝试配置 GitLab 自带的 CI / CD

总结
以上就是对曾经踩过的一些坑进行的整合, 也没什么好总结的。总之, 合理地利用现有工具来解放双手, 就能有更多时间做其他想做的事!

时间有限一些基础的步骤就不细讲直接一笔带过了, 方案上可能有些细节方面也没考虑全, 欢迎评论留言。
————————————————
版权声明:本文为CSDN博主「zhangjunli」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zhangjunli/article/details/108436980