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