微服务持续集成之集群化批量部署

目录

  • 微服务部署方案优化
  • Jenkins+Docker+SpringCloud集群部署流程说明
  • 修改所有微服务配置
  • 注册中心配置
  • 其他微服务配置
  • 设置Jenkins 集群项目的构建参数
  • 安装Extended Choice Parameter插件,支持多选框
  • 创建流水线项目,添加参数
  • idea 里修改Jenkinsfile,配置 代码检查 的循环构建
  • 修改Jenkinsfile
  • 构建项目,测试代码检查
  • 修改Jenkinsfile,配置 循环打包编译制作镜像
  • 修改Jenkinsfile文件

微服务部署方案优化

单节点的部署方案存在以下问题:

  • 一次只能选择一个微服务部署
  • 只有一台生产者部署服务器
  • 每个微服务只有一个实例,容错率低



优化方案:

  • 在一个Jenkins工程中选择多个微服务同时发布
  • 在一个Jenkins工程中可以选择多台生产服务器同时部署
  • 每个微服务都是以集群高可用形式部署



Jenkins+Docker+SpringCloud集群部署流程说明

docker和eureka关系 docker eureka集群_git


修改所有微服务配置

注册中心配置

再去启动一台docker2服务器(安装部署docker环境),要配置镜像加速,并且能够登陆到harhor仓库。


idea里,修改eureka注册中心配置

docker和eureka关系 docker eureka集群_微服务_02

# 集群版
spring:
  application:
    name: EUREKA-HA


---
server:
  port: 10086
spring:
  # 指定profile=eureka-server1
  profiles: eureka-server1
eureka:
  instance:
    # 指定当profile=eureka-server1时,主机名是eureka-server1
    hostname: 192.168.23.12
  client:
    service-url:
      # 将自己注册到eureka-server1、eureka-server2这个Eureka上面去
      defaultZone: http://192.168.23.12:10086/eureka/,http://192.168.23.14:10086/eureka/

---
server:
  port: 10086
spring:
  profiles: eureka-server2
eureka:
  instance:
    hostname: 192.168.23.14
  client:
    service-url:
      defaultZone: http://192.168.23.12:10086/eureka/,http://192.168.23.14:10086/eureka/


其他微服务配置

除eureka注册中心以外,其他为服务器配置都需要加入所有Eureka服务

docker和eureka关系 docker eureka集群_docker_03

eureka:
  client:
    service-url:  
      defaultZone: http://192.168.23.14:10086/eureka,http://192.168.23.12:10086/eureka # Eureka访问地址
  instance:
    prefer-ip-address: true


将整个项目提交到gitlab

docker和eureka关系 docker eureka集群_git_04

docker和eureka关系 docker eureka集群_docker和eureka关系_05



设置Jenkins 集群项目的构建参数

安装Extended Choice Parameter插件,支持多选框

docker和eureka关系 docker eureka集群_git_06


创建流水线项目,添加参数

docker和eureka关系 docker eureka集群_git_07


参数化构建

docker和eureka关系 docker eureka集群_docker_08

docker和eureka关系 docker eureka集群_git_09


继续添加参数,选择 Extended Choice Parameter

docker和eureka关系 docker eureka集群_docker_10

name为project_name ,输入描述信息后,点击Basic Parameter Types 基础参数类型

docker和eureka关系 docker eureka集群_git_11

docker和eureka关系 docker eureka集群_git_12


选择 Choose Source for Value ... ,输入值

docker和eureka关系 docker eureka集群_docker_13


配置value,格式是 项目名@端口,项目名@端口........ 注意,中间的逗号为英文逗号

docker和eureka关系 docker eureka集群_git_14

tensquare_eureka_server@10086,tensquare_zuul@10020,tensquare_admin_service@9001,tensquare_gathering@9002


配置默认值

!

docker和eureka关系 docker eureka集群_docker和eureka关系_15

docker和eureka关系 docker eureka集群_git_16


配置描述信息。描述信息和值对应,并且,中间的逗号也是英文

docker和eureka关系 docker eureka集群_docker_17

docker和eureka关系 docker eureka集群_docker和eureka关系_18


docker和eureka关系 docker eureka集群_docker_19

docker和eureka关系 docker eureka集群_微服务_20

docker和eureka关系 docker eureka集群_微服务_21


保存后,构建项目时,界面如下

docker和eureka关系 docker eureka集群_docker_22



idea 里修改Jenkinsfile,配置 代码检查 的循环构建

修改Jenkinsfile

docker和eureka关系 docker eureka集群_docker_23

docker和eureka关系 docker eureka集群_docker_24

def git_auth="f3268a97-e838-4da4-ba6a-5a4ef6f12c4b"
def git_url="git@192.168.23.10:my_group/tensquare_back.git"

//定义标签
def tag="latest"
//定义仓库地址
def harbor_url="192.168.23.13:85"
//定义仓库名称
def harbor_name="tensquare"
//harbor凭证
def harbor_auth="a5daf047-4518-4481-bfe6-78940f1b4b95"

