Jenkins+K8S自動化集成和部署微服務

前言

最近在學習如何使用jenkins結合阿里雲k8s自動化集成和部署springcloud微服務和前端next.js項目,如今記錄下來分享給你們,文章有什麼不妥的地方,但願大佬們批評指正。css

DevOps CI/CD 流程

image.png

面向對象

  • 熟練使用vue或者react
  • 熟練使用SpringCloud微服務
  • 熟練使用docker容器
  • 熟練使用jenkins自動化運維工具
  • 熟練使用k8s(deployment、service、ingress)

準備工做

一、購買阿里雲ACK集羣(或者自行搭建)html

我購買的是阿里雲ACK託管版,建立集羣地址前端

注意:建立ACK集羣不收費,收費的是裏面的NAT網關、SLB負載均衡、ECS服務器等vue

二、安裝gitlabjava

這裏我以前寫了一篇阿里雲ECS搭建gitlab,安裝gitlab地址node

三、安裝jenkinsreact

這裏我以前寫了一篇阿里雲ECS搭建jenkins,安裝jenkins地址linux

四、安裝dockernginx

使用官網推薦yum 安裝比較方便,安裝以下:git

sudo yum install -y yum-utils \
  device-mapper-persistent-data \
  lvm2

sudo yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo

sudo yum install docker-ce docker-ce-cli containerd.io

系統架構

image.png

Next.js 前端開發

Next.js項目:

服務:react+next.js

服務端口:3000,

K8S:Deployment+Server+Ingress

Pod名:demo-webapp

Dockerfile

FROM node:12

# 設置工做路徑。全部的路徑都會關聯WORKDIR
WORKDIR /usr/src/app

# 安裝依賴
COPY package*.json ./
RUN npm install

# 拷貝源文件
COPY . .

# 構建應用
RUN npm run build

# 運行應用
CMD [ "npm", "start" ]

image.png

SpringCloud微服務開發

一、服務發現:SpringCloud Eureka

微服務名:demo-eureka-server

微服務端口:8761,

K8S:Deployment+Service+Ingress(由於要經過網址查看服務註冊狀況,因此要添加ingress)

Pod名:demo-eureka-server

二、服務配置:SpringCloud Config

微服務名:demo-config-server

微服務端口:8888,

K8S:Deployment+Service

Pod名:demo-config-server

三、服務認證和受權:SpringSecurity + Oauth2

微服務名:demo-auth-service

微服務端口:8901,

K8S:Deployment+Service

Pod名:demo-auth-service

四、服務網關:SpringCloud Zuul

微服務名:demo-auth-service

微服務端口:5555,

K8S:Deployment+Service+Ingress(服務網關是全部服務對外惟一入口,因此要配置ingress)

Pod名:demo-auth-service

五、編寫Dockerfile、K8S yaml

爲了方便起見,上面的微服務名和Pod名都設置相同名稱,具體的服務開發過程這裏就暫時忽略,後面有時間再寫篇搭建企業級微服務的文章吧,相關微服務的目錄結構以下所示:

image.png

注意:不一樣服務之間Dockerfile和k8s yaml文件大同小異,咱們以Eureka爲例:

Eureka Dockerfile:

FROM openjdk:8-jdk-alpine
MAINTAINER "zhangwei"<zhangwei900808@126.com>
RUN mkdir -p /usr/local/configsvr
ARG JAR_FILE
ADD ${JAR_FILE} /usr/local/configsvr/app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/usr/local/configsvr/app.jar"]
EXPOSE 8888

Eureka K8S Yaml:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/configuration-snippet: |
      rewrite ^/eureka/css/(.*)$ /eureka/eureka/css/$1 redirect;
      rewrite ^/eureka/js/(.*)$ /eureka/eureka/js/$1 redirect;
    nginx.ingress.kubernetes.io/force-ssl-redirect: 'true'
    nginx.ingress.kubernetes.io/rewrite-target: /$2
    nginx.ingress.kubernetes.io/service-weight: ''
  generation: 4
  name: <podname>-ingress
  namespace: default
spec:
  rules:
  - host: baidu.com
    http:
      paths:
      - backend:
          serviceName: <podname>-svc
          servicePort: 8761
        path: /eureka(/|$)(.*)
        pathType: ImplementationSpecific
