一 集成Harbor

1.1 Harbor介绍

前面在部署项目时,我们主要采用Jenkins推送jar包到指定服务器,再通过脚本命令让目标服务器对当前jar进行部署,这种方式在项目较多时,每个目标服务器都需要将jar包制作成自定义镜像再通过docker进行启动,重复操作比较多,会降低项目部署时间。

我们可以通过Harbor作为私有的Docker镜像仓库。让Jenkins统一将项目打包并制作成Docker镜像发布到Harbor仓库中,只需要通知目标服务,让目标服务统一去Harbor仓库上拉取镜像并在本地部署即可。

Docker官方提供了Registry镜像仓库,但是Registry的功能相对简陋。Harbor是VMware公司提供的一款镜像仓库,提供了权限控制、分布式发布、强大的安全扫描与审查机制等功能

1.2 Harbor安装

这里采用原生的方式安装Harbor。

  • 下载Harbor安装包:https://github.com/goharbor/harbor/releases/download/v2.3.4/harbor-offline-installer-v2.3.4.tgz

  • 拖拽到Linux并解压:

    tar -zxvf harbor-offline-installer-v2.3.4.tgz -C /usr/local/
    
  • 修改Harbor配置文件:

    • 首先复制一份harbor.yml配置

      cp harbor.yml.tmpl harbor.yml
      
    • 编辑harbor.yml配置文件

      配置Harbor文件
      在这里插入图片描述
  • 启动Harbor

    ./install.sh
    
    查看日志
    在这里插入图片描述
  • 登录Harbor

    登录Harbor
    在这里插入图片描述
  • 首页信息

    首页信息
    在这里插入图片描述

1.3 Harbor使用方式

Harbor作为镜像仓库,主要的交互方式就是将镜像上传到Harbor上,以及从Harbor上下载指定镜像

在传输镜像前,可以先使用Harbor提供的权限管理,将项目设置为私有项目,并对不同用户设置不同角色,从而更方便管理镜像。

1.3.1 添加用户构建项目

  • 创建用户

    创建用户
    在这里插入图片描述

|

  • 构建项目(设置为私有)

    构建项目
    在这里插入图片描述
  • 给项目追加用户

    追加用户管理
    在这里插入图片描述
  • 切换测试用户

    切换测试用户
    在这里插入图片描述

1.3.2 发布镜像到Harbor

  • 修改镜像名称

    名称要求:[harbor地址/项目名/镜像名:版本]

    修改镜像名称
    在这里插入图片描述
  • 修改daemon.json,支持Docker仓库,并重启Docker

    修改daemon.json,支持Docker仓库
    在这里插入图片描述
  • 设置登录仓库信息

    docker login -u 用户名 -p 密码 Harbor地址
    
  • 推送镜像到Harbor

    推送镜像到Harbor
    在这里插入图片描述
    在这里插入图片描述

1.3.3 从Harbor拉取镜像ls

跟传统方式一样,不过需要先配置/etc/docker/daemon.json文件

{
        "registry-mirrors": ["https://pee6w651.mirror.aliyuncs.com"],
        "insecure-registries": ["192.168.11.11:80"]
}
拉取镜像
在这里插入图片描述

1.3.4 Jenkins容器使用宿主机Docker

构建镜像和发布镜像到harbor都需要使用到docker命令。而在Jenkins容器内部安装Docker官方推荐直接采用宿主机带的Docker即可。

设置Jenkins容器使用宿主机Docker

  • 设置宿主机docker.sock权限:

    sudo chown root:root /var/run/docker.sock
    sudo chmod o+rw /var/run/docker.sock
    
  • 添加数据卷

    version: "3.1"
    services:
      jenkins:
        image: jenkins/jenkins
        container_name: jenkins
        ports:
          - 8080:8080
          - 50000:50000
        volumes:
          - ./data/:/var/jenkins_home/
          - /usr/bin/docker:/usr/bin/docker
          - /var/run/docker.sock:/var/run/docker.sock
          - /etc/docker/daemon.json:/etc/docker/daemon.json
    

