六、Kubernetes CICD之旅

1、概述

? 在前面的章節(jié)中我們已經(jīng)演示了不少案例與各種組件的介紹與使用,我們也實戰(zhàn)搭建了項目。通過K8S的幫助,我們可以很方便的部署項目,但還不是很完美。如果我們部署的是自己的項目,而我們的項目又是要經(jīng)常改動的,這就意味著我們需要經(jīng)常進行 打包、上傳、重啟、測試等,這些都是重復性的工作,一次兩次還好,次數(shù)多了也煩人。所以下面要講的 CI/CD 就是來幫我們解放雙手,擺脫這些重復性的工作!

1.1、CI/CD是什么?

  • CI/CD 是一種通過在應用開發(fā)階段引入 自動化 來頻繁向客戶交付應用的方法。

  • CI/CD 的核心概念是持續(xù)集成、持續(xù)交付和持續(xù)部署。

  • CI/CD 主要針對在集成新代碼時所引發(fā)的問題。

  • CI/CD 可讓持續(xù)自動化和持續(xù)監(jiān)控貫穿于應用的整個生命周期(從集成和測試階段,到交付和部署)。

  • 這些關聯(lián)的事務通常被統(tǒng)稱為 “CI/CD 管道”,由開發(fā)和運維團隊以敏捷方式協(xié)同支持。

1.2、 CI 和 CD 有什么區(qū)別?

  • CI/CD 中的 “CI” 始終指持續(xù)集成,它屬于開發(fā)人員的自動化流程。
  • 成功的 CI 意味著應用代碼的新更改會定期構建、測試并合并到共享存儲庫中。
  • 該解決方案可以解決在一次開發(fā)中有太多應用分支,從而導致相互沖突的問題。
  • CI/CD 中的“CD”指的是持續(xù)交付和/或持續(xù)部署,這些相關概念有時會交叉使用。
  • 兩者都事關管道后續(xù)階段的自動化,但它們有時也會單獨使用,用于說明自動化程度。

更多概念可以到 紅帽 看官方介紹: https://www.redhat.com/zh/topics/devops/what-is-ci-cd

下面這張圖就相對完整的介紹了本章節(jié)要進行的工作:

  • 開發(fā)手動提交代碼到git倉庫
  • 自動拉取代碼
  • 自動進行Maven構建、代碼檢查、單元測試
    • 這個步驟在生產(chǎn)環(huán)境一般不會做自動構建,因為公司可能進行代碼檢查,確認無誤后由QA手動進行部署
    • 本章節(jié)只進行Maven構建,代碼檢查和單元測試需要集成其他組件,讀者可以自行了解
  • 自動build鏡像、上傳鏡像至鏡像倉庫
  • 自動拉取鏡像進行部署
image.png

2、環(huán)境準備

  • 準備一個項目
  • 準備一個 Git 倉庫
    • 可以是自己搭建的也可以是GitHub或者碼云都可以
  • 準備一個鏡像倉庫
    • 這里使用阿里云的鏡像倉庫
  • 準備一個安裝了 Kubernetes 的機器
    • 直接使用之前搭建好的 K8S 集群
    • 安裝 Java
    • 安裝 Maven
    • 安裝 Git
    • 安裝 Jenkins
      • Jenkins必須在k8s集群中,因為后面需要在jenkins的目錄下創(chuàng)建文件執(zhí)行K8S的命令
      • 其他環(huán)境在這臺機器安裝的原因在于Jenkins需要依賴這些環(huán)境

