微服务持续集成之集群化批量部署
目录
- 微服务部署方案优化
- Jenkins+Docker+SpringCloud集群部署流程说明
- 修改所有微服务配置
- 注册中心配置
- 其他微服务配置
- 设置Jenkins 集群项目的构建参数
- 安装Extended Choice Parameter插件,支持多选框
- 创建流水线项目,添加参数
- idea 里修改Jenkinsfile,配置 代码检查 的循环构建
- 修改Jenkinsfile
- 构建项目,测试代码检查
- 修改Jenkinsfile,配置 循环打包编译制作镜像
- 修改Jenkinsfile文件
微服务部署方案优化
单节点的部署方案存在以下问题:
- 一次只能选择一个微服务部署
- 只有一台生产者部署服务器
- 每个微服务只有一个实例,容错率低
优化方案:
- 在一个Jenkins工程中选择多个微服务同时发布
- 在一个Jenkins工程中可以选择多台生产服务器同时部署
- 每个微服务都是以集群高可用形式部署
Jenkins+Docker+SpringCloud集群部署流程说明
修改所有微服务配置
注册中心配置
再去启动一台docker2服务器(安装部署docker环境),要配置镜像加速,并且能够登陆到harhor仓库。
idea里,修改eureka注册中心配置
# 集群版
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服务
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
设置Jenkins 集群项目的构建参数
安装Extended Choice Parameter插件,支持多选框
创建流水线项目,添加参数
参数化构建
继续添加参数,选择 Extended Choice Parameter
name为project_name ,输入描述信息后,点击Basic Parameter Types 基础参数类型
选择 Choose Source for Value ... ,输入值
配置value,格式是 项目名@端口,项目名@端口........ 注意,中间的逗号为英文逗号
tensquare_eureka_server@10086,tensquare_zuul@10020,tensquare_admin_service@9001,tensquare_gathering@9002
配置默认值
!
配置描述信息。描述信息和值对应,并且,中间的逗号也是英文
保存后,构建项目时,界面如下
idea 里修改Jenkinsfile,配置 代码检查 的循环构建
修改Jenkinsfile
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)])
}
}
构建项目,测试代码检查
选择4个项目,然后进行构建(最后后报错),进入到项目的终端输出,查看
修改Jenkinsfile,配置 循环打包编译制作镜像
修改Jenkinsfile文件
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)])
}
}
}
循环打包,编译,制作镜像,上传镜像,测试成功