preface

Examples of pipelining syntax have been compiled in the last article. Prior to this, I also wrote scripts for one-click deployment of the SpringBoot project using shell. This article will synthesize the previous knowledge to write a complete pipeline for publishing SpringBoot to a K8S cluster.

Release Process Analysis

The release process is pretty much the same, depending on what tools are used to implement the release process, manual /shell/ Jenkins, etc

  1. Pull the code
  2. Compile the package
  3. Building a new image
  4. Push to a private repository
  5. Use the template to generate the new release YAML
  6. Call publish command

Of course, that’s the basic process, but some of the details need to be considered.

About Dockerfile

Dockerfile files are not recommended to be stored separately, can be directly stored with the source code.

About the K8S publishing template

This, too, can be stored directly with the source code.

About the production profile

Production configuration files for open source projects cannot be placed directly in the source code (of course, production configuration is not recommended in the source code even if it is not open source, because then all developers have access to it), so they need to be stored separately. This is temporarily stored in a directory on the host machine. The directory is then mounted into the container when the runtime environment is specified.

Code snippet:

agent { 
    docker {
    	image 'maven:3-alpine'
    	args '-v /root/.m2:/root/.m2 -v /root/project name -config: /root/project name -config'}}Copy the code

/root/.m2 is maven’s dependency, which ensures that the host and container share the dependency and avoids having to re-download each time.

About the pipeline definition file

There are two ways to define pipelining. One is the Pipeline script described in previous articles, which is directly managed by Jenkins. The other is Pipeline script from SCM, which puts the Pipeline and source together and then checks out the Pipeline simultaneously using the SCM to check out the code. For debugging purposes, use the former first, and switch to the latter later.

Start coding

Ginseng explanation to

Parameter names The default value instructions
project_name mldong-admin The project name
deploy_type deploy Release type, not currently in use
git_url [email protected]:mldong/mldong.git The warehouse address
branch_name master The name of the branch
profiles test Environment Type (PROD/Test)
registry_url registry-vpc.cn-zhangjiakou.aliyuncs.com Docker image repository address
registry_ns mldong/java Mirror namespace
hostname c.mldong.com Bound domain name
k8sCredentialsId ali-k8s-config K8s Cluster configuration ID
k8sServerUrl https://172.26.22.121:6443 K8s Cluster service address

The directory structure

├ ─ ─ mldong source root ├ ─ ─ mldong - admin └ ─ ─ pom. The XML ├ ─ ─ mldong - common └ ─ ─ pom. The XML ├ ─ ─ mldong - generator └ ─ ─ pom. The XML ├ ─ ─ ├─ ├─ k8s.tpl ├─ ├─ k8s.tpl ├─Copy the code

