基于Jenkins实现的CI/CD方案

news2024/11/18 20:36:55

基于Jenkins实现的CI/CD方案

前言

最近基于Jenkins的基座,搭建了一套适用于我们项目小组的持续集成环境。现在把流程整理分享出来,希望可以给大家提供一些帮助和思路。

使用到的组件和版本

组件名称组件版本作用
Harbor2.7.3镜像仓库
Jenkins2.319.2持续集成工具
Pipeline2.6Jenkins插件,编排流水线脚本
SSH Pipeline Steps2.0.0Jenkins插件,提供远程执行ssh能力
Git4.10.1Jenkins插件,提供拉取git代码仓库的能力
Httpd2.4.18HTTP服务器,用于归档编译后的软件包,镜像包
Maven3.6.3后端代码构建工具
Node8.17.0前端代码构建工具
Docker20.10.0容器版本
Docker Composev2.18.1容器编排

我这边是基于Jenkins的Pipeline+Docker的方式进行的任务编排,Jenkins是找的一个别人做好的,内置了绝大多数插件的容器版本,链接地址:https://hub.docker.com/r/h1kkan/jenkins-docker。这个做好的镜像里面没有SSH Pipeline Steps这个插件,需要自己额外下载一下,这边需要注意一下插件和Jenkins的对应版本。

基本流程图


这边有几个需要注意的地方,简单说明一下

  1. 首先需要配置代码仓库的webhook,这个网上有很多资料,可以自行参考配置一下

  2. dockerfile,docker-compose.yml这些文件需要内置在代码仓库中或者服务器内(我们是dockerfile文件内置在代码仓库,docker-compose.yml文件放在服务器里面固定目录)

  3. 在第五步,执行远端ssh时,需要去更改docker-compose.yml中的image节点,一开始准备用shell去做的,但是实现有点难度,然后就内置了一个python脚本,用yaml这个库去实现的,具体脚本updateImageLabel.py参考:

    import yaml
    import sys
    
    filename = sys.argv[1]
    # 加载docker-compose.yml文件
    with open(filename,'r') as f:
        data = yaml.load(f)
    # 更新镜像标签
    data['services'][sys.argv[2]]['image'] = sys.argv[3]
    with open(filename, 'w') as yaml_file:
        yaml_file.write(yaml.dump(data, default_flow_style=False))
    

    使用时,传入三个参数,分别是docker-compose.yml文件路径,需要更新的服务,更新后的镜像标签

    python3 updateImageLabel.py ${dockerComposePath}  ${service}  ${image}
    
  4. Harbor的安装可以参考我之前的博客,安装完成如果是http的话,还需要配置一下insecure-registries仓库信息,并且执行docker login命令登录镜像仓库,用于拉取Harbor仓库镜像

    {
      "insecure-registries": [
        "harbor服务器地址"
      ]
    }
    
  5. 第七步是可选的,做这个是为了方便每一个版本的归档,这边可以归档软件包或者save之后的镜像包

具体实现步骤

下面具体写一下实现的步骤,因为涉及的东西很多,有一些能找到的通用的步骤我就先不写了,大家可以自行去百度或者Google。

基础中间件部署

这边只讲Jenkins和Httpd的部署,Harbor部署可以参考我之前的文档。

Jenkins部署

通过docker的方式拉起Jenkins

docker run -u root -e TZ=Asia/Shanghai --name=jenkins -d -e TZ="Asia/Shanghai" -p 8080:8080 -p 50000:50000 -v /data/jenkins:/var/jenkins_home -v /run/docker.sock:/var/run/docker.sock -v /data/archive:/data/archive h1kkan/jenkins-docker:2.319.2

容器起来之后,需要进入到容器内部执行一下docker login的命令,在Jenkins容器内部也生成一套Harbor的凭证。

第三个挂载目录是用来开给Httpd服务器的,用于归档软件包和镜像包。

Httpd服务器部署

通过docker拉起Httpd服务器