node {
   //获取当前选择项目名称,将project_name的值,按照逗号分隔。获取到的应该是 项目名@端口
    def selectedProjectNames="${project_name}".split(",")


    stage('pull code') {
       checkout([$class: 'GitSCM', branches: [[name: "${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]]])
    }
     stage('check code') {

                 // 使用for 循环遍历,获取的值依次是 项目1@项目1端口 ,项目2@项目2端口..........
                 for(int i=0;i<selectedProjectNames.length;i++){
                     //项目信息  tensquare_eureka_server@10086
                     def projectInfo=selectedProjectNames[i]

                     //当前的项目名称,将projectInfo的值,按照@符号进行分隔,获取第一项,即时项目名
                     def currentProjectName="${projectInfo}".split("@")[0]

                     //当前的项目端口
                     def currentProjectPort="${projectInfo}".split("@")[1]


                //定义SonarQubeScanner工具
                def scannerHome = tool 'sonar-scanner'
                //引用SonarQube系统环境
                withSonarQubeEnv('sonarqube') {
                sh """
                    cd ${currentProjectName}
                    ${scannerHome}/bin/sonar-scanner
                   """
                   }
            }

      }
      stage('make install public sub project') {
               sh "mvn -f tensquare_common clean install"
          }
      //打包微服务项目,制作镜像
      stage('make package') {
              sh  "mvn -f ${project_name} clean package dockerfile:build"
              //镜像打标签
              def imageName="${project_name}:${tag}"
              sh "docker tag ${imageName} ${harbor_url}/${harbor_name}/${imageName}"
              //镜像推送到harbor
             withCredentials([usernamePassword(credentialsId: "${harbor_auth}", passwordVariable: 'password', usernameVariable: 'username')]) {
                 //登录harbor
                 sh "docker login -u ${username} -p ${password} ${harbor_url}"
                 //上传镜像
                 sh "docker push ${harbor_url}/${harbor_name}/${imageName}"
                 sh "echo 镜像上传成功"
             }
       sshPublisher(publishers: [sshPublisherDesc(configName: 'master_server', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "/opt/jenkins_shell/deploy.sh ${harbor_url} ${harbor_name} ${project_name} ${tag} ${port}", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
      }
}


docker和eureka关系 docker eureka集群_微服务_25

构建项目,测试代码检查

选择4个项目,然后进行构建(最后后报错),进入到项目的终端输出,查看

docker和eureka关系 docker eureka集群_微服务_26

docker和eureka关系 docker eureka集群_微服务_27

docker和eureka关系 docker eureka集群_git_28

docker和eureka关系 docker eureka集群_微服务_29

docker和eureka关系 docker eureka集群_微服务_30


修改Jenkinsfile,配置 循环打包编译制作镜像

修改Jenkinsfile文件

docker和eureka关系 docker eureka集群_docker_31

def git_auth="f3268a97-e838-4da4-ba6a-5a4ef6f12c4b"
def git_url="git@192.168.23.10:my_group/tensquare_back.git"

//定义标签
def tag="latest"
//定义仓库地址
def harbor_url="192.168.23.13:85"
//定义仓库名称
def harbor_name="tensquare"
//harbor凭证
def harbor_auth="a5daf047-4518-4481-bfe6-78940f1b4b95"

node {
   //获取当前选择项目名称,将project_name的值,按照逗号分隔。获取到的应该是 项目名@端口
    def selectedProjectNames="${project_name}".split(",")


    stage('pull code') {
       checkout([$class: 'GitSCM', branches: [[name: "${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]]])
    }
     stage('check code') {

                 // 使用for 循环遍历,获取的值依次是 项目1@项目1端口 ,项目2@项目2端口..........
                 for(int i=0;i<selectedProjectNames.length;i++){
                     //项目信息  tensquare_eureka_server@10086
                     def projectInfo=selectedProjectNames[i]

                     //当前的项目名称,将projectInfo的值,按照@符号进行分隔,获取第一项,即时项目名
                     def currentProjectName="${projectInfo}".split("@")[0]

                     //当前的项目端口
                     def currentProjectPort="${projectInfo}".split("@")[1]


                //定义SonarQubeScanner工具
                def scannerHome = tool 'sonar-scanner'
                //引用SonarQube系统环境
                withSonarQubeEnv('sonarqube') {
                sh """
                    cd ${currentProjectName}
                    ${scannerHome}/bin/sonar-scanner
                   """
                   }
            }

      }
      stage('make install public sub project') {
               sh "mvn -f tensquare_common clean install"
          }


      //打包微服务项目,制作镜像
      stage('make package') {

        for(int i=0;i<selectedProjectNames.length;i++){
            //项目信息  tensquare_eureka_server@10086
            def projectInfo=selectedProjectNames[i]

            //当前的项目名称
            def currentProjectName="${projectInfo}".split("@")[0]

            //当前的项目端口
            def currentProjectPort="${projectInfo}".split("@")[1]


              sh  "mvn -f ${currentProjectName} clean package dockerfile:build"
              //镜像打标签
              def imageName="${currentProjectName}:${tag}"
              sh "docker tag ${imageName} ${harbor_url}/${harbor_name}/${imageName}"
              //镜像推送到harbor
             withCredentials([usernamePassword(credentialsId: "${harbor_auth}", passwordVariable: 'password', usernameVariable: 'username')]) {
                 //登录harbor
                 sh "docker login -u ${username} -p ${password} ${harbor_url}"
                 //上传镜像
                 sh "docker push ${harbor_url}/${harbor_name}/${imageName}"
                 sh "echo 镜像上传成功"
             }
         
        //部署应用
       sshPublisher(publishers: [sshPublisherDesc(configName: 'master_server', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "/opt/jenkins_shell/deploy.sh ${harbor_url} ${harbor_name} ${project_name} ${tag} ${port}", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
      }
   }
}


docker和eureka关系 docker eureka集群_docker_32

docker和eureka关系 docker eureka集群_微服务_33

docker和eureka关系 docker eureka集群_git_34

docker和eureka关系 docker eureka集群_docker和eureka关系_35


docker和eureka关系 docker eureka集群_docker和eureka关系_36


docker和eureka关系 docker eureka集群_docker_37


docker和eureka关系 docker eureka集群_docker_38


docker和eureka关系 docker eureka集群_docker和eureka关系_39

循环打包,编译,制作镜像,上传镜像,测试成功