I. Introduction to Pipeline

Pipeline is a set of plugins officially provided by Jenkins, which can be used to implement and integrate continuous delivery in Jenkins. Users can take advantage of many features of Pipeline:

Code: Pipelines are implemented in code, usually with source control checked, enabling the team to edit, review, and iterate over their delivery pipeline. Durability: Pipelines can survive planned and unplanned restarts by Jenkins Master. Pausable: The pipeline has the option to stop and wait for human input or approval before continuing the pipeline run. Multifunctional: Pipelines support complex practical CD requirements, including the ability to parallel fork/join, loop, and perform work. Extensible: The Pipeline plug-in supports custom extensions of its DSL and multiple options for integration with other plug-ins

Two, K8S integration/deployment/delivery

3. Create a GitLab test project (simple code tests found online)

1. Test code

The code structure

[root@node2 test1]# tree .├ ─ ├─ Java ├─ Java ├─ Java ├─ Java ├─ Java ├─ JavaCopy the code

HelloWorld.java

package hello; public class HelloWorld { public static void main(String[] args) { Greeter greeter = new Greeter(); System.out.println(greeter.sayHello()); }}Copy the code

Greeter.java

package hello;

public class Greeter {
    public String sayHello() {
        return "Hello world!"; }}Copy the code

pom.xml

<? xml version="1.0" encoding="UTF-8"? > <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> < modelVersion > 4.0.0 < / modelVersion > < groupId > org. Springframework < / groupId > < artifactId > gs - maven < / artifactId > <packaging>jar</packaging> <version>0.1.0</version> <build> <plugins> <plugin> . < groupId > org, apache maven plugins < / groupId > < artifactId > maven - shade - plugin < / artifactId > < version > 2.1 < / version > <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>hello.HelloWorld</mainClass>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

Copy the code

2. Git test project

4. Jenkins configuration

1. Plug-in installation

Install Git, GitLab Plugin, GitLab Hook Plugin, GitLab API Plugin, Pipeline and Kubernetes Plugin.

2. Configure Kubernetes in Jenkins

3. Simple test (Create a Pipline project)

The Pipline script for the test

def label = "mypod-${UUID.randomUUID().toString()}"
podTemplate(label: 'label', cloud: 'kubernetes') {
    node('label') {
        stage('Run shell') {
            sh 'echo hello world'}}}Copy the code

4. Configure gi credentials in pipline

Create credentials. Username is the account of Gitlab, and password is the password of gitlab account.

Git credentials in Pipline

6, rebuild jnLP-slave mirror (add MAVEN)

mkdir myjenkins
cdMyjenkins/wget HTTP: / / https://mirrors.tuna.tsinghua.edu.cn/apache/maven/maven-3/3.5.4/binaries/apache-maven-3.5.4-bin.tar.gz Tar xf apache-maven-3.5.4-bin.tar.gz [root@node2 myjenkins]# cat Dockerfile The FROM Jenkins/JNLP slave: 3.27 1 LABEL maintainer ="[email protected]"
ENV MAVEN_HOME /usr/local/maven
ENV PATH=$PATH:$MAVEN_HOME/ bin COPY apache maven - 3.5.4 / usr /local/maven
[root@node2 myjenkins]# docker build -t myjnlP-slave :1.0./
Copy the code

7. Configure the mirror repository (I used Aliyun)

Mysql > alter dokcer group GID = 10000

groupmod  -g10000  docker
chown root.docker /var/run/docker.sock
Copy the code

9. Configure the interaction between Gitlab and Jenkins (I used Webhook mode and set the submission tag to trigger the build)

10. Modify the Pipline script so that after Jenkins build, the image can be directly created and submitted to the mirror warehouse

Pipline script

def label = "mypod-${UUID.randomUUID().toString()}"
def registry = "registry-vpc.cn-hongkong.aliyuncs.com"
def app_name = "javatest"
def namespace = "aliyun-zhang"
def username = "xxxxxxxxxxxxxxxxxx"
def regpass = "xxxxxxxxxxxxxxxxxxx"


