持续集成CICD微服务架构和实践

Jenkins多分支流水线+Docker自动化部署SpringB

2020-01-03  本文已影响0人  阿B咬佢只鸡

Jenkins

官方安装地址
安装最新版,支持jenkins多分支流水线(Multibranch Pipeline Job )

目录


安装docker-ce

官方安装文档

  1. 卸载旧版本
    如果是新机器可以忽略这一步,因为centos还没自带docker服务。
yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine
  1. 安装依赖包
 yum install -y yum-utils device-mapper-persistent-data lvm2
  1. 添加Docker软件包源
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

但是鉴于国内网络问题,建议使用国内阿里的源

yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
  1. 执行安装操作
安装:
yum install -y docker-ce
设置docker服务开机自启动:
systemctl enable docker

安装、运行jenkins

docker run \
-u root \
-itd \
--name=jenkins \
--restart=always \
-e TZ='Asia/Shanghai' \
-p 8080:8080 ‐p 5000:5000 \
-v /data/jenkins/jenkins_home:/var/jenkins_home \
-v /data/jenkins/home:/home \
-v /var/run/docker.sock:/var/run/docker.sock \
jenkinsci/blueocean

参数解析:


登录jenkins

  1. 访问http://宿主机IP:8080访问Jenkins。如果无法访问请检查系统防火墙、云的安全组设置。
  2. 查看并填写初始密码
cat /data/jenkins/jenkins_home/secrets/initialAdminPassword
01.png
02.png
03.png
04.png

配置jenkins

容器内安装:jdk1.8maven-3
下载jdk,maven包(.tar),直接解压到/usr/local, 然后配置环境变量,再执行(docker exec jenkins soure /etc/profile)

maven & jdk.png
配置:
系统管理 ==> 全局工具配置
jdk,maven

编写Jenkinsfile,Dockerfile,start.sh

1. 什么是Jenkinsfile
流水线语法
Jenkinsfile 是 Jenkins 2.x 核心特性 Pipeline 的脚本,由Groovy语言实现。Jenkinsfile一般是放在项目根目录,随项目一起受源代码管理软件控制,无需像创建“自由风格"(Jenkins FreeStyle)项目一样,每次可能需要拷贝很多设置到新项目,提供了一些直接的好处:

Pipeline支持:Declarative(声明式)和Scripted Pipeline(脚本式)两种格式。两者都支持建立Pipeline,两者都可以用于在Web UI中定义一个流水线Jenkinsfile,将Jenkinsfile文件创建并检查到源代码控制库中通常被认为是最佳做法。

Declarative Pipeline (声明式格式一)
当然,还有别的格式样例

pipeline {
    agent any 
    stages {
        stage('Build') { 
            steps {
                // 
            }
        }
        stage('Test') { 
            steps {
                // 
            }
        }
        stage('Prod') { 
            steps {
                // 
            }
        }
    }
}

Scripted Pipeline(脚本式基本格式)

node {  
    stage('Build') { 
        // 
    }
    stage('Test') { 
        // 
    }
    stage('Prod') { 
        // 
    }
}

2. 编写声明式Jenkinsfile ; 使用文本编辑器(最好支持 Groovy 语法高亮显示)
工作原理:获取源代码 ==> maven打包 ==> 构建并推送镜像到Harbor ==>根据环境部署服务到服务器