1.3.5 添加构建操作

制作自定义镜像
在这里插入图片描述

1.3.6 编写部署脚本

部署项目需要通过Publish Over SSH插件,让目标服务器执行命令。为了方便一次性实现拉取镜像和启动的命令,推荐采用脚本文件的方式。

添加脚本文件到目标服务器,再通过Publish Over SSH插件让目标服务器执行脚本即可。

  • 编写脚本文件,添加到目标服务器

    harbor_url=$1
    harbor_project_name=$2
    project_name=$3
    tag=$4
    port=$5
    
    imageName=$harbor_url/$harbor_project_name/$project_name:$tag
    
    containerId=`docker ps -a | grep ${project_name} | awk '{print $1}'`
    if [ "$containerId" != "" ] ; then
        docker stop $containerId
        docker rm $containerId
        echo "Delete Container Success"
    fi
    
    imageId=`docker images | grep ${project_name} | awk '{print $3}'`
    
    if [ "$imageId" != "" ] ; then
        docker rmi -f $imageId
        echo "Delete Image Success"
    fi
    
    docker login -u DevOps -p P@ssw0rd $harbor_url
    
    docker pull $imageName
    
    docker run -d -p $port:$port --name $project_name $imageName
    
    echo "Start Container Success"
    echo $project_name
    

    并设置权限为可执行

    chmod a+x deploy.sh
    
    如图
    在这里插入图片描述

1.3.7 配置构建后操作

执行脚本文件
在这里插入图片描述

二 Jenkins流水线

2.1 Jenkins流水线任务介绍

之前采用Jenkins的自由风格构建的项目,每个步骤流程都要通过不同的方式设置,并且构建过程中整体流程是不可见的,无法确认每个流程花费的时间,并且问题不方便定位问题。

Jenkins的Pipeline可以让项目的发布整体流程可视化,明确执行的阶段,可以快速的定位问题。并且整个项目的生命周期可以通过一个Jenkinsfile文件管理,而且Jenkinsfile文件是可以放在项目中维护。

所以Pipeline相对自由风格或者其他的项目风格更容易操作。

2.2 Jenkins流水线任务

2.2.1 构建Jenkins流水线任务

  • 构建任务

    构建Jenkins流水线任务
    在这里插入图片描述
  • 生成Groovy脚本

    Hello World脚本生成
    在这里插入图片描述
  • 构建后查看视图

    构建后查看视图
    在这里插入图片描述

2.2.2 Groovy脚本

  • Groovy脚本基础语法

    // 所有脚本命令包含在pipeline{}中
    pipeline {  
    	// 指定任务在哪个节点执行(Jenkins支持分布式)
        agent any
        
        // 配置全局环境,指定变量名=变量值信息
        environment{
        	host = '192.168.11.11'
        }
    
        // 存放所有任务的合集
        stages {
        	// 单个任务
            stage('任务1') {
            	// 实现任务的具体流程
                steps {
                    echo 'do something'
                }
            }
    		// 单个任务
            stage('任务2') {
            	// 实现任务的具体流程
                steps {
                    echo 'do something'
                }
            }
            // ……
        }
    }
    
  • 编写例子测试

    pipeline {
        agent any
    
        // 存放所有任务的合集
        stages {
            stage('拉取Git代码') {
                steps {
                    echo '拉取Git代码'
                }
            }
    
            stage('检测代码质量') {
                steps {
                    echo '检测代码质量'
                }
            }
    
            stage('构建代码') {
                steps {
                    echo '构建代码'
                }
            }
    
            stage('制作自定义镜像并发布Harbor') {
                steps {
                    echo '制作自定义镜像并发布Harbor'
                }
            }
    
            stage('基于Harbor部署工程') {
                steps {
                    echo '基于Harbor部署工程'
                }
            }
        }
    }
    
    配置Grovvy脚本
    在这里插入图片描述
  • 查看效果

    查看效果
    在这里插入图片描述

