Jenkins + Docker + SpringCloud 微服务持续集成 - 高可用集群部署(三)
Jenkins + Docker + SpringCloud 高可用集群部署方案微服务持续集成(一):https://blog.csdn.net/shm19990131/article/details/107552335一、单机部署方案存在问题一次只能选择一个微服务部署只有一台生产者 docker 部署服务器每个微服务只有一个实例,容错率低二、高可用集群优化方案在一个 Jenkins 工程中可以选
Jenkins + Docker + SpringCloud 高可用集群部署方案
微服务持续集成(一):https://blog.csdn.net/shm19990131/article/details/107552335
一、单机部署方案存在问题
- 一次只能选择一个微服务部署
- 只有一台生产者 docker 部署服务器
- 每个微服务只有一个实例,容错率低
二、高可用集群优化方案
- 在一个 Jenkins 工程中可以选择多个微服务同时发布。
- 在一个 Jenkins 工程中可以选择多台生产服务器同时部署
- 每个微服务都是以集群高可用形式部署
三、Jenkins + Docker + SpringCloud 集群部署流程说明
部署步骤
一、修改所有微服务配置,让其可以形成一个集群
可以根据自己的需求去修改,这里只是将 eureka变成主从,其余微服务读取eureka配置
1、修改 erueka 的 配置文件application.yml
1 spring:
2 application:
3 name: EUREKA-HA
4
5 ---
6 server:
7 port: 8000
8 spring:
9 profiles: eureka-server1
10 eureka:
11 instance:
12 hostname: 192.168.168.14
13 client:
14 server-url:
15 defaultZone: http://192.168.168.14:8000/eureka/,http://192.168.168.15:8000/eureka/
16
17 ---
18 server:
19 port: 8000
20 spring:
21 profiles: eureka-server2
22 eureka:
23 instance:
24 hostname: 192.168.168.15
25 client:
26 server-url:
27 defaultZone: http://192.168.168.14:8000/eureka/,http://192.168.168.15:8000/eureka/
在启动微服务的时候,加入参数:spring.profiles.active 来读取对应的配置。
2、其他微服务配置
其他所有子项目的配置文件,都需要指定两个 Eureka注册中心的 ip:port/eureka
eureka:
client:
server-url:
defaultZone: http://192.168.168.14:8000/eureka/,http://192.168.168.15:8000/eureka/
二、高可用集群部署 - pipeline 流水线参数设置
1、创建一个 Pipeline SCM 的流水线
2、安装集群必须的多选插件
Extended Choice Paranter
3、利用多选插件,设置 Pipeline 项目参数
分支参数:string Parameter
多选参数:Extended Choice Parameter
Number of Visible ltems :有几个微服务需要部署就填几。
注意,这里的逗号有讲究,不能是中文逗号,必须是英文无间隔的逗号。
效果:
以上是设置微服务集群部署的必要参数,这些参数都是将来用在 Jenkinsfile 脚本当中的,非常重要。
三、修改 Jenkinsfile ,实现高可用集群部署
修改 Jenkinsfile ,实现高可用集群部署
1、定义代码审查功能
node {
//获取当前复选的项目名称
def project_Names = "${project_name}".split(",")
stage('拉取代码') {
checkout([$class: 'GitSCM', branches: [[name: '*/${branch}']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]]])
}
stage('代码审查') {
//循环获取项目名称,并生成数组
for(int i=0; i<projectNames.length;i++){
//获取每个微服务的名字:microservice-base-eureka:8000
def projectInfo = projectNames[i];
//切割出微服务名:microservice-base-eureka
def projectName = "${projectInfo}".split("@")[0]
//切割出port:8000
def projectPort = "${projectInfo}".split("@")[1]
//定义当前jenkins的 sonarQubeScanner 工具
def scannerHome = tool 'sonar-Scanner'
//引用当前 JenkinsSonarQube
withSonarQubeEnv('sonarqube') {
sh """
cd ${project_Name}
${scannerHome}/bin/sonar-scanner
"""
}
}
}
1-2、修改 sonar-project.properties
### 注意大小写
sonar.projectKey=cluster_eureka_server
sonar.projectName=cluster_eureka_server
sonar.projectVersion=1.0
#扫描路径 “.”代表全部内容
sonar.sources=.
#排除扫描路径
sonar.exclusions=**/test/**,**/target/**
sonar.java.binaries=.
sonar.java.source=1.8
sonar.java.target=1.8
sonar.sourceEncoding=UTF-8
2、构建镜像
父工程不变,改动的是父工程下的子工程。
stage('编译,安装父工程') {
sh "/usr/local/maven/bin/mvn -f microservice-base-common install"
sh "/usr/local/maven/bin/mvn -f microservice-base-common clean package"
}
子工程Jenkinsfile文件如下:
stage('编译,安装公共子工程,制作镜像') {
//循环遍历 微服务名,并生成数组
for(int i=0; i<projectNames.length;i++){
//获取每个微服务的名字:microservice-base-eureka:8000
def projectInfo = projectNames[i];
//切割出微服务名:microservice-base-eureka
def projectName = "${projectInfo}".split("@")[0]
//切割出port:8000
def projectPort = "${projectInfo}".split("@")[1]
sh "/usr/local/maven/bin/mvn -f ${projectName} clean package dockerfile:build"
}
}
3、上传镜像至 Harbor 仓库
stage('镜像上传至Harbor仓库') {
for(int i=0; i<projectNames.length;i++){
//获取每个微服务的名字:microservice-base-eureka:8000
def projectInfo = projectNames[i];
//切割出微服务名:microservice-base-eureka
def projectName = "${projectInfo}".split("@")[0]
//切割出port:8000
def projectPort = "${projectInfo}".split("@")[1]
//定义镜像名字
def imageName = "${projectName}:${tag}"
//为镜像打标签
sh "docker tag ${imageName} ${harbor_url}/${harbor_project}/${imageName}"
//凭据登录Harbor
withCredentials([usernamePassword(credentialsId:"${harbor_auth}", passwordVariable: 'password', usernameVariable: 'username')]) {
//引用用户名密码登录
sh "docker login -u ${username} -p ${password} ${harbor_url}"
//镜像上传
sh "docker push ${harbor_url}/${harbor_project}/${imageName} && echo 镜像上传成功"
//登出 Harbor
sh "docker logout ${harbor_url}"
}
}
}
>
四、多台docker生产服务器部署 eureka 集群
需求:两台 docker 服务器 同时部署 eureka 微服务
eureka配置文件
1 spring:
2 application:
3 name: EUREKA-HA
4
5 ---
6 server:
7 port: 8000
8 spring:
9 profiles: eureka-server1
10 eureka:
11 instance:
12 hostname: 192.168.168.14
13 client:
14 server-url:
15 defaultZone: http://192.168.168.14:8000/eureka/,http://192.168.168.15:8000/eureka/
16
17 ---
18 server:
19 port: 8000
20 spring:
21 profiles: eureka-server2
22 eureka:
23 instance:
24 hostname: 192.168.168.15
25 client:
26 server-url:
27 defaultZone: http://192.168.168.14:8000/eureka/,http://192.168.168.15:8000/eureka/
br
1、传递公钥至所有的 dokcer 生产服务器
docker 生产服务器必须能从 Harbor上拉取镜像。
[root@jenkins ~]# ssh-copy-id 192.168.168.15
[root@jenkins ~]# ssh-copy-id 192.168.168.14
2、在 Jenkins 设置里配置 SSH密钥认证
3、Jenkins - pipeline 设置多选参数,多选生产服务器
4、修改 Jenkinsfile 文件,设置多选生产服务器
//设置 gitlab 拉取凭证ID号的变量
def git_auth = "218fb747-c605-4fa0-80d3-c322cd42d7a9"
//设置 gitlab 拉取代码 URL 地址的变量
def git_url = "git@192.168.168.12:itheima_group/tensquare_front.git"
//镜像版本号
def tag = "latest"
//Harbor仓库的IP地址
def harbor_url = "192.168.168.14"
//Harbor凭证
def harbor_auth = "584bf0a9-d247-4c4f-9e29-b9291381dd45"
//Harbor仓库
def harbor_project = "tensquare"
node {
//获取当前选择的项目名称
def projectNames = "${project_name}".split(",")
//获取当前选择的服务器名称
def Servers = "${publish_server}".split(",")
......省略之前的步骤
stage('镜像上传至Harbor仓库,并完成部署') {
for(int i=0; i<projectNames.length;i++){
//获取每个微服务的名字:microservice-base-eureka:8000
def projectInfo = projectNames[i];
//切割出微服务名:microservice-base-eureka
def projectName = "${projectInfo}".split("@")[0]
//切割出port:8000
def projectPort = "${projectInfo}".split("@")[1]
//定义镜像名字
def imageName = "${projectName}:${tag}"
//为镜像打标签
sh "docker tag ${imageName} ${harbor_url}/${harbor_project}/${imageName}"
//凭据登录Harbor
withCredentials([usernamePassword(credentialsId:"${harbor_auth}", passwordVariable: 'password', usernameVariable: 'username')]) {
//引用用户名密码登录
sh "docker login -u ${username} -p ${password} ${harbor_url}"
//镜像上传
sh "docker push ${harbor_url}/${harbor_project}/${imageName} && echo 镜像上传成功"
//登出 Harbor
sh "docker logout ${harbor_url}"
}
//设置多机部署 eureka 应用。
for(int j=0;j<Servers.length;j++){
//获取当前遍历的服务器名称
def ServerName = Servers[j]
//加上指定主机的参数格式:--spring.profiles.active=eureka-server1/eureka-server2
def activeProfile = "--spring.profiles.active="
//根据不同的服务器名称(docker/docker-slave),来区分 eureka服务部署的主机
if(ServerName == "docker"){
activeProfile = activeProfile+"eureka-server1"
}else if(ServerName == "docker-slave") {
activeProfile = activeProfile+"eureka-server2"
}
// 部署应用
sshPublisher(publishers: [sshPublisherDesc(configName: "${ServerName}", transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "/opt/jenkins/deployCluster.sh $harbor_url $harbor_project $projectName $tag $projectPort $activeProfile", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
}
}
}
在所有的 docker 生产服务器创建此脚本
/opt/jenkins/deployCluster.sh
#!/bin/sh
harbor_url=$1 #对应$harbor_url
harbor_project_name=$2 #对应$harbor_project
project_name=$3 #对应$projectName
tag=$4 #对应$tag
port=$5 #对应$projectPort
profile=$6 #对应$activeProfile
imageName=$harbor_url/$harbor_project_name/$project_name:$tag
echo "==========$imageName========="
#查询容器是否存在,存在即删除该容器
containerId=`docker ps -a | grep -w ${project_name}:${tag} | awk '{print $1}'`
echo "==========$containerId==========="
if [ "$containerId" != " " ];then
#删除容器
docker rm -f $containerId && echo "成功删除容器"
fi
#查看镜像是否存在,存在即删除该镜像
imageId=`docker images | grep -w $project_name | awk '{print $3}'`
echo "=========$imageId========="
if [ "$imageId" != " " ];then
#删除镜像
docker rmi $imageId && echo "成功删除镜像"
fi
#登录 Harbor
docker login -u shm -p QQ1136265636.com $harbor_url
#下载容器
docker pull $imageName
#启动容器
docker run -itd -p $port:$port $imageName $profile
echo "新版本容器启动成功"
构建测试一下,同时勾选两个生产服务器,看看能不能同时部署上 eureka
五、总结
这种高可用集群部署方案,可以同时在 多个生产服务器 上,同时部署多个相同的微服务。达到高可用集群效果。
如下图,可以一次构建所有需求。
完整的 Jenkinsfile 文件
//设置 gitlab 拉取凭证ID号的变量
def git_auth = "218fb747-c605-4fa0-80d3-c322cd42d7a9"
//设置 gitlab 拉取代码 URL 地址的变量
def git_url = "git@192.168.168.12:itheima_group/tensquare_front.git"
//镜像版本号
def tag = "latest"
//Harbor仓库的IP地址
def harbor_url = "192.168.168.14"
//Harbor凭证
def harbor_auth = "584bf0a9-d247-4c4f-9e29-b9291381dd45"
//Harbor仓库
def harbor_project = "tensquare"
node {
//获取当前选择的项目名称
def projectNames = "${project_name}".split(",")
//获取当前选择的服务器名称
def Servers = "${publish_server}".split(",")
stage('拉取代码') {
checkout([$class: 'GitSCM', branches: [[name: '*/${branch}']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]]])
}
stage('代码审查') {
for(int i=0; i<projectNames.length;i++){
//获取每个微服务的名字:microservice-base-eureka:8000
def projectInfo = projectNames[i];
sh "echo ${projectNames}"
//切割出微服务名:microservice-base-eureka
def projectName = "${projectInfo}".split("@")[0]
sh "echo ${projectName}"
//切割出port:8000
def projectPort = "${projectInfo}".split("@")[1]
sh "echo ${projectPort}"
//定义当前jenkins的 sonarQubeScanner 工具
def scannerHome = tool 'sonar-Scanner'
//引用当前 JenkinsSonarQube
withSonarQubeEnv('sonarqube') {
sh """
cd ${projectName}
${scannerHome}/bin/sonar-scanner
"""
}
}
}
stage('编译,安装父工程') {
sh "/usr/local/maven/bin/mvn -f microservice-base-common install"
sh "/usr/local/maven/bin/mvn -f microservice-base-common clean package"
}
stage('编译,安装公共子工程,制作镜像') {
for(int i=0; i<projectNames.length;i++){
//获取每个微服务的名字:microservice-base-eureka:8000
def projectInfo = projectNames[i];
//切割出微服务名:microservice-base-eureka
def projectName = "${projectInfo}".split("@")[0]
sh "/usr/local/maven/bin/mvn -f ${projectName} clean package dockerfile:build"
}
}
stage('镜像上传至Harbor仓库') {
for(int i=0; i<projectNames.length;i++){
//获取每个微服务的名字:microservice-base-eureka:8000
def projectInfo = projectNames[i];
//切割出微服务名:microservice-base-eureka
def projectName = "${projectInfo}".split("@")[0]
//切割出port:8000
def projectPort = "${projectInfo}".split("@")[1]
//定义镜像名字
def imageName = "${projectName}:${tag}"
//为镜像打标签
sh "docker tag ${imageName} ${harbor_url}/${harbor_project}/${imageName}"
//凭据登录Harbor
withCredentials([usernamePassword(credentialsId:"${harbor_auth}", passwordVariable: 'password', usernameVariable: 'username')]) {
//引用用户名密码登录
sh "docker login -u ${username} -p ${password} ${harbor_url}"
//镜像上传
sh "docker push ${harbor_url}/${harbor_project}/${imageName} && echo 镜像上传成功"
//登出 Harbor
sh "docker logout ${harbor_url}"
}
for(int j=0;j<Servers.length;j++){
//获取当前遍历的服务器名称
def ServerName = Servers[j]
//加上指定主机的参数格式:--spring.profiles.active=eureka-server1/eureka-server2
def activeProfile = "--spring.profiles.active="
//根据不同的服务器名称(docker/docker-slave),来区分 eureka服务部署的主机
if(ServerName == "docker"){
activeProfile = activeProfile+"eureka-server1"
}else if(ServerName == "docker-slave") {
activeProfile = activeProfile+"eureka-server2"
}
// 部署应用
sshPublisher(publishers: [sshPublisherDesc(configName: "${ServerName}", transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "/opt/jenkins/deployCluster.sh $harbor_url $harbor_project $projectName $tag $projectPort $activeProfile", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
}
}
}
六、前端网站与微服务对接
Nginx + Zuul集群,实现网关高可用架构
①搭建Nginx(已完成)
②修改Nginx 配置文件
upstream zuulServer{
server 192.168.168.103:10020 weight=1;
server 192.168.168.104:10020 weight=1;
}
server {
listen default_server;
server_name _;
root /usr/local/nginx/html
location / {
proxy_pass http://zuulServer/;
}
}
systemctl restart nginx
更多推荐
所有评论(0)