2.1、環(huán)境搭建

  • 安裝 Java

    • 下載 Java 安裝包上傳并解壓到服務器

    • 配置環(huán)境變量

      • 采用 profile.d 目錄設置環(huán)境變量,好處在于想刪掉該環(huán)境可以直接刪除文件,無需修改配置文件
      # 1、配置環(huán)境變量
      [root@worker01-kubeadm-k8s profile.d]# pwd
      /etc/profile.d
      [root@worker01-kubeadm-k8s profile.d]# vi java.sh
      
      export JAVA_HOME=/root/develop/java/jdk1.8.0_181
      export JRE_HOM=$JAVA_HOME/jre
      export CLASSPATH=$JAVA_HOME/lib/
      
      export PATH=$PATH:$JAVA_HOME/bin
      
      # 2、賦予權限
      [root@worker01-kubeadm-k8s profile.d]# chmod 755 ./java.sh
      
      # 3、編譯文件
      [root@worker01-kubeadm-k8s profile.d]# source ./java.sh
      
      # 4、測試
      [root@worker01-kubeadm-k8s profile.d]# java -version
      java version "1.8.0_181"
      Java(TM) SE Runtime Environment (build 1.8.0_181-b13)
      Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)
      
  • 安裝 Maven

    • 下載 Maven 安裝包上傳并解壓到服務器

    • 配置環(huán)境變量

      # 1、配置環(huán)境變量
      [root@worker01-kubeadm-k8s profile.d]# vi mvn.sh
      
      export MAVEN_HOME=/root/develop/maven/apache-maven-3.6.3
      export PATH=$PATH:$MAVEN_HOME/bin
      
      # 2、賦予權限
      [root@worker01-kubeadm-k8s profile.d]# chmod 755 ./mvn.sh
      
      # 3、編譯文件
      [root@worker01-kubeadm-k8s profile.d]# source ./mvn.sh
      
      # 4、測試
      [root@worker01-kubeadm-k8s profile.d]# mvn -v
      Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f)
      Maven home: /root/develop/maven/apache-maven-3.6.3
      Java version: 1.8.0_181, vendor: Oracle Corporation, runtime: /root/develop/java/jdk1.8.0_181/jre
      Default locale: en_US, platform encoding: UTF-8
      OS name: "linux", version: "3.10.0-1062.18.1.el7.x86_64", arch: "amd64", family: "unix"
      
    • 配置本地倉庫路徑、阿里云鏡像

      # 1、本地倉庫路徑,改成自己的
      <localRepository>/root/develop/maven/repo</localRepository>
          
      # 2、配置阿里云鏡像
      <mirror>
          <id>aliyunmaven</id>
          <mirrorOf>*</mirrorOf>
          <name>阿里云公共倉庫</name>
          <url>https://maven.aliyun.com/repository/public</url>
      </mirror>
      
  • 安裝 Git

    • 下載安裝

      # 1、安裝 Git
      [root@worker01-kubeadm-k8s ~]# yum install git
      
      # 2、測試
      [root@worker01-kubeadm-k8s ~]# git --version
      git version 1.8.3.1
      
    
    + 配置賬號
    
      ```ruby
      [root@worker01-kubeadm-k8s ~]# git config --global user.name "Sunny"
      [root@worker01-kubeadm-k8s ~]# git config --global user.email "yzy_zhaoyang@163.com"
      [root@worker01-kubeadm-k8s ~]# ssh-keygen -t rsa -C "yzy_zhaoyang@163.com"
      
      # 出現(xiàn)需要輸入密碼的地方可以設置自己的ssh密碼, 也可以直接回車表示不設置密碼
      Generating public/private rsa key pair.
      Enter file in which to save the key (/root/.ssh/id_rsa):
      Enter passphrase (empty for no passphrase):
      Enter same passphrase again:
      Your identification has been saved in /root/.ssh/id_rsa.
              
      # 這里的路徑文件指的是公鑰,我們要打開這個文件將公鑰填到 Git 倉庫
      Your public key has been saved in /root/.ssh/id_rsa.pub.
      The key fingerprint is:
      ae:ca:9b:84:t5:3e:b7:as:98:51:d1:77:31:34:0e:tt yzy_zhaoyang@163.com
      The key's randomart image is:
      +--[ RSA 2048]----+
      |  ...o           |
      | . E. o          |
      |o .. o .         |
      |.o  . o          |
      |.  .    S        |
      |  ..   .         |
      | ....   .        |
      |.o=+.. .         |
      |.=+o*o.          |
      +-----------------+
    

2.2、準備項目

image.png
  • 上傳到 Git 倉庫

    image.png

2.3、搭建 Jenkins

  • 前情提要

    Jenkins 官網(wǎng):https://jenkins.io/

    入門指南:https://jenkins.io/zh/doc/pipeline/tour/getting-started/

    • 下載并上傳 Jenkins 到服務器

    • 啟動 Jenkins

      #以后臺啟動方式啟動 Jenkins,設置端口為 8088
      [root@worker01-kubeadm-k8s jenkins]#  [root@sunny jenkins]# nohup java -jar jenkins.war --httpPort=8088 &
      
      # 查看啟動日志
      [root@worker01-kubeadm-k8s jenkins]#  tail -f nohup.out
      Running from: /root/jenkins/jenkins.war
      webroot: $user.home/.jenkins
      2020-04-16 15:20:49.849+0000 [id=1]     INFO    org.eclipse.jetty.util.log.Log#initialized: Logging initialized @753ms to org.eclipse.jetty.util.log.JavaUtilLog
      
      # ... 省略 ...
      
      *************************************************************
      *************************************************************
      *************************************************************
      
      Jenkins initial setup is required. An admin user has been created and a password generated.
      Please use the following password to proceed to installation:
      
      # 這是進入 Jenkins 管理頁面所需要的密碼
      f9025b52a4824997b09cb62d5c89f7cc
      
      # 這是存放密碼的文件
      This may also be found at: /root/.jenkins/secrets/initialAdminPassword
      
      *************************************************************
      *************************************************************
      *************************************************************
      
image.png

2.3.1、配置 Jenkins

  • 安裝推薦的插件

    image.png

等待安裝即可,需要的時間比較久

也可以先點推薦安裝,然后刷新頁面選擇跳過安裝,之后手動下載插件安裝,這樣會更快

如果跳過,先截圖保存一下推薦插件的列表,后面手動安裝要去搜索的

  • 創(chuàng)建用戶

    username: sunny
    password: sunny
    
    image.png
  • 安裝插件

    這里說的是推薦插件安裝完后還需要安裝的一些插件,如果你選擇了跳過安裝,那要先記好它推薦了哪些插件,有些插件是必要的

    • 中文插件
      • Locale
      • Localization: Chinese (Simplified)
      • Localization Support
    • git插件
      • GitHub / Gitee
      • Gitlab Hook
      • Gitlab Plugin
  • 配置Java、Maven、Git路徑

    • Manage Jenkins — Global Tool Configuration

    • 配置機器中的路徑

      image.png

2.3.2、鏡像倉庫與Kubernetes集群

  • 鏡像倉庫采用國內(nèi)的阿里云鏡像倉庫

  • Kubernetes 集群直接采用我們之前章節(jié)中已經(jīng)搭建好的 Kubernetes 集群即可。

3、Pipeline任務

我們一個步驟一個步驟的演示,從最開始的拉取代碼,慢慢延伸到最終的CICD!

3.1 拉取項目代碼

Jenkins要實現(xiàn)自動拉取代碼,需要安裝Git相關插件,以及要到Git倉庫去進行一些配置,插件之前都已經(jīng)安裝了,接下來就演示一下Jenkins的配置。

  • 創(chuàng)建任務

    image.png
  • 創(chuàng)建流水線任務

    image.png
  • 編寫pipeline

    注意這里要勾選上,保存webhook的鏈接,后面配置自動拉取時要用到

    image.png
image.png
node {
   // Pull
   stage('Pull') { //stage表示一個任務
      //這里是任務的內(nèi)容
      //因為我們的機器已經(jīng)生成了秘鑰且與Gieee進行了綁定,所以無需輸入賬號密碼就可以進行拉取代碼
      git 'https://gitee.com/suny95/springboot-demo-k8s.git'
   }
}

配置完成后點擊保存

  • 構建任務

    image.png

構建完成后會顯示綠色,構建失敗是紅色,可以去查看錯誤信息

image.png

這里是Jenkins工作目錄:/root/.jenkins/workspace目錄

代碼是拉取到這個目錄下的

# Jenkins工作目錄
[root@worker01-kubeadm-k8s workspace]# pwd
/root/.jenkins/workspace
[root@worker01-kubeadm-k8s workspace]# ll
total 0
drwxr-xr-x. 4 root root 62 Apr 18 14:37 springboot-k8s-task

# 新建的任務目錄
[root@worker01-kubeadm-k8s workspace]# cd springboot-k8s-task/
[root@worker01-kubeadm-k8s springboot-k8s-task]# ll
total 4
-rw-r--r--. 1 root root 1277 Apr 18 14:37 pom.xml
drwxr-xr-x. 3 root root   18 Apr 18 14:37 src

3.2 Maven自動編譯

修改之前編寫好的流水線任務,增加一個Stage用來做Maven自動編譯

  • 修改Pipeline腳本內(nèi)容

    node {
       // Pull
       stage('Pull') { //stage表示一個任務
          //這里是任務的內(nèi)容
          //因為我們的機器已經(jīng)生成了秘鑰且與Gieee進行了綁定,所以無需輸入賬號密碼就可以進行拉取代碼
          git 'https://gitee.com/suny95/springboot-demo-k8s.git'
       }
       
       //Maven
       stage('AutoCompile') {
           sh "mvn clean package"
       }
    }
    
  • 構建任務

    開始構建任務后,可以通過Console Output監(jiān)控當前任務執(zhí)行情況

    image.png
image.png
# 再次查看目錄,發(fā)現(xiàn)已經(jīng)成功編譯出 target 目錄了
[root@worker01-kubeadm-k8s springboot-k8s-task]# ll
total 4
-rw-r--r--. 1 root root 1277 Apr 18 14:37 pom.xml
drwxr-xr-x. 3 root root   18 Apr 18 14:37 src
drwxr-xr-x. 6 root root  181 Apr 18 14:56 target

到這里為止,手動構建的方式已經(jīng)完成, 下面將要開始配置自動構建

3.3 Git Push 觸發(fā) Jenkins 自動構建

當用戶進行git push提交代碼到 GitHub / Git EE 時,能夠通知 jenkins 自動構建

注意: Jenkins 的 ip 一定要是 Git EE 能夠訪問到的地址

我這里由于是本地搭建的虛擬機,就不做演示了,百度搜一下有很多的教程可以參考

3.4 build 與 push 鏡像

經(jīng)過前面的演示,現(xiàn)在已經(jīng)可以獲取到代碼,并且用maven進行構建了,最終拿到一個target/xxx.jar

現(xiàn)在我們要演示Docker的鏡像構建與Push鏡像到鏡像倉庫!

  • 準備執(zhí)行文件

    • 到 Jenkins 的工作目錄

      • cd /root/.jenkins/workspace
    • 創(chuàng)建 .sh 執(zhí)行文件

      # 創(chuàng)建專門存放腳本的目錄
      [root@worker01-kubeadm-k8s workspace]# mkdir scripts
      [root@worker01-kubeadm-k8s workspace]# cd scripts/
      
      # 編寫執(zhí)行文件
      [root@worker01-kubeadm-k8s scripts]# vi springboot-demo-k8s-build-image.sh
      
      # ================== 執(zhí)行文件內(nèi)容 ======================
      # 進入到springboot-k8s-task目錄
      cd ../springboot-k8s-task
      
      # 編寫Dockerfile文件, 這里也可以先在項目里寫好
      
      cat <<EOF > Dockerfile
      FROM openjdk:8-jre-alpine
      COPY target/springboot-demo-0.0.1-SNAPSHOT.jar /springboot-demo.jar
      ENTRYPOINT ["java","-jar","/springboot-demo.jar"]
      EOF
      
      echo "Dockerfile created successfully!"
      
      # 基于指定目錄下的Dockerfile構建鏡像
      # 注意 zhao_yang 這個命名空間是公開的,如果是私有的,還需要配置K8S的認證
      docker build -t registry.cn-hangzhou.aliyuncs.com/zhao_yang/springboot-demo-k8s:v1.0 .
      
      # 登錄docker賬號
      # 注意: 如果密碼不能開放的話,可以先手動在機器上登錄一次,那這里就無需再次登錄了
      docker login --username=用戶名 --password=密碼 registry.cn-shanghai.aliyuncs.com
      
      # push鏡像
      docker push registry.cn-hangzhou.aliyuncs.com/zhao_yang/springboot-demo-k8s:v1.0
      # ================== 執(zhí)行文件內(nèi)容 ======================
      
      # 增加執(zhí)行權限
      [root@worker01-kubeadm-k8s scripts]# chmod +x ./springboot-demo-k8s-build-image.sh
      
  • 修改任務的Pipeline腳本

    node {
       // Pull
       stage('Pull') { //stage表示一個任務
          //這里是任務的內(nèi)容
          //因為我們的機器已經(jīng)生成了秘鑰且與Gieee進行了綁定,所以無需輸入賬號密碼就可以進行拉取代碼
          git 'https://gitee.com/suny95/springboot-demo-k8s.git'
       }
       
       //Maven
       stage('AutoCompile') {
           sh "mvn clean package"
       }
       
       //增加任務,執(zhí)行腳本文件
       stage('Build And Push Image') { 
          sh "/root/.jenkins/workspace/scripts/springboot-demo-k8s-build-image.sh"
       }
    }
    
  • 構建任務,監(jiān)控輸出

    image.png
    image.png

build 鏡像與 push 鏡像至鏡像倉庫 都已成功!!!

3.1.5 Kubernetes 拉取鏡像運行

這個過程需要提前準備的也就是image鏡像和ingress,image剛才我們都已經(jīng)上傳到阿里云鏡像倉庫了,ingress我們在之前也準備過了,如果沒有ingress環(huán)境的,可以去看前面的 kubernetes 網(wǎng)絡模型 ,里面有安裝ingress的流程!

  • 編寫 YAML 文件

    YAML文件可以寫到項目中,也可以直接在機器上創(chuàng)建

    • vi /root/.jenkins/workspace/scripts/springboot-demo-k8s.yaml
    # 以Deployment部署Pod
    apiVersion: apps/v1
    kind: Deployment
    metadata: 
      name: springboot-demo-k8s
    spec: 
      selector: 
        matchLabels: 
          app: springboot-demo-k8s
      replicas: 1
      template: 
        metadata:
          labels: 
            app: springboot-demo-k8s
        spec: 
          containers: 
          - name: springboot-demo-k8s
            image: registry.cn-hangzhou.aliyuncs.com/zhao_yang/springboot-demo-k8s:v1.0
            ports: 
            - containerPort: 8080
    ---
    # 創(chuàng)建Pod的Service
    apiVersion: v1
    kind: Service
    metadata: 
      name: springboot-demo-k8s
    spec: 
      ports: 
      - port: 80
        protocol: TCP
        targetPort: 8080
      selector: 
        app: springboot-demo-k8s
    ---
    # 創(chuàng)建Ingress,定義訪問規(guī)則
    apiVersion: networking.k8s.io/v1beta1
    kind: Ingress
    metadata: 
      name: springboot-demo-k8s
    spec: 
      rules: 
      - host: springboot.sunny.com
        http: 
          paths: 
          - path: /
            backend: 
              serviceName: springboot-demo-k8s
              servicePort: 80
    
  • 編寫 .sh 執(zhí)行文件

    [root@worker01-kubeadm-k8s scripts]# vi /root/.jenkins/workspace/scripts/k8s-deploy-springboot-demo.sh
    
    # ================== YAML文件內(nèi)容 ============
    kubectl delete -f /root/.jenkins/workspace/scripts/springboot-demo-k8s.yaml
    kubectl apply -f /root/.jenkins/workspace/scripts/springboot-demo-k8s.yaml
    echo "k8s deploy success!"
    # ================== YAML文件內(nèi)容 ============
    
    [root@worker01-kubeadm-k8s scripts]# chmod +x k8s-deploy-springboot-demo.sh
    
  • 修改Pipeline

    node {
       // Pull
       stage('Pull') { //stage表示一個任務
          //這里是任務的內(nèi)容
          //因為我們的機器已經(jīng)生成了秘鑰且與Gieee進行了綁定,所以無需輸入賬號密碼就可以進行拉取代碼
          git 'https://gitee.com/suny95/springboot-demo-k8s.git'
       }
       
       //Maven
       stage('AutoCompile') {
           sh "mvn clean package"
       }
       
       //build push
       stage('Build And Push Image') { 
          sh "/root/.jenkins/workspace/scripts/springboot-demo-k8s-build-image.sh"
       }
       
       //k8s
       stage('K8S Deploy') { 
          sh "/root/.jenkins/workspace/scripts/k8s-deploy-springboot-demo.sh"
       }
    }
    
  • 構建任務并監(jiān)控輸出

    image.png

發(fā)現(xiàn)出現(xiàn)異常了,這個問題其實是因為我們選擇的機器在 K8S 集群中不是 Master 節(jié)點,它沒有執(zhí)行kubectl 命令的權限,我們需要配置一下!

  • 復制 .kube 文件目錄到 Worker01 節(jié)點

    [root@master-kubeadm-k8s .kube]# pwd
    /root/.kube
    
    # 這里的 config 是權限認證的文件
    [root@master-kubeadm-k8s .kube]# ll
    total 12
    drwxr-xr-x. 3 root root   23 Mar 24 14:32 cache
    -rw-------. 1 root root 5454 Mar 24 14:30 config
    drwxr-xr-x. 3 root root 4096 Apr  4 08:59 http-cache
    
    image.png
```ruby
[root@worker01-kubeadm-k8s ~]# mkdir .kube
[root@worker01-kubeadm-k8s ~]# cd .kube/