|

Ps:涉及到特定脚本,Jenkins给予了充足的提示,可以自动生成命令

生成命令位置
在这里插入图片描述

2.2.3 Jenkinsfile实现

Jenkinsfile方式需要将脚本内容编写到项目中的Jenkinsfile文件中,每次构建会自动拉取项目并且获取项目中Jenkinsfile文件对项目进行构建

  • 配置pipeline

    配置pipeline
    在这里插入图片描述

|

  • 准备Jenkinsfile

    准备Jenkinsfile文件
    在这里插入图片描述

|

  • 测试效果

    测试效果
    在这里插入图片描述

2.3 Jenkins流水线任务实现

2.3.1 参数化构建

添加参数化构建,方便选择不的项目版本

Git参数化构建
在这里插入图片描述

2.3.2 拉取Git代码

通过流水线语法生成Checkout代码的脚本

语法生成
在这里插入图片描述
在这里插入图片描述

将*/master更改为标签${tag}

pipeline {
    agent any
    stages {

        stage('拉取Git代码') {
            steps {
                checkout([$class: 'GitSCM', branches: [[name: '${tag}']], extensions: [], userRemoteConfigs: [[url: 'http://49.233.115.171:8929/root/test.git']]])
            }
        }
    }
}

2.3.3 构建代码

通过脚本执行mvn的构建命令

pipeline {
    agent any

    stages {

        stage('拉取Git代码') {
            steps {
                checkout([$class: 'GitSCM', branches: [[name: '${tag}']], extensions: [], userRemoteConfigs: [[url: 'http://49.233.115.171:8929/root/test.git']]])
            }
        }

        stage('构建代码') {
            steps {
                sh '/var/jenkins_home/maven/bin/mvn clean package -DskipTests'
            }
        }
}

2.3.4 代码质量检测

通过脚本执行sonar-scanner命令即可

pipeline {
    agent any

    stages {

        stage('拉取Git代码') {
            steps {
                checkout([$class: 'GitSCM', branches: [[name: '${tag}']], extensions: [], userRemoteConfigs: [[url: 'http://49.233.115.171:8929/root/test.git']]])
            }
        }

        stage('构建代码') {
            steps {
                sh '/var/jenkins_home/maven/bin/mvn clean package -DskipTests'
            }
        }

        stage('检测代码质量') {
            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=31388be45653876c1f51ec02f0d478e2d9d0e1fa' 
            }
        }
    }
}