---
apiVersion: v1
kind: Service
metadata:
  name: <podname>-svc
  namespace: default
spec:
  externalTrafficPolicy: Local
  ports:
  - nodePort: 31061
    port: 8761
    protocol: TCP
    targetPort: 8761
  selector:
    app: <podname>
  sessionAffinity: None
  type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: '1'
  generation: 1
  labels:
    app: <podname>
  name: <podname>
  namespace: default
spec:
  progressDeadlineSeconds: 600
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: <podname>
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: <podname>
    spec:
      containers:
      - env:
        - name: LANG
          value: C.UTF-8
        - name: JAVA_HOME
          value: /usr/lib/jvm/java-1.8-openjdk
        image: <imagename>
        imagePullPolicy: IfNotPresent
        name: <podname>
        ports:
        - containerPort: 8761
          protocol: TCP
        resources:
          requests:
            cpu: 250m
            memory: 512Mi
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30

注意:不一樣的策服務bootstrap.yml和application.yml文件仍是有所區別,好比下面這些:

demo-auth-service、demo-zuul-server 配置bootstrap.yml文件添加SpringCloud Config地址:

spring:
  application:
    name: authservice
  cloud:
    config:
      enabled: true
      # config的Server名
      uri: http://demo-config-server-svc:8888

demo-auth-service、demo-zuul-server、demo-config-server 配置application.yml文件添加Eureka地址:

eureka:
  instance:
    preferIpAddress: true
    hostname: demo-eureka-server-svc
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      # eureka的Server名
      defaultZone: http://demo-eureka-server-svc:8761/eureka/

Git工做流

按照Git工做流,通常咱們能夠分爲:開發環境(develop)、測試環境(release)、預生產環境(uat)和生產環境(prop),對應的分支分別是:dev、test、release、master,所以不一樣階段提交的代碼所屬分支也不相同,且dockerfile、jenkins pipline、k8s yaml文件也不相同,這個要注意下。
image.png

Jenkins DevOps CI/CD

一、視圖規範

jenkins能夠按照git工做流添加:測試視圖、預生產視圖、生產視圖,以下所示:
image.png

二、建立流水線任務

image.png
咱們先建立流水線任務並編寫pipline script腳原本建立CI/CD流水線步驟

三、編寫前端的pipline script

先編寫環境變量

environment {
  GIT_REPOSITORY="前端代碼倉庫地址"
  K8S_YAML="k8s yaml文件所在目錄"
  DOCKER_USERNAME="docker 倉庫用戶名"
  DOCKER_PWD="docker倉庫密碼"
  ALIYUN_DOCKER_HOST = '阿里雲docker倉庫域名'
  ALIYUN_DOCKER_NAMESPACE="阿里雲docker倉庫命名空間"
  ALIYUN_DOCKER_REPOSITORY_NAME="阿里雲docker倉庫命名空間下的倉庫名"
}

步驟一:克隆代碼

stage("Clone") {
    steps {
        echo "1.Clone Stage"
         // 刪除文件夾
        deleteDir()
        // 測試分支,jenkins-gitlab-ssh-hash是ssh密鑰,替換成本身的就好
        git branch: 'test', credentialsId: 'jenkins-gitlab-ssh-hash', url: "${GIT_REPOSITORY}"
        script {
            // 獲取git提交的hash值作爲docker鏡像tag
            GIT_TAG = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim()
            // 組裝成完整地址
            DOCKER_REPOSITORY = "${ALIYUN_DOCKER_HOST}/${ALIYUN_DOCKER_NAMESPACE}/${ALIYUN_DOCKER_REPOSITORY_NAME}"
            DOCKER_REPOSITORY_TAG = "${DOCKER_REPOSITORY}:${GIT_TAG}"
        }
    }
}

步驟二:代碼測試

stage("Test") {
    steps {
        echo "2.Test Stage"
    }
}

步驟三:製做docker鏡像

stage("Build") {
    steps {
        echo "3.Build Docker Image Stage"
        sh "docker build -t ${DOCKER_REPOSITORY_TAG} -f docker/Dockerfile ."
    }
}

步驟四:推送docker鏡像