docker run -p 8001:80 -v /data/archive:/usr/local/apache2/htdocs/ -d --name httpd httpd:2.4.18 

这边挂载目录就是Jenkins开出来的目录

Maven、Node、JDK等基础镜像

可以先从外网拉取对应版本,然后本地打成tar包之后上传到服务器解压,再tag之后推送到自己的Harbor仓库。

在Jenkins配置Git凭证

这个网上也很多,就不细致展开了,可以自己查一下

Pipeline流水线编排

后端流水线pipeline脚本
import java.text.SimpleDateFormat
import java.util.TimeZone

// 构建版本
def createVersion() {
    def simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss")
    simpleDateFormat.timeZone = TimeZone.getTimeZone("Asia/Shanghai")
    return simpleDateFormat.format(new Date()) + "_${env.branch}"
}

def getTime() {
    def simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss")
    simpleDateFormat.timeZone = TimeZone.getTimeZone("Asia/Shanghai")
    return simpleDateFormat.format(new Date())
}

// 获取远端服务器信息 
def GetRemoteServer(ip, username, password) {
    def remote = [:]
    remote.name = ip
    remote.host = ip
    remote.user = username
    remote.password = password
    remote.allowAnyHosts = true
    return remote
}

pipeline {
    agent none
    environment {
        _version = createVersion()
        _time = getTime()
    }
    stages {
        stage('Git Checkout') {
            agent any
            steps {
                checkout([
	                $class: 'GitSCM', 
	                branches: [[name: "${branch}"]], 
	                doGenerateSubmoduleConfigurations: false, 
	                extensions: [], 
	                gitTool: 'Default', 
	                submoduleCfg: [], 
	                userRemoteConfigs: [[url: '{{git_url}}',credentialsId: '{{credentialsId}}',]]
                ])
            }
        }
        stage('Source Package') {
            agent {
                docker { 
                    image 'local-maven:3.6.3-openjdk-8' 
                    args '-v maven-repo:/usr/share/maven/ref'
                }
            }
            steps {
                sh 'mvn clean install -Dmaven.test.skip=true'
            }
        }
      
        stage('Build Image') {
            agent any
            steps {
                sh 'docker build -f $WORKSPACE/CI/dockerfile --build-arg JARNAME=backend.jar -t 127.0.0.1:18080/library/backend:${_version} $WORKSPACE/backend/target/'
                sh 'docker push 127.0.0.1:18080/library/backend:${_version}'
                sh 'docker rmi 127.0.0.1:18080/library/backend:${_version}'
            }
        }

        stage('Publish To Env') {
            agent any
            steps {
                script {
                    def remote = [:]
                    remote = GetRemoteServer('127.0.0.1', 'username', 'password')
                  	sshCommand remote: remote, command: "python3 updateImageLabel.py docker-compose.yml backend 127.0.0.1:18080/library/backend:${_version}"
                  	sshCommand remote: remote, command: "docker-compose -f docker-compose.yml up -d --build backend"
                }
            }
        }
          
        stage('Archive Package') {
            agent any
            steps {
                sh 'mkdir -p /data/archive/backend/${branch}/${_time}'
                sh 'cp $WORKSPACE/backend/backend.jar /data/archive/backend/${branch}/${_time}'
            }
        }
    }
}

