上一篇已经将流水线常用语法案例整理了。在这之前,也使用shell写过一键部署springboot项目的脚本。本文会综合前面的知识,编写一条完整的发布springboot到k8s集群的流水线。
其实,发布流程都大同小异,只是看使用的是啥工具去实现发布流程,人工/shell/jenkins等
当然,基础流程是这样,但是有部分细节还是需要另外考虑。
Dockerfile文件不建议另外存放了,可直接和源码一起存放。
这个也一样,可直接和源码一起存放。
开源项目的生产配置文件是不可能直接放在源码上的(当然,即使是不开源,生产配置也不建议放在源码上,因为这样所有开发人员都有访问权限了),所以需要另外存放。这里暂时存放在宿主机的某个目录上。然后指定运行环境时,将目录挂载到容器中。
代码片段:
agent {
docker {
image 'maven:3-alpine'
args '-v /root/.m2:/root/.m2 -v /root/项目名称-config:/root/项目名称-config'
}
}
其中/root/.m2
是maven的依赖,这样保证宿主和容器共用依赖,避免了每次都要重新下载。
流水线有两种定义方式,一种是前面几篇文章讲到的Pipeline script
,这种直接就由Jenkins管理。另一种是Pipeline script from SCM
,该种即将流水线和源码放在一起,然后使用SCM检出代码的同时检出流水线。为了调试方便,这里先使用前者,后续再考虑转成后者。
参数名 | 默认值 | 说明 |
---|---|---|
project_name | mldong-admin | 项目名称 |
deploy_type | deploy | 发布类型,暂未使用 |
git_url | [email protected]:mldong/mldong.git | 仓库地址 |
branch_name | master | 分支名称 |
profiles | test | 环境类型(prod/test) |
registry_url | registry-vpc.cn-zhangjiakou.aliyuncs.com | docker镜像仓库地址 |
registry_ns | mldong/java | 镜像命名空间 |
hostname | c.mldong.com | 绑定的域名 |
k8sCredentialsId | ali-k8s-config | k8s集群配置id |
k8sServerUrl | https://172.26.22.121:6443 | k8s集群服务地址 |
├── mldong 源码根目录
├── mldong-admin
└── pom.xml
├── mldong-common
└── pom.xml
├── mldong-generator
└── pom.xml
├── mldong-mapper
└── pom.xml
├── Dockerfile
├── k8s.tpl
└── Jenkinsfile
mldong/Dockerfile
服务镜像定义文件,与之前一键部署的springboot项目的一致
/java_projects/mldong-admin
[root@mldong mldong-admin]# cat Dockerfile
# 指定基础镜像
FROM openjdk:8u212-jdk-alpine
# 维护者信息
MAINTAINER mldong <[email protected]>
# 创建应用目录
RUN mkdir -p /app && mkdir -p /app/config
# 进入工作目录
WORKDIR /app
# 复制jar
COPY app.jar .
# 配置配置文件
COPY config/* .
# EXPOSE 映射端口
EXPOSE 8080
# CMD 运行以下命令(如果yaml文件定义了command会被覆盖)
CMD ["/bin/sh","-c","set -e && java -jar app.jar --spring.profiles.active=dev --server.port=8080"]
mldong/k8s.tpl
k8s发布模板,与之前一键部署的springboot项目的一致
apiVersion: v1
kind: Namespace
metadata:
name: {{NAMESPACE}}
---
apiVersion: v1
kind: Service
metadata:
name: {{APP_NAME}}-nodeport
namespace: {{NAMESPACE}}
spec:
type: NodePort
ports:
- port: 8080
targetPort: 8080
selector:
app: {{APP_NAME}}
---
apiVersion: v1
kind: Service
metadata:
name: {{APP_NAME}}
namespace: {{NAMESPACE}}
spec:
type: ClusterIP
ports:
- port: 8080
protocol: TCP
targetPort: 8080
selector:
app: {{APP_NAME}}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{APP_NAME}}
namespace: {{NAMESPACE}}
spec:
selector:
matchLabels:
app: {{APP_NAME}}
replicas: 1
template:
metadata:
labels:
app: {{APP_NAME}}
spec:
containers:
- name: {{APP_NAME}}
env:
- name: TZ
value: Asia/Shanghai
image: {{IMAGE_URL}}:{{IMAGE_TAG}}
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
name: port
protocol: TCP
command: ["/bin/sh"]
args: ["-c", "set -e && java -jar app.jar --spring.profiles.active={{PROFILES}} --server.port=8080"]
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
name: {{APP_NAME}}-ingress
namespace: {{NAMESPACE}}
spec:
rules:
- host: {{HOST}}
http:
paths:
- backend:
serviceName: {{APP_NAME}}
servicePort: 8080
path: /
mldong/Jenkinsfile
流水线定义文件
pipeline {
agent any
// 环境变量
environment {
// docker私有仓库凭证
dockerhub_credentials = credentials('ali-dockerhub')
// 镜像版本
image_tag = sh(returnStdout: true,script: 'echo `date +"%Y%m%d%H%M"_``git describe --tags --always`').trim()
}
// 入参定义
parameters {
string(name: 'project_name', defaultValue: 'mldong-admin', description: '项目名称')
string(name: 'deploy_type', defaultValue: 'deploy', description: '发布类型')
string(name: 'git_url', defaultValue: '[email protected]:mldong/mldong.git', description: '仓库地址')
string(name: 'branch_name', defaultValue: 'master', description: 'git分支')
string(name: 'profiles', defaultValue: 'test', description: '环境')
string(name: 'registry_url', defaultValue: 'registry-vpc.cn-zhangjiakou.aliyuncs.com', description: '镜像仓库地址')
string(name: 'registry_ns', defaultValue: 'mldong/java', description: '镜像命名空间')
string(name: 'hostname', defaultValue: 'c.mldong.com', description: '绑定的域名')
string(name: 'k8sCredentialsId', defaultValue: 'ali-k8s-config', description: 'k8s集群配置id')
string(name: 'k8sServerUrl', defaultValue: 'https://172.26.22.121:6443', description: 'k8s集群服务地址')
}
stages{
stage('检出代码') {
steps{
// 检出代码
checkout([$class: 'GitSCM', branches: [[name: "*/${params.branch_name}"]],
doGenerateSubmoduleConfigurations: false,
extensions: [],
submoduleCfg: [],
userRemoteConfigs: [[
credentialsId: 'mldong-gitbash',
url: "${params.git_url}"]]])
}
}
stage("编译打包"){
agent {
docker {
image 'maven:3-alpine'
args "-v /root/.m2:/root/.m2 -v /root/${params.project_name}-config:/root/${params.project_name}-config"
}
}
steps{
// 编译打包
sh "mvn -B -DskipTests clean package"
// 删除当前目录下的config
sh "rm -rf config"
// 复制配置文件到当前工作空间
sh "cp -rf /root/${params.project_name}-config config"
sh "pwd"
}
}
stage('构建镜像及推送到docker仓库') {
steps {
sh "pwd"
// 将前一步的配置文件复制到当前目录下
sh "cp -rf ${env.WORKSPACE}@2/config config"
// 将前一步生成的jar包复制到当前工作空间下
sh "cp -rf ${env.WORKSPACE}@2/${params.project_name}/target/${params.project_name}.jar app.jar"
// 登录镜像仓库
sh "docker login -u ${dockerhub_credentials_USR} -p ${dockerhub_credentials_PSW} ${params.registry_url}"
// 构建镜像
sh "docker build -t ${params.registry_url}/${params.registry_ns}/${params.project_name}:${image_tag} ."
// 推送镜像到私服
sh "docker push ${params.registry_url}/${params.registry_ns}/${params.project_name}:${image_tag}"
// 删除当前目录下的config
sh "rm -rf config"
// 删除当前目录下的app.jar
sh "rm -rf app.jar"
}
}
stage('生成k8s发布模板') {
steps {
// 生成k8s发布模板
sh "sed -e 's#{{APP_NAME}}#${params.project_name}#g;s#{{NAMESPACE}}#${params.project_name}-${params.profiles}#g;s#{{PROFILES}}#${params.profiles}#g;s#{{IMAGE_URL}}#${params.registry_url}/${params.registry_ns}/${params.project_name}#g;s#{{IMAGE_TAG}}#${image_tag}#g;s#{{HOST}}#${params.hostname}#g' k8s.tpl > k8s.yaml"
// 暂存文件
stash name: "k8s.yaml", includes: "k8s.yaml"
// 查看文件
sh "cat k8s.yaml"
}
}
stage("kubectl apply") {
agent {
docker {
image 'lwolf/helm-kubectl-docker'
}
}
steps {
withKubeConfig([credentialsId: "${params.k8sCredentialsId}",serverUrl: "${params.k8sServerUrl}"]) {
// 取出文件
unstash("k8s.yaml")
// 发布到k8s集群
sh 'kubectl apply -f k8s.yaml'
}
}
}
}
}
配置私有仓库用户名密码
配置k8s凭证
宿主机上添加springboot配置文件,目录和编译打包挂载的目录一致。
新增任务(略)
构建项目
结果
可查查看pods详情,镜像一致
kubectl describe pods -n mldong-admin-test
https://gitee.com/mldong/mldong
https://gitee.com/mldong/mldong-vue
本文以springboot项目为例,编写一个较为完整的发布流水线。看过前面一键部署springboot项目的同学,可能对这个会更有感触些。在我看来,自己使用shell写的一键发布脚本和jenkins流水线写的发布脚本,其实现的思路都大同小异。只不过jenkins的流水线会有更多的配套。而我之所以两个版本都分享了(其实加上快速开发框架的那个一键部署脚本,也有三个版本了),一是为了循序渐进地学习,二是为了让想学习这块内容的同学更多的思路,同时可以根据自己公司的情况,选择不一样的发布方式。咱们做这些,都是为了效率。