stage("Push") {
    steps {
        echo "4.Push Docker Image Stage"
        //推送Docker鏡像,username 跟 password 爲 阿里雲容器鏡像服務的帳號密碼
        sh "docker login --username=${DOCKER_USERNAME} --password=${DOCKER_PWD} ${ALIYUN_DOCKER_HOST}"

        // 開始推送鏡像到阿里雲docker鏡像倉庫
        sh "docker push ${DOCKER_REPOSITORY_TAG}"
        // 刪除jenkins生成的image
        sh '''
            docker images | grep seaurl | awk '{print $3}' | xargs docker rmi -f
        '''
    }
}

步驟五:k8s部署docker鏡像

stage("Deploy") {
    steps {
        echo "5.發佈鏡像"
        // 使用sed替換k8s yaml文件中的<imagename>和<podname>
        sh "sed -i 's#<imagename>#${DOCKER_REPOSITORY_TAG}#g;s#<podname>#${POD_NAME}#g' ${K8S_YAML}"
        // 執行應用k8s yaml
        sh "kubectl apply -f ${K8S_YAML}"
    }
}

sed 語法你們能夠自行百度,這裏我使用的是#分隔,而沒有使用/分隔,緣由是分隔的字符中包含/,因此不能再用。

首先,咱們來看看前端k8s yaml文件

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod-http01
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/force-ssl-redirect: 'true'
    nginx.ingress.kubernetes.io/service-weight: ''
  generation: 3
  name: <podname>-ingress
  namespace: default
spec:
  rules:
    - host: baidu.com
      http:
        paths:
          - backend:
              serviceName: <podname>-svc
              servicePort: 3000
            path: /
            pathType: ImplementationSpecific
  tls:
    - hosts:
        - baidu.com
      secretName: <podname>-ingress
---
apiVersion: v1
kind: Service
metadata:
  name: <podname>-svc
  namespace: default
spec:
  ports:
    - port: 3000
      protocol: TCP
      targetPort: 3000
  selector:
    app: <podname>
  sessionAffinity: None
  type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: '1'
  generation: 1
  labels:
    app: <podname>
  name: <podname>
  namespace: default
spec:
  progressDeadlineSeconds: 600
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: <podname>
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    metadata:
      labels:
        app:<podname>
    spec:
      containers:
        - image: <imagename>
          imagePullPolicy: IfNotPresent
          name: <podname>
          resources:
            requests:
              cpu: 250m
              memory: 512Mi

上面的yaml文件中包含:deployment、service和ingress,ingress中配置了tls,所以可使用https來訪問域名,而且配置了nginx.ingress.kubernetes.io/force-ssl-redirect: 'true'因此能夠自動將http 跳轉到https,其中裏面的<podname>和<imagename>是要被sed替換成真實名稱和地址。

完整的pipline script腳本:

pipeline {
    agent any
    environment {
      GIT_REPOSITORY="前端代碼倉庫地址"
      K8S_YAML="k8s yaml文件所在目錄"
      DOCKER_USERNAME="docker 倉庫用戶名"
      DOCKER_PWD="docker倉庫密碼"
      ALIYUN_DOCKER_HOST = '阿里雲docker倉庫域名'
      ALIYUN_DOCKER_NAMESPACE="阿里雲docker倉庫命名空間"
      ALIYUN_DOCKER_REPOSITORY_NAME="阿里雲docker倉庫命名空間下的倉庫名"
    }
    stages {
        stage("Clone") {
            steps {
                echo "1.Clone Stage"
                 // 刪除文件夾
                deleteDir()
                // 測試分支,jenkins-gitlab-ssh-hash是ssh密鑰,替換成本身的就好
                git branch: 'test', credentialsId: 'jenkins-gitlab-ssh-hash', url: "${GIT_REPOSITORY}"
                script {
                    // 獲取git提交的hash值作爲docker鏡像tag
                    GIT_TAG = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim()
                    // 組裝成完整地址
                    DOCKER_REPOSITORY = "${ALIYUN_DOCKER_HOST}/${ALIYUN_DOCKER_NAMESPACE}/${ALIYUN_DOCKER_REPOSITORY_NAME}"
                    DOCKER_REPOSITORY_TAG = "${DOCKER_REPOSITORY}:${GIT_TAG}"
                }
            }
        }
        stage("Test") {
            steps {
                echo "2.Test Stage"
            }
        }
        stage("Build") {
            steps {
                echo "3.Build Docker Image Stage"
                sh "docker build -t ${DOCKER_REPOSITORY_TAG} -f docker/Dockerfile ."
            }
        }
        stage("Push") {
            steps {
                echo "4.Push Docker Image Stage"
                //推送Docker鏡像,username 跟 password 爲 阿里雲容器鏡像服務的帳號密碼
                sh "docker login --username=${DOCKER_USERNAME} --password=${DOCKER_PWD} ${ALIYUN_DOCKER_HOST}"
        
                // 開始推送鏡像到阿里雲docker鏡像倉庫
                sh "docker push ${DOCKER_REPOSITORY_TAG}"
                // 刪除jenkins生成的image
                sh '''
                    docker images | grep seaurl | awk '{print $3}' | xargs docker rmi -f
                '''
            }
        }
        stage("Deploy") {
            steps {
                echo "5.發佈鏡像"
                // 使用sed替換k8s yaml文件中的<imagename>和<podname>
                sh "sed -i 's#<imagename>#${DOCKER_REPOSITORY_TAG}#g;s#<podname>#${POD_NAME}#g' ${K8S_YAML}"
                // 執行應用k8s yaml
                sh "kubectl apply -f ${K8S_YAML}"
            }
        }
    }
}