解释一下这个脚本

  • 首选镜像的版本是时间戳+分支的格式,类似20231026095511_dev,可以根据项目组的要求进行生成。

  • GetRemoteServer方法主要是提供获取远端服务器的信息,主要使用了SSH Pipeline Steps这个插件的能力,传入ip,username,password三个参数,这边密码是明文写死在脚本里面的,这个插件也支持密码加密保存,如果安全性要求比较高的可以换成加密的方式。

  • Git Checkout 这个stage主要是进行代码的下载,根据${branch}这个参数来指定代码仓库的版本,参数的具体配置可以看下Jenkins参数化构建的相关指导和文章。

  • Source Package就是代码仓库的打包,这边指定使用Docker镜像作为执行的Agent,只要指定镜像和编译命令就可以。这边我还挂载了一个maven-repo的volume,主要是为了缓存Jar包,不用每次都去下载。

  • Build Image步骤进行代码的构建,通过docker-build命令去生成镜像,这边的dockerfile文件是内置在我们代码库中的,参考如下:

    FROM 127.0.0.1:18080/library/java:8.0
    ARG JARNAME
    COPY ${JARNAME} /data/
    
  • Publish To Env 推送到环境,这边核心就是连接到远程服务器,通过修改镜像标签的脚本去更新docker-compose.yml文件中的镜像标签,然后重新构建容器

  • Archive Package 是否归档,演示的脚本里面只是归档了编译后的文件,还可以归档镜像等等。归档的路径为分支名/时间戳
    在这里插入图片描述

前端流水线pipeline脚本
import java.text.SimpleDateFormat
import java.util.TimeZone

// 构建版本
def createVersion() {
    def simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss")
    simpleDateFormat.timeZone = TimeZone.getTimeZone("Asia/Shanghai")
    return simpleDateFormat.format(new Date()) + "_${env.branch}"
}

def getTime() {
    def simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss")
    simpleDateFormat.timeZone = TimeZone.getTimeZone("Asia/Shanghai")
    return simpleDateFormat.format(new Date())
}

// 获取远端服务器信息 
def GetRemoteServer(ip, username, password) {
    def remote = [:]
    remote.name = ip
    remote.host = ip
    remote.user = username
    remote.password = password
    remote.allowAnyHosts = true
    return remote
}

pipeline {
    agent none
    environment {
        _version = createVersion()
        _time = getTime()
    }
    stages {
        stage('Git Checkout') {
            agent any
            steps {
                checkout([
	                $class: 'GitSCM', 
	                branches: [[name: "${branch}"]], 
	                doGenerateSubmoduleConfigurations: false, 
	                extensions: [], 
	                gitTool: 'Default', 
	                submoduleCfg: [], 
	                userRemoteConfigs: [[url: '{{git_url}}',credentialsId: '{{credentialsId}}',]]
                ])
            }
        }
        stage('Source Package') {
            agent {
                docker { 
                    image 'node:8.17.0' 
                }
            }
            steps {
                script {
                    sh 'npm install --registry=http://registry.npm.taobao.org'
                }
            }
        }
        stage('Image Build') {
            agent any
            steps {
                sh 'docker build -f $WORKSPACE/CI/dockerfile -t 127.0.0.1:18080/library/frontend:${_version} $WORKSPACE/target/'
                sh 'docker push 127.0.0.1:18080/library/frontend:${_version}'
                sh 'docker rmi 127.0.0.1:18080/library/frontend:${_version}'
            }
        }
        stage('Publish To Env') {
            agent any
            steps {
                script {
                    def remote = [:]
                    remote = GetRemoteServer('127.0.0.1', 'username', 'password')
                    // 更新docker-compose.yml文件,修改镜像
                    sshCommand remote: remote, command: "python3 updateImageLabel.py docker-compose.yml frontend 127.0.0.1:18080/library/frontend:${_version}"
                    sshCommand remote: remote, command: "docker-compose -f docker-compose.yml up -d --build frontend"

                }
            }
        }
        stage('Archive Package') {
            agent any
            steps {
                sh 'mkdir -p /data/archive/frontend/${branch}/${environment}/${_time}'
                sh 'cd $WORKSPACE/target/dist/ && zip -r dist.zip *'
                sh 'cp $WORKSPACE/target/dist/dist.zip /data/archive/frontend/${branch}/${environment}/${_time}'
            }
        }
    }
}

前端和后端除了构建方式不一样,其他基本都相同。

结语

参考地址:

https://www.jenkins.io/doc/book/pipeline/