# 將 Master 節(jié)點中config文件內(nèi)容復制進去即可
[root@worker01-kubeadm-k8s .kube]# vi config
[root@worker01-kubeadm-k8s .kube]# ll
total 8
-rw-r--r--. 1 root root 5454 Apr 19 09:45 config
```
  • 重新構建并監(jiān)控

    image.png
  • 測試

    # pod 運行成功
    [root@worker01-kubeadm-k8s scripts]# kubectl get pods
    NAME                                   READY   STATUS    RESTARTS   AGE
    springboot-demo-k8s-79c867fd58-ts2f7   1/1     Running   0          5m53s
    
    # service 也創(chuàng)建成功
    [root@worker01-kubeadm-k8s scripts]# kubectl get svc
    NAME                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
    kubernetes            ClusterIP   10.96.0.1       <none>        443/TCP   25d
    springboot-demo-k8s   ClusterIP   10.99.138.171   <none>        80/TCP    6m46s
    
    # ingress 也在
    [root@worker01-kubeadm-k8s scripts]# kubectl get ingress
    NAME                  HOSTS                ADDRESS   PORTS   AGE
    springboot-demo-k8s   springboot.sunny.com             80      10m
    
    # 訪問 Service IP + 路徑, 成功訪問到結(jié)果
    [root@worker01-kubeadm-k8s scripts]# curl 10.99.138.171/k8s
    hello K8S
    
    • 通過Ingress訪問也成功
image.png

由于機器問題,我沒辦法演示 Git Push 就觸發(fā)自動構建的任務,大家如果有公網(wǎng)的機器的話,可以去嘗試弄一下!

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容