點擊當即構建,以下所示:
image.png

四、編寫微服務的pipline script

先編寫環境變量

environment {
    GIT_REPOSITORY="代碼倉庫地址"
    MODULE_NAME="maven 模塊名"
    POD_NAME="k8s pod name"
    K8S_YAML="${MODULE_NAME}/src/main/k8s/eurekasvr.yaml"
    DOCKER_USERNAME="docker 倉庫用戶名"
    DOCKER_PWD="docker倉庫密碼"
    ALIYUN_DOCKER_HOST = 阿里雲docker倉庫域名'
    ALIYUN_DOCKER_NAMESPACE="阿里雲docker倉庫命名空間"
    ALIYUN_DOCKER_REPOSITORY_NAME="阿里雲docker倉庫命名空間下的倉庫名"
}

步驟一:克隆代碼

stage("Clone") {
    steps {
        echo "1.Clone Stage"
         // 刪除文件夾
        deleteDir()
        // 測試分支,jenkins-gitlab-ssh-hash是ssh密鑰,替換成本身的就好
        git branch: 'test', credentialsId: 'jenkins-gitlab-ssh-hash', url: "${GIT_REPOSITORY}"
        script {
            // 獲取git提交的hash值作爲docker鏡像tag
            GIT_TAG = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim()
            // 組裝成完整地址
            DOCKER_REPOSITORY = "${ALIYUN_DOCKER_HOST}/${ALIYUN_DOCKER_NAMESPACE}/${ALIYUN_DOCKER_REPOSITORY_NAME}"
            DOCKER_REPOSITORY_TAG = "${DOCKER_REPOSITORY}:${GIT_TAG}"
        }
    }
}

步驟二:代碼測試

stage("Test") {
    steps {
        echo "2.Test Stage"
    }
}

步驟三:製做docker鏡像

stage("Build") {
    steps {
        echo "3.Build Server"
        sh "mvn -e -U -pl ${MODULE_NAME} -am clean package -Dmaven.test.skip=true dockerfile:build -Ddockerfile.tag=${GIT_TAG} -Ddockerfile.repository=${DOCKER_REPOSITORY}"
    }
}

這裏說明一下,由於咱們使用的是maven 多模塊因此打包編譯的時候要分模塊來打包,因此要使用-pl指定模塊名,而後咱們pom.xml中使用了dockerfile-maven-plugin,以下所示:

<build>
    <plugins>
        <plugin>
            <groupId>com.spotify</groupId>
            <artifactId>dockerfile-maven-plugin</artifactId>
            <version>1.4.10</version>
            <configuration>
                <!--  指定dockerfile所在目錄-->
                <dockerfile>src/main/docker/Dockerfile</dockerfile>
                <buildArgs>
                    <!--提供參數向Dockerfile傳遞-->
                    <JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
                </buildArgs>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