2.3.5 制作自定义镜像并发布

  • 生成自定义镜像脚本

    pipeline {
        agent any
        environment{
            harborHost = '192.168.11.11:80'
            harborRepo = 'repository'
            harborUser = 'DevOps'
            harborPasswd = 'P@ssw0rd'
        }
    
        // 存放所有任务的合集
        stages {
    
            stage('拉取Git代码') {
                steps {
                    checkout([$class: 'GitSCM', branches: [[name: '${tag}']], extensions: [], userRemoteConfigs: [[url: 'http://49.233.115.171:8929/root/test.git']]])
                }
            }
    
            stage('构建代码') {
                steps {
                    sh '/var/jenkins_home/maven/bin/mvn clean package -DskipTests'
                }
            }
    
            stage('检测代码质量') {
                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=31388be45653876c1f51ec02f0d478e2d9d0e1fa' 
                }
            }
    
            stage('制作自定义镜像并发布Harbor') {
                steps {
                    sh '''cp ./target/*.jar ./docker/
                    cd ./docker
                    docker build -t ${JOB_NAME}:${tag} ./'''
    
                    sh '''docker login -u ${harborUser} -p ${harborPasswd} ${harborHost}
                    docker tag ${JOB_NAME}:${tag} ${harborHost}/${harborRepo}/${JOB_NAME}:${tag}
                    docker push ${harborHost}/${harborRepo}/${JOB_NAME}:${tag}'''
                }
            }
        }
    }
    
  • 生成Publish Over SSH脚本

    pipeline {
        agent any
        environment{
            harborHost = '192.168.11.11:80'
            harborRepo = 'repository'
            harborUser = 'DevOps'
            harborPasswd = 'P@ssw0rd'
        }
    
        // 存放所有任务的合集
        stages {
    
            stage('拉取Git代码') {
                steps {
                    checkout([$class: 'GitSCM', branches: [[name: '${tag}']], extensions: [], userRemoteConfigs: [[url: 'http://49.233.115.171:8929/root/test.git']]])
                }
            }
    
            stage('构建代码') {
                steps {
                    sh '/var/jenkins_home/maven/bin/mvn clean package -DskipTests'
                }
            }docker
    
            stage('检测代码质量') {
                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=7d66af4b39cfe4f52ac0a915d4c9d5c513207098' 
                }
            }
    
            stage('制作自定义镜像并发布Harbor') {
                steps {
                    sh '''cp ./target/*.jar ./docker/
                    cd ./docker
                    docker build -t ${JOB_NAME}:${tag} ./'''
    
                    sh '''docker login -u ${harborUser} -p ${harborPasswd} ${harborHost}
                    docker tag ${JOB_NAME}:${tag} ${harborHost}/${harborRepo}/${JOB_NAME}:${tag}
                    docker push ${harborHost}/${harborRepo}/${JOB_NAME}:${tag}'''
                }
            }
            
            stage('目标服务器拉取镜像并运行') {
                steps {
                    sshPublisher(publishers: [sshPublisherDesc(configName: 'testEnvironment', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "/usr/bin/deploy.sh $harborHost $harborRepo $JOB_NAME $tag $port ", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
                }
            }
        }
    }
    

Ps:由于采用变量,记得使用双引号

2.4 Jenkins流水线整合钉钉

在程序部署成功后,可以通过钉钉的机器人及时向群众发送部署的最终结果通知

  • 安装插件

    安装插件
    在这里插入图片描述

|

  • 钉钉内部创建群组并构建机器人

    钉钉内部创建群组并构建机器人
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述

最终或获取到Webhook信息

https://oapi.dingtalk.com/robot/send?access_token=kej4ehkj34gjhg34jh5bh5jb34hj53b4
  • 系统配置添加钉钉通知

    配置钉钉通知
    在这里插入图片描述

|

  • 任务中追加流水线配置

    pipeline {
        agent any
    
        environment {
            sonarLogin = '2bab7bf7d5af25e2c2ca2f178af2c3c55c64d5d8'
            harborUser = 'admin'
            harborPassword = 'Harbor12345'
            harborHost = '192.168.11.12:8888'
            harborRepo = 'repository'
        }
    
        stages {
            stage('拉取Git代码'){
                steps {
                    checkout([$class: 'GitSCM', branches: [[name: '$tag']], extensions: [], userRemoteConfigs: [[url: 'http://49.233.115.171:8929/root/lsx.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=${sonarLogin}'
                }
            }
            stage('制作自定义镜像'){
                steps {
                    sh '''cd docker
                    mv ../target/*.jar ./
                    docker build -t ${JOB_NAME}:$tag .
                    '''
                }
            }
    
            stage('推送自定义镜像'){
                steps {
                    sh '''docker login -u ${harborUser} -p ${harborPassword} ${harborHost}
                    docker tag ${JOB_NAME}:$tag ${harborHost}/${harborRepo}/${JOB_NAME}:$tag
                    docker push ${harborHost}/${harborRepo}/${JOB_NAME}:$tag'''
                }
            }
    
            stage('通知目标服务器'){
                steps {
                    sshPublisher(publishers: [sshPublisherDesc(configName: 'centos-docker', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "/usr/bin/deploy.sh $harborHost $harborRepo $JOB_NAME $tag $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}"]
                )
            }
        }
    }
    
  • 查看效果

    钉钉通知效果
    在这里插入图片描述
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