podTemplate(label: 'label', cloud: 'kubernetes', containers: [
    containerTemplate(
        name: 'jnlp', 
        image: 'myjnlp - slave: 1.0'
    ),
],
  volumes: [
    hostPathVolume(mountPath: '/var/run/docker.sock', hostPath: '/var/run/docker.sock'),
    hostPathVolume(mountPath: '/usr/bin/docker', hostPath: '/usr/bin/docker')
],)
{
    node('label') {
        stage('Task') {
            stage('Pull code') {
                git credentialsId: 'gitlab-auth', url: 'http://mygitlab-gitlab-ce.default.svc.cluster.local/root/test1.git'
                def mytag = sh returnStdout: true, script: 'git describe --always --tag'
                sh "git checkout -b $mytag"
            }
            stage('Compile package') {
                sh "mvn clean package -Dmaven.test.skip=true"
            }
            
            stage('Build an upload image') {
                def mytag = sh returnStdout: true, script: 'git describe --always --tag'
                def image_name = "${app_name}:${mytag}".minus("\n")
                sh label: ' ', script: ' '' echo \'
                    FROM tomcat:latest 
                    ADD pom.xml /usr/local/tomcat/webapps/ 
                    \' Dockerfile '' ' 
                    
                sh """ docker build -t "${registry}/${namespace}/${image_name}" ./
                    docker login -u ${username} -p \"${regpass}\" ${registry}
                    docker push ${registry}/${namespace}/${image_name}
                    
                """}}}}Copy the code

Jenkins builds tests and reviews

5. Automatically deploy to the K8S cluster

Jenkins download Kubernetes Continuous