步驟四:推送docker鏡像

stage("Push") {
    steps {
        echo "4.Push Docker Image Stage"
        //推送Docker鏡像,username 跟 password 爲 阿里雲容器鏡像服務的帳號密碼
        sh "docker login --username=${DOCKER_USERNAME} --password=${DOCKER_PWD} ${ALIYUN_DOCKER_HOST}"

        // 開始推送鏡像到阿里雲docker鏡像倉庫
        sh "docker push ${DOCKER_REPOSITORY_TAG}"
        // 刪除jenkins生成的image
        sh '''
            docker images | grep seaurl | awk '{print $3}' | xargs docker rmi -f
        '''
    }
}

步驟五:k8s部署docker鏡像

stage("Deploy") {
    steps {
        echo "5.發佈鏡像"
        // 使用sed替換k8s yaml文件中的<imagename>和<podname>
        sh "sed -i 's#<imagename>#${DOCKER_REPOSITORY_TAG}#g;s#<podname>#${POD_NAME}#g' ${K8S_YAML}"
        // 執行應用k8s yaml
        sh "kubectl apply -f ${K8S_YAML}"
    }
}

sed 語法你們能夠自行百度,這裏我使用的是#分隔,而沒有使用/分隔,緣由是分隔的字符中包含/,因此不能再用。

首先,咱們來看看Eureka k8s yaml文件

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/configuration-snippet: |
      rewrite ^/eureka/css/(.*)$ /eureka/eureka/css/$1 redirect;
      rewrite ^/eureka/js/(.*)$ /eureka/eureka/js/$1 redirect;
    nginx.ingress.kubernetes.io/force-ssl-redirect: 'true'
    nginx.ingress.kubernetes.io/rewrite-target: /$2
    nginx.ingress.kubernetes.io/service-weight: ''
  generation: 4
  name: <podname>-ingress
  namespace: default
spec:
  rules:
  - host: baidu.com
    http:
      paths:
      - backend:
          serviceName: <podname>-svc
          servicePort: 8761
        path: /eureka(/|$)(.*)
        pathType: ImplementationSpecific
---
apiVersion: v1
kind: Service
metadata:
  name: <podname>-svc
  namespace: default
spec:
  externalTrafficPolicy: Local
  ports:
  - nodePort: 31061
    port: 8761
    protocol: TCP
    targetPort: 8761
  selector:
    app: <podname>
  sessionAffinity: None
  type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: '1'
  generation: 1
  labels:
    app: <podname>
  name: <podname>
  namespace: default
spec:
  progressDeadlineSeconds: 600
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: <podname>
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: <podname>
    spec:
      containers:
      - env:
        - name: LANG
          value: C.UTF-8
        - name: JAVA_HOME
          value: /usr/lib/jvm/java-1.8-openjdk
        image: <imagename>
        imagePullPolicy: IfNotPresent
        name: <podname>
        ports:
        - containerPort: 8761
          protocol: TCP
        resources:
          requests:
            cpu: 250m
            memory: 512Mi
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30

上面的yaml文件中包含:deployment、service和ingress,ingress中配置了tls,所以可使用https來訪問域名,而且配置了nginx.ingress.kubernetes.io/force-ssl-redirect: 'true'因此能夠自動將http 跳轉到https,其中裏面的<podname>和<imagename>是要被sed替換成真實名稱和地址。

完整的pipline script腳本:

