说明:
此 pipeline 可以实现:
1 通过Jenkins的页面上传一个包含所有需要部署的jar包的压缩包文件,上传的压缩包名称不限制,扩展名支持 tar.gz 、 tgz 、zip
2 其中每个 jar 包的命名格式需要遵循的格式是:
镜像名-tag.jar
这里镜像名需要和 kubernetes 中的 deployment 名称以及容器名称一致。
tag 建议和微服务的版本号一致,便于管理。
#!groovy
@Library("jenkinsci-unstashParam-library") _
pipeline {
// 指定运行构建的主机名和工作空间
agent any
// 全局选项
options {
//disableResume() // 当 master 重启后,不允许恢复流水线
timestamps() //日志会有时间, 它对应了一个同名的插件
skipDefaultCheckout() //删除隐式checkout scm语句
//disableConcurrentBuilds() //禁止并行
timeout(time: 30, unit: 'MINUTES') //流水线超时设置1h
buildDiscarder(logRotator(numToKeepStr: '10')) //设置构建历史保存个数
}
environment {
// 定义全局环境变量
PATH="/usr/local/bin:/usr/bin:/bin:/sbin:/usr/sbin"
// 本地 docker 仓库
REGISTRY_LOCAL = "dockerhub.kubekey.local"
// 一个使用 username/password 方式添加到 Jenkins 中的凭证 id
// 如果不需要用户名密码验证的仓库,此值可以指定为空字符串: ''
REGISTRY_AUTH = ''
// 远程服务器凭证 ID,需要在 jenkins 系统管理中添加登录远程服务器
// 时使用的用户名和密码的凭证,凭证的名字 target-host
HOSTAUTH = credentials("target-host")
}
parameters {
// 定义一个 选项参数
choice (choices: ['yes', 'no'], description: '解压之后,是否删除上传的 tar.gz 部署包?', name: 'delTgz')
// 定义一个文本参数
//string (name: 'version', defaultValue: '1.0', description: 'build version')
file (name: 'deploy-java', description: '''上传的文件会被保存在 Jenkins 的工作空间:
宿主机的 /apps/middle/jenkins/jenkinsHome/workspace/此任务名/ 目录下,只能传 tar.gz 格式的文件。解压后的目录结构需要是直接的 jar 包,或者含有 java 程序的目录。''')
}
// 任务段,所有的任务都在这里声明
stages {
stage('解压部署包'){
steps{
script{
//获取到上传的部署压缩包,并解压到 jenkins 的 /extractJava 目录下
def file = unstashParam "deploy-java"
if (file.endsWith(".tar.gz") || file.endsWith(".tgz")){
sh "tar -xf ${file} -C /extractJava/"
}else if(file.endsWith(".zip")){
sh "unzip ${file} -d /extractJava/"
}else{
echo "没有识别到压缩文件,需要是 tar.gz tgz 或者 zip"
}
if(delTgz == "yes"){
//是否删除上传的压缩包
sh "rm -rf ${file}"
}
}
}
}
stage("构建镜像,上传到本地 docker registry"){
steps{
script{
// 配置使用 ssh 方式登录远程服务器(k8s-master1)
def remote = [:]
remote.name = 'k8s-master1'
remote.host = "192.168.0.231"
remote.port = 22
remote.allowAnyHosts = true
remote.user = env.HOSTAUTH_USR
remote.password = env.HOSTAUTH_PSW
// 配置使用 ssh 方式登录远程服务器结束
// 获取到文件列表
def appFiles = sh(script: "cd /extractJava;ls -1d *.jar", returnStdout: true).trim()
// 存放所有此次需要部署的 jar 文件名,文件名的命名格式: 镜像名(应用的名称)-容器tag(应用的版本号)
def imgNameTagLst = []
def imgName = ""
def imgTag = ""
def appNames = appFiles.tokenize('\n')
echo "${appNames}"
for (file in appNames){
file = file.trim()
if (!file){
continue
}
if (file.endsWith(".jar")){
sh "cp -u /extractJava/${file} /builddir/spms-server/apps/app.jar"
def imgNameTag = file.minus(".jar")
imgNameTagLst = imgNameTag.tokenize("-")
imgTag = imgNameTagLst.pop()
imgName = imgNameTagLst.join("-")
echo "准备构建的镜像为 ${imgName}:${imgTag}"
dir("/builddir/spms-server"){
sh "docker build -f /builddir/spms-server/dockerfile/Dockerfile -t ${env.REGISTRY_LOCAL}/${imgName}:${imgTag} ."
sh "docker push ${env.REGISTRY_LOCAL}/${imgName}:${imgTag}"
echo "================删除镜像====================="
sh "docker rmi ${env.REGISTRY_LOCAL}/${imgName}:${imgTag}"
sh "rm -rf /builddir/spms-server/apps/*"
}
namespaces = "spms-bluespace"
// 更新应用到 k8s
sshCommand(
remote: remote,
command: "kubectl -n ${namespaces} set image deployments ${imgName} ${imgName}=${env.REGISTRY_LOCAL}/${imgName}:${imgTag}"
)
}
}
}
}
}
stage("清除工作空间的文件"){
steps{
script{
echo "rm -rf ${env.WORKSPACE}/*"
}
}
}
}
post {
failure{
echo "failure: 有失败的任务"
}
success{
echo "success: 恭喜!所有任务均成功了!"
}
always {
echo "无论任务是否成功,均删除解压后的文件"
sh "rm -rf /extractJava/*"
sh "rm -rf /builddir/*/apps/*"
}
aborted{
echo "aborted: 手动终止登录任务的执行"
}
unstable{
echo "unstable: 通常由于测试失败,代码违规等造成,导致了流水线或阶段的完成状态为 unstable"
}
}
}