微信公众号「后端进阶」,专一后端技术分享:Java、Golang、WEB框架、分布式中间件、服务治理等等。
老司机倾囊相授,带你一路进阶,来不及解释了快上车!node
最近在公司推行Docker Swarm集群的过程当中,须要用到Jenkins来作自动化部署,Jenkins实现自动化部署有不少种方案,能够直接在jenkins页面写Job,把一些操做和脚本都经过页面设置,也能够在每一个项目中直接写Pipeline脚本,但像我那么优秀,那么追求极致的程序员来讲,这些方案都打动不了我那颗骚动的心,下面我会跟大家讲讲我是如何经过Pipeline脚本实现自动化部署方案的,而且实现多分支构建,还实现了全部项目共享一个Pipeline脚本。git
为了快速搭建Jenkins,我这里使用Docker安装运行Jenkins:程序员
$ sudo docker run -it -d \
--rm \
-u root \
-p 8080:8080 \
-v jenkins-data:/var/jenkins_home \
-v /var/run/docker.sock:/var/run/docker.sock \
-v "$HOME":/home \
--name jenkins jenkinsci/blueocean
复制代码
初次使用jenkins,进入Jenkins页面前,须要密码验证,咱们须要进入docker容器查看密码:github
$ sudo docker exec -it jenkins /bin/bash
$ vi /var/jenkins_home/secrets/initialAdminPassword
复制代码
Docker安装的Jenkins稍微有那么一点缺陷,shell版本跟CenOS宿主机的版本不兼容,这时咱们须要进入Jenkins容器手动设置shell:docker
$ sudo docker exec -it jenkins /bin/bash
$ ln -sf /bin/bash /bin/sh
复制代码
因为咱们的Pipeline还须要在远程服务器执行任务,须要经过ssh链接,那么咱们就须要在Jenkins里面生成ssh的公钥密钥:shell
$ sudo docker exec -it jenkins /bin/bash
$ ssh-keygen -C "root@jenkins"
复制代码
在远程节点的~/.ssh/authorized_keys中添加jenkins的公钥(id_rsa.pub)后端
还须要安装一些必要的插件:bash
安装完插件后,还须要去全局工具那里添加maven:服务器
这里后面Jenkinsfile有用到。微信
因为咱们的开发是基于多分支开发,每一个开发环境都对应有一条分支,因此普通的Pipeline自动化构建并不能知足现有的开发部署需求,因此咱们须要使用Jenkins的mutiBranch Pipeline。
首先固然是新建一个mutiBranch多分支构建job:
接着设置分支源,分支源就是你项目的git地址,选择Jenkinsfile在项目的路径
接下来Jenkins会在分支源中扫描每一个分支下的Jenkinsfile,若是该分支下有Jenkinsfile,那么就会建立一个分支Job
该job下的分支job以下:
这里须要注意的是,只有须要部署的分支,才加上Jenkinsfile,否则Jenkins会将其他分支也建立一个分支job。
到这里以前,基本就能够基于Pipeline脚本自动化部署了,但若是你是一个追求极致,不甘于平庸的程序员,你必定会想,随着项目的增多,Pipeline脚本不断增多,这会形成愈来愈大的维护成本,随着业务的增加,不免会在脚本中修改东西,这就会牵扯太多Pipeline脚本了,并且这些脚本基本都相同,那么对于我这么优秀的程序员,怎么会想不到这个问题呢,我第一时间就想到通用化pipeline脚本。所幸,Jenkins已经看出了我不断骚动的心了,Jenkins甩手就给我一个Shared Libraries。
Shared Libraries是什么呢?顾名思义,它就是一个共享库,它的主要做用是用于将通用的Pipeline脚本放在一个地方,其它项目能够从它那里获取到一个全局通用化的Pipeline脚本,项目之间经过不通的变量参数传递,达到通用化的目的。
接下来咱们先建立一个用于存储通用Pipeline脚本的git仓库:
仓库目录不是随便乱添加了,Jenkins有一个严格的规范,下面是官方说明:
官方已经讲得很清楚了,大概意思就是vars目录用于存储通用Pipeline脚本,resources用于存储非Groovy文件。因此我这里就把Pipeline须要的构建脚本以及编排文件都集中放在这里,彻底对业务工程师隐蔽,这样作的目的就是为了不业务工程师不懂瞎几把乱改,致使出bug。
建立完git仓库后,咱们还须要在jenkins的Manage Jenkins » Configure System » Global Pipeline Libraries
中定义全局库:
这里的name,能够在jenkinsfile中经过如下命令引用:
@Library 'objcoding-pipeline-library'
复制代码
下面咱们来看通用Pipeline脚本的编写规则:
#!groovy
def getServer() {
def remote = [:]
remote.name = 'manager node'
remote.user = 'dev'
remote.host = "${REMOTE_HOST}"
remote.port = 22
remote.identityFile = '/root/.ssh/id_rsa'
remote.allowAnyHosts = true
return remote
}
def call(Map map) {
pipeline {
agent any
environment {
REMOTE_HOST = "${map.REMOTE_HOST}"
REPO_URL = "${map.REPO_URL}"
BRANCH_NAME = "${map.BRANCH_NAME}"
STACK_NAME = "${map.STACK_NAME}"
COMPOSE_FILE_NAME = "docker-compose-" + "${map.STACK_NAME}" + "-" + "${map.BRANCH_NAME}" + ".yml"
}
stages {
stage('获取代码') {
steps {
git([url: "${REPO_URL}", branch: "${BRANCH_NAME}"])
}
}
stage('编译代码') {
steps {
withMaven(maven: 'maven 3.6') {
sh "mvn -U -am clean package -DskipTests"
}
}
}
stage('构建镜像') {
steps {
sh "wget -O build.sh https://git.x-vipay.com/docker/jenkins-pipeline-library/raw/master/resources/shell/build.sh"
sh "sh build.sh ${BRANCH_NAME} "
}
}
stage('init-server') {
steps {
script {
server = getServer()
}
}
}
stage('执行发版') {
steps {
writeFile file: 'deploy.sh', text: "wget -O ${COMPOSE_FILE_NAME} " +
" https://git.x-vipay.com/docker/jenkins-pipeline-library/raw/master/resources/docker-compose/${COMPOSE_FILE_NAME} \n" +
"sudo docker stack deploy -c ${COMPOSE_FILE_NAME} ${STACK_NAME}"
sshScript remote: server, script: "deploy.sh"
}
}
}
}
}
复制代码
remote.identityFile
就是咱们上面在容器生成的密钥的地址;从脚本看出来Jenkins未来要推崇的一种思惟:配置即代码。
写完通用Pipeline脚本后,接下来咱们就须要在各个项目的须要自动化部署的分支的根目录下新建一个Jenkinsfile脚本了:
接下来我来解释一下Jenkinsfile内容:
#!groovy
// 在多分支构建下,严格规定Jenkinsfile只存在能够发版的分支上
// 引用在jenkins已经全局定义好的library
library 'objcoding-pipeline-library'
def map = [:]
// 远程管理节点地址(用于执行发版)
map.put('REMOTE_HOST','xxx.xx.xx.xxx')
// 项目gitlab代码地址
map.put('REPO_URL','https://github.com/objcoding/docker-jenkins-pipeline-sample.git')
// 分支名称
map.put('BRANCH_NAME','master')
// 服务栈名称
map.put('STACK_NAME','vipay')
// 调用library中var目录下的build.groovy脚本
build(map)
复制代码
library 'objcoding-pipeline-library'
引用咱们在Jenkins定义的全局库,定义一个map参数;Shared Libraries共享库极大地提高了Pipeline脚本的通用性,避免了脚本过多带来的问题,也符合了一个优秀程序员的审美观,若是你是一个有追求的程序员,你必定会爱上它。
架构图:
demo git 地址:
pipeline脚本: github.com/objcoding/j…
单项目部署: github.com/objcoding/d…
多项目部署: github.com/objcoding/d…