pipeline {
    agent any
    environment {
        GIT_REPOSITORY="代碼倉庫地址"
        MODULE_NAME="maven 模塊名"
        POD_NAME="k8s pod name"
        K8S_YAML="${MODULE_NAME}/src/main/k8s/eurekasvr.yaml"
        DOCKER_USERNAME="docker 倉庫用戶名"
        DOCKER_PWD="docker倉庫密碼"
        ALIYUN_DOCKER_HOST = 阿里雲docker倉庫域名'
        ALIYUN_DOCKER_NAMESPACE="阿里雲docker倉庫命名空間"
        ALIYUN_DOCKER_REPOSITORY_NAME="阿里雲docker倉庫命名空間下的倉庫名"
    }
    stages {
        stage("Clone") {
            steps {
                echo "1.Clone Stage"
                // 刪除文件夾
                deleteDir()
                git branch: 'test',credentialsId: '1297dda3-e592-4e70-8fb0-087a26c08db0', url: "${GIT_REPOSITORY}"
                script {
                    // 獲取git代碼tag爲docker倉庫tag
                    // GIT_TAG = sh(returnStdout: true,script: 'git describe --tags --always').trim()
                    // 獲取git提交hash作爲docker倉庫tag
                    GIT_TAG = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim()
                    DOCKER_REPOSITORY = "${ALIYUN_DOCKER_HOST}/${ALIYUN_DOCKER_NAMESPACE}/${ALIYUN_DOCKER_REPOSITORY_NAME}"
                    // docker 阿里鏡像倉庫
                    DOCKER_REPOSITORY_TAG = "${DOCKER_REPOSITORY}:${GIT_TAG}"
                }
            }
        }
        stage("Test") {
            steps {
                echo "2.Test Stage"
            }
        }
        stage("Build") {
            steps {
                echo "3.Build Server"
                sh "mvn -e -U -pl ${MODULE_NAME} -am clean package -Dmaven.test.skip=true dockerfile:build -Ddockerfile.tag=${GIT_TAG} -Ddockerfile.repository=${DOCKER_REPOSITORY}"
            }
        }
         stage("Push") {
            steps {
                echo "4.Push Docker Image Stage"
                //推送Docker鏡像,username 跟 password 爲 阿里雲容器鏡像服務的帳號密碼
                sh "docker login --username=${DOCKER_USERNAME} --password=${DOCKER_PWD} ${ALIYUN_DOCKER_HOST}"
        
                // 開始推送鏡像到阿里雲docker鏡像倉庫
                sh "docker push ${DOCKER_REPOSITORY_TAG}"
                // 刪除jenkins生成的image
                sh '''
                    docker images | grep seaurl | awk '{print $3}' | xargs docker rmi -f
                '''
            }
        }
        stage("Deploy") {
            steps {
                echo "5.發佈鏡像"
                sh "sed -i 's#<dockerrepository>#${DOCKER_REPOSITORY_TAG}#g;s#<podname>#${POD_NAME}#g' ${K8S_YAML}"
                sh "kubectl apply -f ${K8S_YAML}"
            }
        }
    }
}

點擊當即構建,以下所示:
image.png

查看k8s是否成功

能夠經過命令

kubectl get deploy
kubectl get pod
kubectl get svc
kubectl get ingress

image.png

還能夠查看pod日誌,對其成功或失敗進行分析:

kubectl logs podname

訪問Eureka

image.png

postman訪問微服務接口地址

能夠經過postman接口訪問對外的zuul地址,查看是否能夠認證經過:
image.png

瀏覽器訪問Web頁面地址

能夠經過next.js的部署地址,查看是否部署成功:
image.png

總結

一、jenkins pipline script腳本和Dockerfile寫法網上各式各樣,你們找到一個符合標準的就好
二、kubectl apply -f 的做用是:若是沒有建立deployment就會建立,不然就更新
三、微服務k8s yaml文件中Service要設置type: NodePort不然,微服務間不能通訊
四、jenkins 編譯微服務的maven模塊要用到-pl 和 dockerfile-maven-plugin
五、微服務若是要用k8s ingress要設置https,以及http自動跳轉到https

引用

JenkinsPipeline部署一個Kubernetes 應用
採用jenkins pipeline實現自動構建並部署至k8s
Configuring-CI-CD-on-Kubernetes-with-Jenkins
spring-k8s
jenkins pipeline 自動構建並部署至k8s
微服務實戰(一)基於OAUTH2.0統一認證受權的微服務基礎架構
使用cert-manager申請免費的HTTPS證書
SPRINGBOOT利用SPRING.PROFILES.ACTIVE=@SPRING.ACTIVE@不一樣環境下靈活切換配置文件
https://kuboard.cn/learning/k8s-practice/ocp/eureka-server.html#%E6%9F%A5%E7%9C%8B%E9%83%A8%E7%BD%B2%E7%BB%93%E6%9E%9C
kubernetes部署微服務spring cloud的簡單例子
k8s-nginx-ingress eureka二級路徑轉發的問題