pipeline {
    agent any
    environment {
        registryUrl= "192.168.1.110:5000"       #搭建docker私有仓库(Harbor)或者 用DockerHub
        registry_user= "xxx"
        registry_pass= "xxx"
        env=test       //"test" or "prod"        #选择打包及发布环境
    }
    options {
        timestamps()                    //设置在项目打印日志时带上对应时间
        disableConcurrentBuilds()       //不允许同时执行流水线,被用来防止同时访问共享资源等
        buildDiscarder(logRotator(numToKeepStr: '3'))   // 表示保留n次构建历史
    }

    //gitlab  webhook触发器
    //聚合项目,代码发生以下动作后,所有子项目将被触发构建,可选择使用
    //triggers{
    //   gitlab( triggerOnPush: true,                       //代码有push动作就会触发job
    //       triggerOnMergeRequest: true,                   //代码有merge动作就会触发job
    //        branchFilterType: "NameBasedFilter",          //只有符合条件的分支才会触发构建 “ALL/NameBasedFilter/RegexBasedFilter”
    //        includeBranchesSpec: "${JOB_BASE_NAME}")      //基于branchFilterType值,输入期望包括的分支的规则
    //}

    stages{
        stage('Print Message') {      //打印信息
            steps {
                echo "workspace: ${WORKSPACE}  build_id: ${BUILD_ID}  branch(gitlab分支名): ${env.BRANCH_NAME}"        
                echo "registryUrl: ${registryUrl}"
           }
        }
        //stage('Test') {         //测试
        //    steps {
        //        echo 'Testing..'
        //    }
        //}
        stage('Build project') {        //mvn打包
            steps {
                echo 'mvn打包'
                script {
                    try {
                        sh 'mvn clean package -pl ${JOB_NAME%%/*} -am -amd -P${env} -Dmaven.test.skip=true'     //springboot maven 多模块 jenkins 单独打包子项目
                    } catch (err) {
                        echo '打包失败 & End of Pipeline!!!'
                    }
                }
            }
        }
        stage('Build & Push Image') {      //构建,推送镜像
            steps {
                echo '构建,推送镜像'
                dir ('./') {       //指定工作目录(默认为${WORKSPACE})
                    script {
                        try {
                            sh 'mv ${JOB_NAME%%/*}/Dockerfile  ./'
                            sh 'docker login  --username=${registry_user} --password=${registry_pass}   ${registryUrl}'
                            def app = docker.build('${registryUrl}/${JOB_NAME%%/*}:${build_id}')
                            app.push('${build_id}')
                        } catch (err) {
                            echo '打包失败 & End of Pipeline!!!'
                        }
                    }
                }
                echo "delete local image"
                sh 'docker rmi ${registryUrl}/${JOB_NAME%%/*}:${build_id}'     //删除jenkins本地新建的镜像
            }
        }
        stage('Deploy for test') {
            when {
                beforeAgent true
                branch 'xxx'            //填写test环境gitlab分支名(我的分支名:release_eat_away)
            }
            steps {
                timeout(time: 40, unit: 'SECONDS') {    // 设置远程部署超过40秒,将终止该步骤
                echo '部署到开发环境'
                sh 'bash ./start.sh ${JOB_NAME%%/*} ${registryUrl}/${JOB_NAME%%/*}:${build_id} ${env}'    //位置变量1:工程名字  ; 位置变量2:镜像名字  ; 位置变量3:指定环境
            }            
        }
        stage('Deploy for prod') {          //部署到生产环境
            when {
                beforeAgent true
                branch 'xxx'       //填写prod环境gitlab分支名(我的分支名:release-3.0-prod)
            }
            steps {
                timeout(time: 40, unit: 'SECONDS') {    // 设置远程部署超过40秒,将终止该步骤
                echo '部署到生产环境'
                sh 'bash ./start.sh ${JOB_NAME%%/*} ${registryUrl}/${JOB_NAME%%/*}:${build_id} ${env}'     //位置变量1:工程名字  ; 位置变量2:镜像名字 ; 位置变量3:指定环境
            }
        }
        stage('Delete Workspace') {         //清理工作目录
            steps {
                echo "清理工作目录: ${WORKSPACE}"
                deleteDir()     //表示删除当前目录(${WORKSPACE})下内容,通常用在构建完毕之后清空工作空间
            }
        }
    }
}

3. 编写Dockerfile

FROM java:latest
MAINTAINER qiujt  qiujt123@163.com
WORKDIR /data/logs
ADD canfu-admin/target/canfu-admin-0.0.1-SNAPSHOT.jar     canfu-admin.jar
EXPOSE  8091
ENTRYPOINT    ["java","-jar","-Xms512m","-Xmx1024m","-XX:PermSize=512M","-XX:MaxPermSize=1024M","/canfu-admin.jar"]

4. 编写部署脚本(start.sh)

#/bin/bash
#ENV
 #docker私有仓库(Harbor)
  registryUrl=192.168.1.110:5000
  registry_user="xxx"
  registry_pass="xxx"
  project_name=$1
  image_name=$2
  env=$3
  node_user=root
if [ "${env}"  == test ];then
   #测试环境
  node1=192.168.1.105
elif [ "${env}" == prod ];then
  #生产环境
  node1=192.168.1.106
else
    echo '没有${env}环境!!!'
fi
  
#Prepare
echo "project_name: $1 , image_name: $2 , env:$3"

#Deploying
if [ $1 == canfu-eureka ];then
    ssh $node_user@node1 "docker login --username=${registry_user} --password=${registry_pass} ${registryUrl} && docker pull $image_name && docker stop $project_name | xargs docker rm && docker  run -itd  --name=$project_name  --restart=always -e TZ="Asia/Shanghai" -p 7002:7002 $image_name && docker image prune -a  -f --filter 'until=1h' "
else
    #可以像上面写成一个ssh"",为了解析方便,切分开(接下来为第一行,以此类推)
    ssh $node_user@$node1 "docker login --username=${registry_user} --password=${registry_pass} ${registryUrl} “
    ssh $node_user@$node1 “docker pull $image_name && docker stop $project_name | xargs docker rm ”
    ssh $node_user@$node1 ”docker run -itd --name=$project_name --restart=always --net=host -e TZ="Asia/Shanghai" -P -v /data/logs/$project_name:/data/logs/$project_name $image_name“
    ssh $node_user@$node1 “docker image prune -a -f --filter 'until=1h' ”
    ssh $node_user@$node1 ”tailf /data/logs/$project_name/${project_name}.log"
fi
$ docker exec -it jenkins /bin/bash
$ ssh-keygen -C "root@jenkins"

在远程节点的~/.ssh/authorized_keys中添加jenkins的公钥(id_rsa.pub)


创建多分支流水线项目

SpringBoot聚合项目与Jenkinsfile ,Dockerfile , start.sh位置关系;及子项目下创建各个环境文件(application-test.yml 和 application-prod.yml)

Springboot聚合项目
指定环境文件
创建jenkins流水线项目
配置流水线项目
点击 “立刻扫描 多分支流水线”,接下来Jenkins会在分支源中扫描每个分支下的Jenkinsfile,如果该分支下有Jenkinsfile,那么就会创建一个
分支Job
(下图扫描到release_eat_away 和 release-3.0-prod两个分支下有Jenkinsfile,所以jenkins创建了两个Job)
(这里需要注意的是,只有需要部署的分支,才加上Jenkinsfile,不然Jenkins会将其余分支也创建一个分支job。例如:下图的release-3.0-beta 和 release_pressuretest)
扫描多分支流水线
到此,多分支流水线项目配置完毕,可以点击触发构建项目了
多分枝流水线.png

上一篇下一篇

猜你喜欢

热点阅读