上一篇已经将流水线常用语法案例整理了。在这之前,也使用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 | git@gitee.com: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 <524719755@qq.com> # 创建应用目录 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: 'git@gitee.com: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 复制代码
本文以springboot项目为例,编写一个较为完整的发布流水线。看过前面一键部署springboot项目的同学,可能对这个会更有感触些。在我看来,自己使用shell写的一键发布脚本和jenkins流水线写的发布脚本,其实现的思路都大同小异。只不过jenkins的流水线会有更多的配套。而我之所以两个版本都分享了(其实加上快速开发框架的那个一键部署脚本,也有三个版本了),一是为了循序渐进地学习,二是为了让想学习这块内容的同学更多的思路,同时可以根据自己公司的情况,选择不一样的发布方式。咱们做这些,都是为了效率。