文章简介
- 上次写过一篇使用 Jenkins 在远程服务器上部署 docker 镜像的通用脚本,这次这份脚本是基于上次那份脚本修改而来,用于 Kubernetes 部署镜像使用。
- Kubernetes 部署相关信息可以查看这篇文章:Kubernetes 生产入门:Deployment 与 Service 配置实战
- 本文介绍的部署脚本适用于单工程下多 module 的微服务,单工程服务需要阅读脚本自行微调。不过我建议使用本文脚本的每一位朋友都能够阅读所有的代码,确定是否符合自己的需求。
脚本变量
- 定义、设置变量主要是为了形成一个通用型脚本,部署多个服务尤其微服务时,编写好一个流水线脚本,其他流水线可以直接复制使用,复制后只需修改此处变量即可。
- 此处有部分变量嵌套使用 MODULE_NAME、MODULE_PATH 变量复用相同参数,使用本文脚本的朋友一定要观察此处的变量是否与你们工程一致。
- 具体参数信息代码中已有注释,不过多赘述
ini
environment {
// 模块信息
MODULE_NAME = "xxx-service" // 模块名称
MODULE_PATH = "./${MODULE_NAME}" // 模块路径,适用于微服务多 module
// Git 仓库配置
GIT_URL = 'git@git.xxx.com:xxx.git' // 替换为你的代码仓库
GIT_KEY_ACR_CRED = 'git-ssh-key'
BRANCH = 'master'
// Docker 镜像相关配置
DOCKER_IMAGE_REGISTRY = 'registry.xxx.aliyuncs.com' // 替换为你的镜像仓库
DOCKER_IMAGE_ACR_CRED = 'docker-cred'
IMAGE_PRE_NAME = 'xxxx' // 镜像名称前缀
IMAGE_NAME = "${MODULE_NAME}" // 镜像名称
DOCKERFILE = "${MODULE_PATH}/Dockerfile" // 用来构建镜像的 dockerfile 文件
// Kubernetes 相关配置
KUBERNETES_CONFIG = "kubernetes-config" // Kubernetes 配置文件凭证
RESOURCE_NAME = "${MODULE_NAME}" // 资源类型名称,这里为 deployment 名称
CONTAINER_NAME = "${MODULE_NAME}" // 容器名称
}
工具设置
这里设置构建代码的 Maven 工具
groovy
tools {
// Install the Maven version configured as "M3" and add it to the path.
maven "Maven3"
}
拉取代码
拉取仓库中的代码
- git branch: BRANCH:指定拉取的分支
- url: GIT_URL,设置代码仓库地址
- credentialsId:仓库访问凭据
groovy
stage('Checkout') {
steps {
git branch: BRANCH,
url: GIT_URL,
credentialsId: GIT_KEY_ACR_CRED
}
}
打包
由于是多 module 多微服务项目,此处使用 mvn 指定模块打包命令,防止构建不相关模块,且指定为 pro 配置
groovy
stage('Package') {
steps {
// 执行 Maven 打包命令,只打包指定模块
sh "mvn -pl ${MODULE_PATH} -am -B clean package -Ppro -Dfile.encoding=UTF-8 -DskipTests=true"
}
}
构建、推送 Docker 镜像,删除本地镜像
- 此处使用当前时间为镜像设置 tag
- 镜像名称格式:<镜像仓库地址>/<镜像名称前缀>/<应用名称>:<当前时间>
- sh "docker build -t ${fullImageNameWithTimestamp} ."
- 使用 docker 构建镜像
- withCredentials 使用凭据登陆、推送镜像
- 登陆仓库: sh "docker login --username REG_USER -p REG_PASS $DOCKER_IMAGE_REGISTRY"
- 推送镜像:sh "docker push ${fullImageNameWithTimestamp}"
- 删除本地镜像:sh "docker rmi ${fullImageNameWithTimestamp}"
- 将镜像名称保存到环境变量,供后续步骤使用:env.BUILT_IMAGE = fullImageNameWithTimestamp
groovy
stage('Build Docker Image') {
steps {
script {
// 生成时间戳
def timestamp = new Date().format('yyyyMMddHHmm', TimeZone.getTimeZone('Asia/Shanghai'))
def imageTag = "${IMAGE_NAME}:${timestamp}"
def fullImageNameWithTimestamp = "${DOCKER_IMAGE_REGISTRY}/${IMAGE_PRE_NAME}/${imageTag}"
// 使用 Docker 构建镜像
echo "Building Docker image: ${fullImageNameWithTimestamp}"
sh "docker build -t ${fullImageNameWithTimestamp} -f ${DOCKERFILE} ${MODULE_PATH}"
withCredentials([usernamePassword(credentialsId: DOCKER_IMAGE_ACR_CRED, usernameVariable: 'REG_USER', passwordVariable: 'REG_PASS')]) {
// 登录到镜像仓库
echo "Login Docker..."
sh "docker login --username $REG_USER -p $REG_PASS ${DOCKER_IMAGE_REGISTRY}"
// 推送镜像
echo "Push Docker Image ${fullImageNameWithTimestamp}"
sh "docker push ${fullImageNameWithTimestamp}"
// 推送完成后,删除本地镜像
echo "Remove Docker Imag ${fullImageNameWithTimestamp}"
sh "docker rmi ${fullImageNameWithTimestamp}"
}
// 输出构建信息
echo "Successfully built and pushed image: ${fullImageNameWithTimestamp}"
// 将镜像名称保存到环境变量,供后续步骤使用
env.BUILT_IMAGE = fullImageNameWithTimestamp
}
}
}
部署到远程 Kubernetes 集群
- withCredentials:使用凭据连接 Kubernetes 集群
- 设置集群连接配置:sh "export KUBECONFIG=$KUBECONFIG"
- 设置集群对应 Deployment 中的镜像信息:sh "kubectl set image deployment/ <math xmlns="http://www.w3.org/1998/Math/MathML"> R E S O U R C E N A M E {RESOURCE_NAME} </math>RESOURCENAME{CONTAINER_NAME}=${BUILT_IMAGE}"
- 备注:Kubernetes 集群中 Deployment 配置内镜像信息修改后,集群会自行拉起新的 Pod,关闭旧的 Pod。
groovy
stage('Deploy to Remote Kubernetes') {
steps {
script {
withCredentials([file(credentialsId: KUBERNETES_CONFIG, variable: 'KUBECONFIG')]) {
// 设置KUBECONFIG环境变量
sh "export KUBECONFIG=$KUBECONFIG"
// 更新Deployment中的镜像信息
// kubectl set image <资源类型>/<资源名称> <容器名称>=<新镜像>:<标签>
sh "kubectl set image deployment/${RESOURCE_NAME} ${CONTAINER_NAME}=${BUILT_IMAGE}"
}
}
}
}
附源码
groovy
pipeline {
agent any
environment {
// 模块信息
MODULE_NAME = "xxx-servcie" // 模块名称
MODULE_PATH = "./${MODULE_NAME}" // 模块路径,适用于微服务多 module
// Git 仓库配置
GIT_URL = 'git@git.xxx.com:xxx.git' // 替换为你的代码仓库
GIT_KEY_ACR_CRED = 'git-ssh-key'
BRANCH = 'master'
// Docker 镜像相关配置
DOCKER_IMAGE_REGISTRY = 'registry.xxx.aliyuncs.com' // 替换为你的镜像仓库
DOCKER_IMAGE_ACR_CRED = 'docker-cred'
IMAGE_PRE_NAME = 'xxxx' // 镜像名称前缀
IMAGE_NAME = "${MODULE_NAME}" // 镜像名称
DOCKERFILE = "${MODULE_PATH}/Dockerfile" // 用来构建镜像的 dockerfile 文件
// Kubernetes 相关配置
KUBERNETES_CONFIG = "kubernetes-config" // Kubernetes 配置文件凭证
RESOURCE_NAME = "${MODULE_NAME}" // 资源类型名称,这里为 deployment 名称
CONTAINER_NAME = "${MODULE_NAME}" // 容器名称
}
tools {
// Install the Maven version configured as "M3" and add it to the path.
maven "Maven3"
}
stages {
stage('Checkout') {
steps {
git branch: BRANCH,
url: GIT_URL,
credentialsId: GIT_KEY_ACR_CRED
}
}
stage('Package') {
steps {
// 执行 Maven 打包命令,只打包指定模块
sh "mvn -pl ${MODULE_PATH} -am -B clean package -Ppro -Dfile.encoding=UTF-8 -DskipTests=true"
}
}
stage('Build Docker Image') {
steps {
script {
// 生成时间戳
def timestamp = new Date().format('yyyyMMddHHmm', TimeZone.getTimeZone('Asia/Shanghai'))
def imageTag = "${IMAGE_NAME}:${timestamp}"
def fullImageNameWithTimestamp = "${DOCKER_IMAGE_REGISTRY}/${IMAGE_PRE_NAME}/${imageTag}"
// 使用 Docker 构建镜像
echo "Building Docker image: ${fullImageNameWithTimestamp}"
sh "docker build -t ${fullImageNameWithTimestamp} -f ${DOCKERFILE} ${MODULE_PATH}"
withCredentials([usernamePassword(credentialsId: DOCKER_IMAGE_ACR_CRED, usernameVariable: 'REG_USER', passwordVariable: 'REG_PASS')]) {
// 登录到镜像仓库
echo "Login Docker..."
sh "docker login --username $REG_USER -p $REG_PASS ${DOCKER_IMAGE_REGISTRY}"
// 推送镜像
echo "Push Docker Image ${fullImageNameWithTimestamp}"
sh "docker push ${fullImageNameWithTimestamp}"
// 推送完成后,删除本地镜像
echo "Remove Docker Imag ${fullImageNameWithTimestamp}"
sh "docker rmi ${fullImageNameWithTimestamp}"
}
// 输出构建信息
echo "Successfully built and pushed image: ${fullImageNameWithTimestamp}"
// 将镜像名称保存到环境变量,供后续步骤使用
env.BUILT_IMAGE = fullImageNameWithTimestamp
}
}
}
stage('Deploy to Remote Kubernetes') {
steps {
script {
withCredentials([file(credentialsId: KUBERNETES_CONFIG, variable: 'KUBECONFIG')]) {
// 设置KUBECONFIG环境变量
sh "export KUBECONFIG=$KUBECONFIG"
// 更新Deployment中的镜像
// kubectl set image <资源类型>/<资源名称> <容器名称>=<新镜像>:<标签>
sh "kubectl set image deployment/${RESOURCE_NAME} ${CONTAINER_NAME}=${BUILT_IMAGE}"
}
}
}
}
}
}