https://www.jenkins.io/doc/pipeline/steps/ssh-steps/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1462170.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【鸿蒙系统学习笔记】网络请求

一、介绍 资料来自官网:文档中心 网络管理模块主要提供以下功能: HTTP数据请求:通过HTTP发起一个数据请求。WebSocket连接:使用WebSocket建立服务器与客户端的双向连接。Socket连接:通过Socket进行数据传输。 日常…

Adobe将类ChatGPT集成到PDF中

2月21日,全球多媒体巨头Adobe在官网宣布,推出生成式AI助手AI Assistant,并将其集成在Reader 和Acrobat 两款PDF阅读器中。 据悉,AI Assistant的功能与ChatGPT相似,可以基于PDF文档提供摘要、核心见解、基于文档内容&a…

[bing]“gang调度 Kubernetes的并发控制和一致性机制“论点的对应的源码分析

你是一位K8S专家。请分析在Kubernates(https://github.com/kubernetes/kubernetes.git)项目和调度coscheduling(https://github.com/kubernetes-sigs/scheduler-plugins/tree/master/pkg/coscheduling) 插件中支撑"PodGroup的管理和调度决策涉及到对…

​Fruity Loops Studio21.2.3软件中文版官方功能介绍

​Fruity Loops Studio 21.2 软件功能介绍 一、概述 Fruity Loops Studio,现更名为FL Studio,是一款由Image-Line公司开发的数字音频工作站(DAW)。该软件广泛用于音乐创作、编曲、录音、混音和制作。FL Studio 21.2是其近期的一…

ARMv8-AArch64 的异常处理模型详解之异常向量表vector tables

目录 一,AArch64 异常向量表 二,栈指针以及SP寄存器的选择 三,从异常返回 一,AArch64 异常向量表 异常向量表(vector tables)是一组存放于普通内存(normal memory)空间的&#xf…

JavaWeb——002JS Vue快速入门

目录 一、JS快速入门​编辑 1、什么是JavaScript?​编辑 2、JS引入方式​编辑 2.1、示例代码 3、JS基础语法 3.1、书写语法 3.2、变量​编辑 3.3、数据类型 3.4、运算符​编辑 3.5、流程控制语句​编辑 4、JS函数 4.1、第一种函数定义方式 function funcName(参数…

什么是数组

目录 概念 案例 有变量,为什么还要数组? 概念 数组就是一个容器,用来存一批同种类型的数据。 案例 有变量,为什么还要数组? 1、假设用变量解决时间点名的需求 代码繁琐:大量变量的定义。 实现需求繁琐…

linux platform架构下I2C接口驱动开发

目录 概述 1 认识I2C协议 1.1 初识I2C 1.2 I2C物理层 1.3 I2C协议分析 1.3.1 Start、Stop、ACK 信号 1.3.2 I2C协议的操作流程 1.3.3 操作I2C注意的问题 2 linux platform驱动开发 2.1 更新设备树 2.1.1 添加驱动节点 2.1.2 编译.dts 2.1.3 更新板卡中的.dtb 2.2 …

Win11蓝屏开不了机进入安全模式的快速方法

最近,很多使用Win11电脑的用户都在反映自己遇到了蓝屏问题,这时候想通过进入系统的安全模式,来解决电脑蓝屏的问题,却不知道进入安全模式的具体操作方法,下面给大家介绍最简单快速的进入方法,帮助大家轻松解…

NDK的log.h使用__android_log_print报错app:buildCMakeDebug[x86_64]

org.gradle.api.tasks.TaskExecutionException: Execution failed for task :app:buildCMakeDebug[x86_64] 重点是 Execution failed for task :app:buildCMakeDebug[x86_64]. 我的代码&#xff1a; #include <android/log.h> #define LOG_TAG "MyJNI" #d…

游戏同步+游戏中的网络模块

原文链接&#xff1a;游戏开发入门&#xff08;九&#xff09;游戏同步技术_游戏数据同步机制流程怎么开发-CSDN博客 游戏开发入门&#xff08;十&#xff09;游戏中的网络模块_游戏开发组网-CSDN博客 3.同步技术的基本常识&#xff1a; a.同步给谁&#xff1f;某个用户&…

二叉树基础知识总结

目录 二叉树基础知识 概念 : 根节点的五个形态 : 特殊的二叉树 满二叉树 : 完全二叉树 : 二叉搜索树 : 平衡二叉搜索树 : 二叉树的性质 : 二叉树的存储结构 二叉树的顺序存储结构 二叉树的链式存储结构 二叉树的遍历方式 : 基础概念 前中后遍历 层序遍历 :…

解决Ultra 5 125H处理器核显使用solidworks卡顿问题

硬件环境&#xff1a;机械革命 无界14pro Ultra 5 125H 软件环境&#xff1a;windows11 solidworks2023 现象&#xff1a;在使用solidworks作图时&#xff0c;软件卡顿&#xff0c;鼠标无法拖动模型 解决办法&#xff1a; 1&#xff0c;下载并安装solidworks官方给出的修补程…

c语言经典测试题2

1.题1 我们来思考一下它的结果是什么&#xff1f; 我们来分析一下&#xff1a;\\是转义为字符\&#xff0c;\123表示的是一个八进制&#xff0c;算一个字符&#xff0c;\t算一个字符&#xff0c;加上\0&#xff0c;应该有13个&#xff0c;但是strlen只计算\0前的字符个数。所以…

3个脚本练习

1.判断当前磁盘剩余空间是否有20G&#xff0c;如果小于20G&#xff0c;则将报警邮件发送给管理员&#xff0c;每天检查一次磁盘剩余空间。 1.下载mailx服务并设置 yum install mailx -y vim /etc/mail.rc 将下列内容写入文件末尾即可 ​​​​​​​set from自己邮箱qq.…

【计算机网络】socket 网络套接字

网络套接字 一、端口号1. 认识端口号2. socket 二、认识TCP协议和UDP协议1. TCP协议2. UDP协议 三、网络字节序四、socket 编程1. socket 常见API2. sockaddr 结构3. 编写 UDP 服务器&#xff08;1&#xff09;socket()&#xff08;2&#xff09;bind()&#xff08;3&#xff0…

SQL注入之DNSLog外带注入

一、认识&#xff1a; 什么是dnslog呢&#xff1f; DNS就是域名解析服务&#xff0c;把一个域名转换成对应的IP地址&#xff0c;转换完成之后&#xff0c;DNS服务器就会有一个日志记录本次转换的时间、域名、域名对应的ip、请求方的一些信息&#xff0c;这个日志就叫DNSLog。…

单体微服务K8S笔记

单体微服务K8S笔记 https://blog.csdn.net/m0_48341969/article/details/126063832思路参考以上博客 //测试 https://gitee.com/yangbuyi/yi项目组织参考以上git 单体&#xff1a; 不特地介绍 微服务&#xff1a; rpc:远程过程调用 拆分&#xff0c;分别部署&#xff0…

无人机快递(物流)技术方案,无人机快递(物流)基础知识

无人机快递技术是一种利用无人机进行快递配送的先进技术。通过利用无人机&#xff0c;快递企业能够在偏远地区或难以通行的地区提供配送服务&#xff0c;同时提高配送效率并降低人力成本。 无人机基本情况 无人驾驶飞机简称“无人机”&#xff0c;是利用无线电遥控设备和自备的…

跨境电商选品推荐:如何在Shopee上找到热销商品?

在当今全球化的商业环境中&#xff0c;跨境电商成为越来越多企业和个人的选择。而在跨境电商中&#xff0c;选品是至关重要的一环&#xff0c;因为选对了产品&#xff0c;销售就迈出了成功的一步。在众多跨境电商平台中&#xff0c;Shopee作为新兴的明星平台&#xff0c;备受关…