1.创建分支及必须的脚本文件
以工程consumer为例
创建分支production、development
git branch production
git branch development
git checkout production
git push -u origin production
git checkout development
git push -u origin development
git checkout master
查看代码仓库是否已经推送
在创建多分支流水线之前查看代码结构
创建应用所需的基础镜像文件
cat Dockerfile
FROM 192.168.0.152:8082/jre8:alphine
ADD target/*jar /tmp/
WORKDIR /tmp
CMD java -jar $(ls *.jar)
创建多分支流水线的pipeline
cat Jenkinsfile
pipeline {
agent any
tools {
maven 'maven'
}
environment {
CI = 'true'
GROUP = readMavenPom().getGroupId()
ARTIFACT = readMavenPom().getArtifactId()
VERSION = readMavenPom().getVersion()
}
stages {
stage('build master') {
when {
branch 'master'
}
steps {
sh 'mvn clean install'
}
}
stage('build development') {
when {
branch 'development'
}
steps {
sh 'mvn clean install'
}
}
stage('build production') {
when {
branch 'production'
}
steps {
sh 'mvn clean install'
}
}
stage('push image') {
steps {
script {
docker.withRegistry("http://192.168.0.152:8082",'01385c55-7871-4868-a03a-889c4dc403ec') {
def customimage = docker.build("${GROUP}-${ARTIFACT}:${VERSION}")
customimage.push()
}
}
}
}
stage('master deploy') {
when {
branch 'master'
}
steps {
sh './jenkins/scripts/master-deploy.sh'
}
}
stage('development deploy') {
when {
branch 'development'
}
steps {
sh './jenkins/scripts/development-deploy.sh'
}
}
stage('production deploy') {
when {
branch 'production'
}
steps {
sh './jenkins/scripts/production-deploy.sh'
}
}
}
}
创建各分支部署脚本
这里以production分支为例
cat jenkins/scripts/production-deploy.sh
#!/bin/bash
jarfile=$(echo $(ls target/*jar) | awk -F '/' '{print $2}')
jarname=${jarfile%.*}
tag=${jarname#*-}
cat <<EOF>> docker-compose.yml
version: "3.4"
services:
consumer:
image: 192.168.0.152:8082/com.teng-consumer:$tag
networks:
- service_overlay
- monitor_overlay
- database_overlay
- elk_overlay
ports:
- 8084:8084
volumes:
- "/etc/localtime:/etc/localtime:ro"
deploy:
placement:
constraints: [node.hostname==node150]
restart_policy:
condition: any
delay: 5s
max_attempts: 3
networks:
service_overlay:
external: true
monitor_overlay:
external: true
database_overlay:
external: true
elk_overlay:
external: true
EOF
scp docker-compose.yml root@192.168.0.150:/root/docker/consumer
ssh root@192.168.0.150 'cd /root/docker/consumer && docker stack deploy -c docker-compose.yml 150'
该脚本有三处需要注意
- 需要对jenkins容器配置到swarm主节点的免密传输
- 因为这里设置的是将服务部署在主节点且jenkins也部署在主节点,故脚本中没有进行应用镜像的pull操作,如果微服务部署到非主节点脚本中需要进行镜像拉取
- 脚本里创建的docker-compose.yml文件要传到目标节点进行部署,故需要在服务部署的节点上事先创建服务运行的目录,这里是/root/docker/consumer
免密传输
docker exec -it jenkins_container_name bash
ssh-copy-id -i /var/jenkins_home/.ssh/id_rsa.pub root@192.168.0.150
2.创建多分支流水线
在创建前先清空各个分支的Jenkinsfile,等初始化完成了多分支流水线任务后,再将前面创建Jenkinsfile的内容添加进来
访问jenkins站点,打开blueocean,
点击确定就会开始构建,最后正常的状态是如下图所示
3.测试各个分支
以production分支为例,添加脚本到Jenkinsfile ,在multi-consumer点击运行
4.更新应用
更新应用也就是要更新应用镜像,一般会针对某个分支进行重新打包编译生成新的镜像进行发布
还是以production为例,将pom.xml里的version升级为0.0.7-production,提交最新改动到gitlab仓库
修改发布脚本中的发布命令添加参数--prune
docker stack deploy -c docker-compose.yml --prune 150
重新执行流水线分支production
5.自动构建配置
多分支没有比较具体的自动触发插件,这里就直接使用gitlab的webhook来触发,配置gitlab
注意连接中的multi-consumer为多分支流水线任务名称,配置好后,执行测试“push event” ,发现三个分支流水线同时开始运行,说明触发成功
如果提交变更到具体的某个分支则只会触发对应的分支进行构建,当然为了更为灵活的出发构建还可以在pipeline脚本中使用判断限制来告诉jenkins哪些分支出发后才能正常运行,哪些分支即时触发了构建但会返回错误不再进行后续的操作,最终的脚本如下
cat Jenkinsfile
pipeline {
agent any
tools {
maven 'maven'
}
environment {
CI = 'true'
GROUP = readMavenPom().getGroupId()
ARTIFACT = readMavenPom().getArtifactId()
VERSION = readMavenPom().getVersion()
}
stages {
stage('pipeline环境准备') {
steps {
script {
echo "开始构建"
if(!env.BRANCH_NAME.startsWith('production') && !env.BRANCH_NAME.startsWith('development')){
error("自动构建分支名称必须以production或development开头,当前分支名称为: ${env.BRANCH_NAME}")
}
}
}
}
stage('build master') {
when {
branch 'master'
}
steps {
sh 'mvn clean install'
}
}
stage('build development') {
when {
branch 'development'
}
steps {
sh 'mvn clean install'
}
}
stage('build production') {
when {
branch 'production'
}
steps {
sh 'mvn clean install'
}
}
stage('push image') {
steps {
script {
docker.withRegistry("http://192.168.0.152:8082",'01385c55-7871-4868-a03a-889c4dc403ec') {
def customimage = docker.build("${GROUP}-${ARTIFACT}:${VERSION}")
customimage.push()
}
}
}
}
stage('master deploy') {
when {
branch 'master'
}
steps {
sh './jenkins/scripts/master-deploy.sh'
}
}
stage('development deploy') {
when {
branch 'development'
}
steps {
sh './jenkins/scripts/development-deploy.sh'
}
}
stage('production deploy') {
when {
branch 'production'
}
steps {
sh './jenkins/scripts/production-deploy.sh'
}
}
}
}