Core File Description

  • mldong/Dockerfile

    Service image definition file, consistent with the previous one-click deployment of the SpringBoot project

    /java_projects/mldong-admin
    [root@mldong mldong-admin]# cat Dockerfile 
    # specify the base image
    FROM openjdk:8u212-jdk-alpine
    # Maintainer information
    MAINTAINER mldong <[email protected]>
    Create an application directory
    RUN mkdir -p /app && mkdir -p /app/config
    Go to the working directory
    WORKDIR /app
    # copy jar
    COPY app.jar .
    Configure the configuration file
    COPY config/* .
    # EXPOSE Map port
    EXPOSE 8080
    # CMD Run the following command (if yaml file defines command will be overwritten)
    CMD ["/bin/sh"."-c"."set -e && java -jar app.jar --spring.profiles.active=dev --server.port=8080"]
    Copy the code
  • mldong/k8s.tpl

    K8s release template, consistent with the previous one-click deployment of the SpringBoot project

    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: /
    Copy the code
  • mldong/Jenkinsfile

    Pipeline definition file

    pipeline {
        agent any
        // Environment variables
        environment {
        	// Docker private repository credentials
            dockerhub_credentials = credentials('ali-dockerhub')
            // Mirror version
            image_tag = sh(returnStdout: true.script: 'echo `date +"%Y%m%d%H%M"_``git describe --tags --always`').trim()
        }
        // Enter the parameter definition
        parameters {
            string(name: 'project_name'.defaultValue: 'mldong-admin'.description: 'Project Name')
            string(name: 'deploy_type'.defaultValue: 'deploy'.description: 'Publication Type')
            string(name: 'git_url'.defaultValue: '[email protected]:mldong/mldong.git'.description: 'Warehouse address')
            string(name: 'branch_name'.defaultValue: 'master'.description: 'git branch')
            string(name: 'profiles'.defaultValue: 'test'.description: 'the environment')
            string(name: 'registry_url'.defaultValue: 'registry-vpc.cn-zhangjiakou.aliyuncs.com'.description: 'Mirror warehouse address')
            string(name: 'registry_ns'.defaultValue: 'mldong/java'.description: 'Mirror namespace')
            string(name: 'hostname'.defaultValue: 'c.mldong.com'.description: 'Bound domain name')	
            string(name: 'k8sCredentialsId'.defaultValue: 'ali-k8s-config'.description: 'K8S cluster configuration ID')
            string(name: 'k8sServerUrl'.defaultValue: 'https://172.26.22.121:6443'.description: 'K8S Cluster Service Address')
        }
        stages{
            stage('Check out code') {
            	steps{
                    // Check out the code
                	checkout([$class: 'GitSCM'.branches: [[name: "*/${params.branch_name}"]], 
                	doGenerateSubmoduleConfigurations: false.            	extensions:[].            	submoduleCfg:[].                userRemoteConfigs: [[
                        credentialsId: 'mldong-gitbash'.                	url: "${params.git_url}"]]])
                }
            }
            stage("Compile and package"){
            	agent { 
                    docker {
                    	image 'maven:3-alpine'
                        args "-v /root/.m2:/root/.m2 -v /root/${params.project_name}-config:/root/${params.project_name}-config"
                    }
                }
                steps{
                    // Compile package
                   	sh "mvn -B -DskipTests clean package"
                   	// Delete the config in the current directory
                   	sh "rm -rf config"
                   	// Copy the configuration file to the current workspace
                   	sh "cp -rf /root/${params.project_name}-config config"
                   	sh "pwd"
                }
            }
            stage('Build image and push to Docker repository') {
            	steps {
            		sh "pwd"
            	    // Copy the previous configuration file to the current directory
            		sh "cp -rf ${env.WORKSPACE}@2/config config"
            		// Copy the jar package generated in the previous step to the current workspace
            		sh "cp -rf ${env.WORKSPACE}@2/${params.project_name}/target/${params.project_name}.jar app.jar"
                   	// Log in to the image repository
                   	sh "docker login -u ${dockerhub_credentials_USR} -p ${dockerhub_credentials_PSW} ${params.registry_url}"
                   	// Build the image
                   	sh "docker build -t ${params.registry_url}/${params.registry_ns}/${params.project_name}:${image_tag} ."
                   	// Push the image to private server
                   	sh "docker push ${params.registry_url}/${params.registry_ns}/${params.project_name}:${image_tag}"
                   	// Delete the config in the current directory
                   	sh "rm -rf config"
                   	// Delete app.jar from current directory
                   	sh "rm -rf app.jar"
            	}
            }
            stage('Generate k8S publish template') {
            	steps {
            		// Generate a K8S publishing template
                    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"
                    // Save the file temporarily
                    stash name: "k8s.yaml".includes: "k8s.yaml"
                    // View the file
                    sh "cat k8s.yaml"
            	}
            }
            stage("kubectl apply") {
                agent {
                    docker {
                        image 'lwolf/helm-kubectl-docker'
                    }
                }
                steps {
                    withKubeConfig([credentialsId: "${params.k8sCredentialsId}".serverUrl: "${params.k8sServerUrl}"]) {
                        // Retrieve the file
                    	unstash("k8s.yaml")
                        // Publish to k8S cluster
                        sh 'kubectl apply -f k8s.yaml'
                    }
                 }
             }
       }
    }
    Copy the code

    Directions for use

    Configure the private warehouse user name and password

Configure K8S credentials

Add the Springboot configuration file to the host in the same directory as the compiler package mount.

New Task (omitted)

Build the project

The results of

Check pods details. Mirror image is the same

kubectl describe pods -n mldong-admin-test
Copy the code

summary

This article takes springboot project as an example to compile a relatively complete release pipeline. Those of you who have seen the previous one-click Deployment of SpringBoot may be more impressed by this. In my opinion, the one-click release script I wrote using shell and the Jenkins pipelined release script were implemented in much the same way. It’s just that Jenkins’ assembly line will have more pieces. And I have two versions are Shared (in fact, combined with a rapid development framework that a key deployment scripts, there are three versions), one is for the sake of learning step by step, the second is to want to learn the contents of the students more ideas, can according to oneself the circumstance of the company at the same time, choose different way of release. We do this for efficiency.

Project source code address

  • The back-end

Gitee.com/mldong/mldo…

  • The front end

Gitee.com/mldong/mldo…

Related articles

Walk you through K8S – cluster creation and Hello World

Take you through K8S-ConfigMap and persistent storage

Take you hand in hand to play K8S – complete release of an externally accessible service

Docker-compose k8S-docker advanced Dockerfile and docker-compose

K8s – One click deployment of springboot project

Take you through k8S – One-click deployment of VUE projects

Take you hand in hand to play K8S – common object details

Walk you through k8S-Jenkins installation and assembly line

Walk you through k8S-Jenkins assembly line grammar