Deploy the plug-in (official document: plugins. Jenkins. IO/kubernetes -…

2. Configure kubeconFig credentials

Add kubeconfig file, I chose to paste the file content directly (master side. Kube /config file)

3. Record the voucher ID value

4, create a deploy.yaml file and upload it to git for your project

[root@k8s-m ~]# cat java-deploy.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mydeploy
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      test_node: k8s-node
  template:
    metadata:
      labels:
        test_node: k8s-node
    spec:
      containers:
      - name: myjava-server
        image: tomcat:latest
        ports:
        - name: http
          containerPort: 8080
Copy the code

5. Change the Pipline script content

def label = "mypod-${UUID.randomUUID().toString()}"
def registry = "registry-vpc.cn-hongkong.aliyuncs.com"
def app_name = "javatest"
def namespace = "aliyun-zhang"
def username = "xxxxxxxxxxxx"
def regpass = "xxxxxxxxx"
def k8s_auth = "5ce0993e-e2e9-4126-a910-2acd0a77fefb"


podTemplate(label: 'label', cloud: 'kubernetes', containers: [
    containerTemplate(
        name: 'jnlp', 
        image: 'myjnlp - slave: 1.0'
    ),
],
  volumes: [
    hostPathVolume(mountPath: '/var/run/docker.sock', hostPath: '/var/run/docker.sock'),
    hostPathVolume(mountPath: '/usr/bin/docker', hostPath: '/usr/bin/docker')
],)
{
    node('label') {
        stage('Task') {
            stage('Pull code') {
                git credentialsId: 'gitlab-auth', url: 'http://mygitlab-gitlab-ce.default.svc.cluster.local/root/test1.git'
                def mytag = sh returnStdout: true, script: 'git describe --always --tag'
                sh "git checkout -b $mytag"
                echo "mytag $mytag ${mytag}-"
            }
            stage('Compile package') {
                sh "mvn clean package -Dmaven.test.skip=true"
            }
            
            stage('Build an upload image') {
                def mytag = sh returnStdout: true, script: 'git describe --always --tag'
                def image_name = "${app_name}:${mytag}".minus("\n")
                
                echo "image_name $image_name"
                sh label: ' ', script: ' '' echo \'
                    FROM tomcat:latest 
                    ADD target/*.jar /usr/local/tomcat/webapps/ 
                    \' Dockerfile '' ' 
                    
                sh """ docker build -t "${registry}/${namespace}/${image_name}" ./
                    docker login -u ${username} -p \"${regpass}\" ${registry}
                    docker push ${registry}/${namespace}/${image_name}
                    
                """
            }
             stage('Deploy to K8S'){
                def mytag = sh returnStdout: true, script: 'git describe --always --tag'
                def image_name = "${app_name}:${mytag}".minus("\n")
                sh """
                sed -i 's#tomcat:latest#${registry}/${namespace}/${image_name}#' java-deploy.yaml
                """
                kubernetesDeploy configs: 'java-deploy.yaml', kubeconfigId: "${k8s_auth}"}}}}Copy the code

6. Build tests

I have configured Jenkins and GitLab’s Webhook configuration, which will be automatically built to deploy to K8S cluster after submitting tag

test

[root@node2 test1]# echo 123 >>README.md 
[root@node2 test1]# git commit -a -m '123'
[master bda4c6f] 123
 1 file changed, 1 insertion(+), 1 deletion(-)
[root@node2 test1]10.0 # git tag
[root@node2 test1]Git push origin master 10.0
Username for 'http://10.101.58.237': root
Password for 'http://[email protected]': Counting objects: 5, done. Delta compression using up to 2 threads. Compressing objects: 100% (2/2), done. Writing objects: 100% (3/3), 347 bytes | 0 bytes/s, done. Total 3 (delta 0), reused zero (0) delta To http://10.101.58.237/root/test1.git da0fbc3.. Bda4c6f master-master * [new tag] 10.0-10.0Copy the code

Jenkins construction process

K8s cluster view

[root@k8s-m ~]# kubectl get deploy mydeploy
NAME       READY   UP-TO-DATE   AVAILABLE   AGE
mydeploy   2/2     2            2           64s
[root@k8s-m ~]# kubectl get pod  
NAME                                   READY   STATUS    RESTARTS   AGE
mydeploy-746bb8db64-4fpvz              1/1     Running   0          69s
mydeploy-746bb8db64-pp7tw              1/1     Running   0          69s

[root@k8s-m ~]# kubectl get pod mydeploy-746bb8db64-4fpvz -o yaml|grep image:
  - image: registry-vpc.cn-hongkong.aliyuncs.com/aliyun-zhang/javatest:10.0
    image: registry-vpc.cn-hongkong.aliyuncs.com/aliyun-zhang/javatest:10.0
Copy the code

Version rollback

The rollback based on the K8S image is still a relatively simple rollback of the previous version

 kubectl rollout undo deployment/deploy-name
Copy the code

View historical version information

Check the Deployment upgrade history
[root@k8s-m ~]# kubectl rollout history deployment/mydeploy
deployment.extensions/mydeploy 
REVISION  CHANGE-CAUSE
3         none
4         none

See the historical version for more detailed upgrade information
[root@k8s-m ~]# kubectl rollout history deployment/mydeploy --revision=3
deployment.extensions/mydeploy with revision # 3Pod Template: Labels: pod-template-hash=746bb8db64 test_node=k8s-node Containers: myjava-server: Image: Registry-vpc.cn-hongkong.aliyuncs.com/aliyun-zhang/javatest:10.0 Port: 8080 / TCP Host Port: 0 / TCP Environment: none Mounts: none Volumes: noneCopy the code

Roll back the specified version

kubectl rollout undo deployment/mydeploy --to-revision=3
Copy the code

Rollback specified version 2

Modify the mirror directly in delpoy

Deployment upgrade Strategy

1, the introduction

There are two types of strategy in Deployment, namely, Conforms and RollingUpdate. RollingUpdate is the default strategy and RollingUpdate also has corresponding upgrade strategy. If the strategy is not set properly, The maximum number of pods that are Unavailable is 25% by default. The maximum number of pods that can be exceeded by the preset number during the Max Surge upgrade. The default value is 25%. MinReadySeconds Specifies the time for waiting for the container to start. The unit is 0, and the container is executed immediately after the container is started

2. View the deploy update policy

[root@k8s-m recreate]# kubectl explain deploy.spec.strategy.type
KIND:     Deployment
VERSION:  extensions/v1beta1

FIELD:    type string

DESCRIPTION:
     Type of deployment. Can be "Recreate" or "RollingUpdate". Default is
     RollingUpdate.
Copy the code

3. Concepts strategy testing

Conclusion: An approach to Concrete stops all existing versions before deploying the new version

[root@k8s-m ~]# kubectl get pod -wNAME READY STATUS RESTARTS AGE my-app-bb9cc7597-dn5bv 1/1 Running 0 3m36s my-app-bb9cc7597-gqfx4 1/1 Running 0 3m36s my-app-bb9cc7597-p4dfb 1/1 Running 0 3m36s my-app-bb9cc7597-p4dfb 1/1 Terminating 0 3m44s my-app-bb9cc7597-dn5bv 1/1 Terminating 0 3m44s my-app-bb9cc7597-gqfx4 1/1 Terminating 0 3m44s my-app-bb9cc7597-p4dfb 0/1 Terminating 0 3m45s my-app-bb9cc7597-gqfx4 0/1 Terminating 0 3m45s my-app-bb9cc7597-dn5bv 0/1 Terminating 0 3m45s my-app-bb9cc7597-p4dfb 0/1  Terminating 0 3m57s my-app-bb9cc7597-p4dfb 0/1 Terminating 0 3m57s my-app-db47b56bf-kwd2c 0/1 Pending 0 0s my-app-db47b56bf-kwd2c 0/1 Pending 0 0s my-app-db47b56bf-xkqdz 0/1 Pending 0 0s my-app-db47b56bf-5v4r5 0/1 Pending 0 0s my-app-db47b56bf-xkqdz 0/1 Pending 0 0s my-app-db47b56bf-kwd2c 0/1 ContainerCreating 0 0sCopy the code

4. RollingUpdate policy test

Conclusion: Release new versions one by one in a rolling update, which can be defined as how many pods are added before being removed, or as adding before removing.

[root@k8s-m ~]# kubectl get pod -wNAME READY STATUS RESTARTS AGE my-app-db47b56bf-2c2c6 1/1 Running 0 19s my-app-db47b56bf-k7k5z 1/1 Running 0 19s my-app-db47b56bf-mclj8 1/1 Running 0 19s my-app-bb9cc7597-hgz6r 0/1 Pending 0 0s my-app-bb9cc7597-hgz6r 0/1 Pending 0 0s  my-app-bb9cc7597-hgz6r 0/1 ContainerCreating 0 1s my-app-bb9cc7597-hgz6r 0/1 ContainerCreating 0 1s my-app-bb9cc7597-hgz6r 0/1 Running 0 5s my-app-bb9cc7597-hgz6r 1/1 Running 0 6s my-app-db47b56bf-mclj8 1/1 Terminating 0  29s my-app-bb9cc7597-84ngs 0/1 Pending 0 0s my-app-bb9cc7597-84ngs 0/1 Pending 0 0s my-app-bb9cc7597-84ngs 0/1 ContainerCreating 0 1s my-app-bb9cc7597-84ngs 0/1 ContainerCreating 0 2s my-app-db47b56bf-mclj8 0/1 Terminating 0 31s my-app-db47b56bf-mclj8 0/1 Terminating 0 34s my-app-db47b56bf-mclj8 0/1 Terminating 0 34s my-app-bb9cc7597-84ngs 0/1 Running 0 6s my-app-bb9cc7597-84ngs 1/1 Running 0 7sCopy the code
[root@k8s-m recreate]# kubectl explain deploy.spec.strategy.rollingUpdate
KIND:     Deployment
VERSION:  extensions/v1beta1

RESOURCE: rollingUpdate Object

DESCRIPTION:
     Rolling update config params. Present only if DeploymentStrategyType =
     RollingUpdate.

     Spec to control the desired behavior of rolling update.

FIELDS:
   maxSurge    string
     The maximum number of pods that can be scheduled above the desired number
     of pods. Value can be an absolute number (ex: 5) or a percentage of desired
     pods (ex: 10%). This can not be 0 if MaxUnavailable is 0. Absolute number
     is calculated from percentage by rounding up. By default, a value of 1 is
     used. Example: when this is set to 30%, the new RC can be scaled up
     immediately when the rolling update starts, such that the total number of
     old and new pods donot exceed 130% of desired pods. Once old pods have been killed, new RC can be scaled up further, ensuring that total number of pods running at any time during the update is at most 130% of desired pods. maxUnavailable  string The maximum number of pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). Absolute number is calculated from percentage by rounding down. This can not be 0if MaxSurge is 0. By default, a fixed value of 1 is used.
     Example: when this is set to 30%, the old RC can be scaled down to 70% of
     desired pods immediately when the rolling update starts. Once new pods are
     ready, old RC can be scaled down further, followed by scaling up the new
     RC, ensuring that the total number of pods available at all times during
     the update is at least 70% of desired pods.
Copy the code

5. Other update strategies (Canary, etc.)

zhuanlan.zhihu.com/p/55964678