• DevOps持续集成-Jenkins(4)


    DevOps

    DevOps概述

    软件开发最初是由两个团队共同组成:(没有采用DevOps之前)

    • 开发团队:从头开始设计和整体系统的构建(编写代码)。需要系统不停的迭代更新。
    • 运维团队:将开发团队的代码进行测试通过后再部署上线。确保系统稳定运行。

    没有采用DevOps的缺点:

    • 这看似两个目标不同的团队需要协同完成一个软件的开发。在开发团队指定好计划并完成编写代码后,需要把代码交给运维团队。运维团队向开发团队反馈需要修复的BUG以及一些需要返工的任务。这时开发团队需要经常等待运维团队的反馈。这无疑会延长整个软件开发的周期。

    采用DevOps的优点?

    • DevOps的方式可以让公司能够更快地应对更新和市场发展变化,开发可以快速交付,部署也更加稳定。核心就在于简化Dev和Ops团队之间的流程,使整体软件开发过程更快速。说白了就是DevOps有利于快速完成项目,不会浪费时间)

    整体的软件开发流程:

    • PLAN:开发团队根据客户的目标制定开发计划
    • CODE:根据PLAN开始编码过程,需要将不同版本的代码存储在一个库中。
    • BUILD:编码完成后,需要将代码构建并且运行。
    • TEST:成功构建项目后,需要测试代码是否存在BUG或错误。
    • DEPLOY:代码经过手动测试和自动化测试后,认定代码已经准备好部署并且交给运维团队。
    • OPERATE:运维团队将代码部署到生产环境中。
    • MONITOR:项目部署上线后,需要持续的监控产品。
    • INTEGRATE:然后将监控阶段收到的反馈发送回PLAN阶段,整体反复的流程就是DevOps的核心即持续集成、持续部署。

    为了保证整体流程可以高效的完成,各个阶段都有比较常见的工具,如下图:

    Jenkins流水线任务入门⭐

    Jenkins流水线任务的Hello World体验⭐

    在这里插入图片描述在这里插入图片描述在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述

    Jenkins流水线语法例子
    // 所有脚本命令包含在pipeline{}中
    pipeline {  
    	// 指定任务在哪个Jenkins集群节点中执行(Jenkins是支持分布式)
    	// 这里的agent any是指该任务可以在任何Jenkins集群节点上执行。
        agent any
        
        // 声明全局变量,格式为:key='value'
        environment{
        	host = '192.168.184.80'
        }
    
        // 存放所有任务的合集
        stages {
        	// 单个任务1
            stage('任务1') {
            	// 实现任务的具体流程
                steps {
                    echo '做任务1'
                }
            }
    		// 单个任务2
            stage('任务2') {
            	// 实现任务的具体流程
                steps {
                    echo '做任务2'
                }
            }
            // 单个任务3
            stage('任务3') {
            	// 实现任务的具体流程
                steps {
                    echo '做任务3'
                }
            }
            
            
            
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    Jenkins流水线语法生成器⭐

    在这里插入图片描述在这里插入图片描述
    在这里插入图片描述

    Jenkins实战4:构建pipeline(流水线)的Jenkins项目⭐

    项目架构图

    在这里插入图片描述

    Jenkins实战4的初步流水线模板(功能全部都未实现)⭐
    pipeline {
        agent any
    
        // 存放所有任务的集合
        stages {
            stage('拉取Git仓库代码') {
                steps {
                    echo '拉取Git仓库代码 - SUCCESS'
                }
            }
            
            stage('通过maven构建项目') {
                steps {
                    echo '通过maven构建项目 - SUCCESS'
                }
            }
            
            stage('通过SonarQube做代码质量检测') {
                steps {
                    echo '通过SonarQube做代码质量检测 - SUCCESS'
                }
            }
    
            stage('通过Docker制作自定义镜像') {
                steps {
                    echo '通过Docker制作自定义镜像 - SUCCESS'
                }
            }
    
            stage('将自定义镜像推送到Harbor仓库') {
                steps {
                    echo '将自定义镜像推送到Harbor仓库 - SUCCESS'
                }
            }
    
            stage('通过Publish Over SSH通知目标服务器') {
                steps {
                    echo '通过Publish Over SSH通知目标服务器 - SUCCESS'
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    Jenkinsfile配置⭐
    在项目中编写Jenkinsfile来维护pipeline模板(以后我们的pipeline语法都放在这个文件上)⭐
    • 注意:该文件名一定要为:Jenkinsfile
    • Jenkinsfile文件内容放在了上面,可以直接复制!

    在这里插入图片描述

    在Jenkins中配置Jenkinsfile在gitlab上的地址⭐

    在这里插入图片描述在这里插入图片描述在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    测试构建,看看Jenkinsfile是否能生效

    在这里插入图片描述

    架构图第2步案例:将gitlab上面的项目代码拉取到Jenkins中⭐
    • 1:配置git参数:(根据tag去拉取代码)
      在这里插入图片描述在这里插入图片描述在这里插入图片描述

    • 2:生成拉取git代码的流水线语法:

      • 生成的语法代码块如下:(注意:下面有个地方(branches的name从原来是/main被我改成了${tag},如果安装默认生成的话,则是拉取最新版本代码,我们这个意思就是安装tag去拉取对应代码)和系统生成的语法不一样!!)*
      checkout([$class: 'GitSCM', branches: [[name: '${tag}']], extensions: [], userRemoteConfigs: [[url: 'http://192.168.184.70:8929/root/mytest.git']]])
      
      • 1

    在这里插入图片描述在这里插入图片描述

    • 3:把生成的pipeline语法放到Jenkinsfile文件的指定位置:

    在这里插入图片描述

    • 4:测试构建:

    在这里插入图片描述

    架构图第3步案例:利用Maven构建项目的jar包⭐
    • 1:生成流水线语法:(生成如下)
      • 注意:/var/jenkins_home/maven/bin/mvn要改成你的maven的mvn地址。
    sh '/var/jenkins_home/maven/bin/mvn clean package -DskipTests'
    
    • 1

    在这里插入图片描述

    • 2:将上面生成的语法放到Jenkinsfile的对应位置上去,然后上传到gitlab即可。(省略!)
    架构图第4步案例:给Jenkins的pipeline任务配置SonarQube自动进行代码质量检测⭐
    • 1:生成流水线语法:(生成如下)
      • 注意:下面的-Dsonar.login要用自己的SonarQube的token
      • 注意:/var/jenkins_home/sonar-scanner/bin/sonar-scanner要改成你的sonar-scanner地址
    sh '/var/jenkins_home/sonar-scanner/bin/sonar-scanner -Dsonar.sources=./ -Dsonar.projectname=${JOB_NAME} -Dsonar.projectKey=${JOB_NAME} -Dsonar.java.binaries=./target/ -Dsonar.login=7ad2200f7cca90c37a909fdba8db049ac700909f'
    
    • 1

    在这里插入图片描述

    • 2:将上面生成的语法放到Jenkinsfile的对应位置上去,然后上传到gitlab即可。(省略!)
    架构图第5步案例:Jenkins制作自定义镜像并上传到Harbor⭐
    • 1:生成制作自定义镜像的流水线语法(生成如下):
    sh '''mv ./target/*.jar ./docker/
    docker build -t ${JOB_NAME}:${tag} ./docker/'''
    
    • 1
    • 2

    在这里插入图片描述

    • 2:在Jenkinsfile文件定义全局变量environment:(记得要把下面的内容改成你自己的!)
      • harborAddress是harbor地址
      • harborRepo是harbor仓库名
      • harborUser是harbor账号
      • harborPasswd是Harbor密码
        environment{
            harborAddress = '192.168.184.80:80'
            harborRepo = 'repo'
            harborUser = 'admin'
            harborPasswd = 'Harbor12345'
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 3:生成将镜像上传到Harbor仓库的流水线语法(生成如下):
    sh '''docker login -u ${harborUser} -p ${harborPasswd} ${harborAddress}
    docker tag ${JOB_NAME}:${tag} ${harborAddress}/${harborRepo}/${JOB_NAME}:${tag}
    docker push ${harborAddress}/${harborRepo}/${JOB_NAME}:${tag}'''
    
    • 1
    • 2
    • 3

    在这里插入图片描述

    • 4:防止Jenkins内部不能使用Docker,所以重新设置一下权限:(有时候即使设置了权限也会自动变回来,导致pipeline报错)

      • 切换目录到/var/run/:
      [root@centos7-jenkins harbor]# cd /var/run/
      
      • 1
      • 修改docker.sock文件的所属组:
      [root@centos7-jenkins run]# chown root:root docker.sock
      
      • 1
      • 修改docker.sock文件的权限:
      [root@centos7-jenkins run]# chmod o+rw docker.sock
      
      • 1
    • 5:将上面生成的语法放到Jenkinsfile的对应位置上去,然后上传到gitlab即可。

    在这里插入图片描述在这里插入图片描述

    • 6:执行构建即可。
    • 7:进入Harbor可视化界面,查看pipeline镜像是否push成功:

    在这里插入图片描述

    架构图第6-7步案例:通知目标服务器可以从Harbor上拉取镜像,并运行容器(注意:这里有个坑!)⭐
    • 1:在所有目标服务器上都放一份shell脚本文件:(原理是:Jenkins通知目标服务器去执行shell脚本文件,从而让目标服务器在Harbor上面拉取指定镜像。)
      • 原来的架构图上是把Dockerfile传到目标服务器,让目标服务器通过docker build构建镜像(缺点是当目标服务器有多台,那每一台目标服务器都需要build构建一次,n台服务器就是n次,这样十分浪费服务器资源)。
      • 现在的架构图是把镜像在Jenkins容器内构建,然后把镜像push到Harbor上,Jenkins通知所有目标服务器(不管有多少台),然后目标服务器就会执行下面的shell脚本,会从Harbor拉取指定镜像,这样一来,不管有多少台目标服务器都只是build构建一次,节省了很多资源。
    vi /root/deploy.sh
    
    • 1

    内容如下:

    harbor_addr=$1
    harbor_repo=$2
    project=$3
    version=$4
    host_port=$5
    container_port=$6
    
    imageName=$harbor_addr/$harbor_repo/$project:$version
    
    containerId=`docker ps -a | grep ${project} | awk '{print $1}'`
    if [ "$containerId" != "" ] ; then
        docker stop $containerId
        docker rm $containerId
    fi
    
    tag=`docker images | grep ${project} | awk '{print $2}'`
    
    if [[ "$tag" =~ "$version" ]] ; then
        docker rmi -f $imageName
    fi
    
    docker login -u admin -p Harbor12345 $harbor_addr
    
    docker pull $imageName
    
    docker run -d -p $host_port:$container_port --name $project $imageName
    
    echo "SUCCESS"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 2:给deploy.sh权限:
    chmod a+x /root/deploy.sh
    
    • 1
    • 3:把所有目标服务器的deploy.sh都放到/usr/bin下:
    [root@centos7-jenkins ~]# mv /root/deploy.sh /usr/bin/
    
    • 1
    • 4:配置Jenkins参数:

    在这里插入图片描述在这里插入图片描述在这里插入图片描述

    • 5:生成流水线语法:

      • 提示Exec command:
      deploy.sh $harborAddress $harborRepo $JOB_NAME $tag $host_port $container_port
      
      • 1

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    • 6:将生成的语法放到Jenkinsfile的对应位置上去,然后上传到gitlab即可。(⭐注意这里有个坑!⭐)

      • 坑坑坑!!!:sshPublisher的execCommand要用双引号,默认是单引号。(一定要改成双引号,否则语法无法生效!⭐)

      ⭐下面的是修改之后的,并且是测试通过的流水线语法!!:

    sshPublisher(publishers: [sshPublisherDesc(configName: 'mytest', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "deploy.sh $harborAddress $harborRepo $JOB_NAME $tag $host_port $container_port", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
    
    • 1
    • 7:最后测试构建即可(省略!)
    Jenkins流水线整合钉钉:在构建完成后通知信息(新增⭐)
    下载安装钉钉,并且注册账号(电脑版和手机版都行)⭐

    钉钉下载官网

    在Jenkins中下载钉钉插件(DingTalk 2.4.7版本)⭐

    在这里插入图片描述

    在钉钉创建一个企业(不然无法申请项目群)⭐

    在这里插入图片描述在这里插入图片描述
    在这里插入图片描述在这里插入图片描述

    在钉钉创建一个新的项目群⭐

    在这里插入图片描述在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    在钉钉的项目群里创建一个机器人⭐

    在这里插入图片描述
    在这里插入图片描述在这里插入图片描述
    在这里插入图片描述在这里插入图片描述
    在这里插入图片描述在这里插入图片描述

    在这里插入图片描述

    在Jenkins中配置这个机器人⭐

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    Jenkinsfile配置钉钉⭐
    • 1:编写流水线语法:
      • 注意:robot的值就是我们在Jenkins的系统配置所设置的机器人id!!(一定要进行修改)
    post {
            success {
                dingtalk (
                    robot: 'Jenkins-dingding',
                    type:'MARKDOWN',
                    title: "success: ${JOB_NAME}",
                    text: ["- 成功构建:${JOB_NAME}项目!\n- 版本:${tag}\n- 持续时间:${currentBuild.durationString}\n- 任务:#${JOB_NAME}"]
                )
            }
            failure {
                dingtalk (
                    robot: 'Jenkins-dingding',
                    type:'MARKDOWN',
                    title: "fail: ${JOB_NAME}",
                    text: ["- 失败构建:${JOB_NAME}项目!\n- 版本:${tag}\n- 持续时间:${currentBuild.durationString}\n- 任务:#${JOB_NAME}"]
                )
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 2:将上面的语法放到Jenkinsfile的stages外面,并上传gitlab:

    在这里插入图片描述

    • 3:点击构建Jenkins

    在这里插入图片描述

    • 4:查看钉钉项目群:

    在这里插入图片描述

    实战4的Jenkinsfile全部代码⭐
    pipeline {
        agent any
    
        environment{
            harborAddress = '192.168.184.80:80'
            harborRepo = 'repo'
            harborUser = 'admin'
            harborPasswd = 'Harbor12345'
        }
        // 存放所有任务的集合
        stages {
            stage('拉取Git仓库代码') {
                steps {
                   checkout([$class: 'GitSCM', branches: [[name: '${tag}']], extensions: [], userRemoteConfigs: [[url: 'http://192.168.184.70:8929/root/mytest.git']]])
                }
            }
    
            stage('通过maven构建项目') {
                steps {
                    sh '/var/jenkins_home/maven/bin/mvn clean package -DskipTests'
                }
            }
    
            stage('通过SonarQube做代码质量检测') {
                steps {
                    sh '/var/jenkins_home/sonar-scanner/bin/sonar-scanner -Dsonar.sources=./ -Dsonar.projectname=${JOB_NAME} -Dsonar.projectKey=${JOB_NAME} -Dsonar.java.binaries=./target/ -Dsonar.login=7ad2200f7cca90c37a909fdba8db049ac700909f'
                }
            }
    
            stage('通过Docker制作自定义镜像') {
                steps {
                    sh '''mv ./target/*.jar ./docker/
                    docker build -t ${JOB_NAME}:${tag} ./docker/'''
                }
            }
    
            stage('将自定义镜像推送到Harbor仓库') {
                steps {
                    sh '''docker login -u ${harborUser} -p ${harborPasswd} ${harborAddress}
                    docker tag ${JOB_NAME}:${tag} ${harborAddress}/${harborRepo}/${JOB_NAME}:${tag}
                    docker push ${harborAddress}/${harborRepo}/${JOB_NAME}:${tag}'''
                }
            }
    
            stage('通过Publish Over SSH通知目标服务器') {
                steps {
                sshPublisher(publishers: [sshPublisherDesc(configName: 'mytest', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "deploy.sh $harborAddress $harborRepo $JOB_NAME $tag $host_port $container_port", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
                }
            }
        }
    
        post {
                success {
                    dingtalk (
                        robot: 'Jenkins-dingding',
                        type:'MARKDOWN',
                        title: "success: ${JOB_NAME}",
                        text: ["- 成功构建:${JOB_NAME}项目!\n- 版本:${tag}\n- 持续时间:${currentBuild.durationString}\n- 任务:#${JOB_NAME}"]
                    )
                }
                failure {
                    dingtalk (
                        robot: 'Jenkins-dingding',
                        type:'MARKDOWN',
                        title: "fail: ${JOB_NAME}",
                        text: ["- 失败构建:${JOB_NAME}项目!\n- 版本:${tag}\n- 持续时间:${currentBuild.durationString}\n- 任务:#${JOB_NAME}"]
                    )
                }
            }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
  • 相关阅读:
    【Linux】管道
    同行评议论文怎么写
    基于复合粒子群优化的模糊神经预测控制的研究(Matlab代码实现)
    【andriod】设备APP开发之数据就地Excel存储
    Python网络爬虫的实践与应用
    Exception in thread “AWT-EventQueue-0“ java.lang.NullPointerException
    Day09字符流&缓冲流&序列化流&IO框架
    Windows 和 Linux 系统下,如何查看 Redis 的版本号?
    Debian安装Docker环境
    网工实验手册:RSTP如何配置?
  • 原文地址:https://blog.csdn.net/weixin_50071998/article/details/126019630