kubernetes+Azure DevOps實現.Net Core專案的自動化部署&均衡負載

寶樹吶發表於2020-07-18

1. 前言

前前後後學習kubernetes也有一個來月了,關於kubernetes的部落格也寫了有十多篇。但是技術如果無法落地到實際的應用場景終歸是紙上談兵,所以就有了這一出:通過結合kubernetesazure devops實現專案的CI/CD以及均衡負載

寫完這篇後kubernetes的相關學習也暫時告一段落了,有種終於闖關成功了啊的感覺,當然這是題外話了。

注1以下只是以Net Core專案為例,實際運用場景中,除了dockfile的編寫有差別,剩下整個自動化部署鏈條中的技術也好,工具也好,都可以複用,與語言和語言框架本身無關。
注2本文演示的也只是其中一種簡便的方式,具體的自動化流程中,由於自由度非常高,所以實際的流程可能會更加複雜,這裡就不做贅述了

以下場景需要用到的工具或者技術:

  • .Net Core

部署的應用本身

作為程式碼倉庫

  • kubernetes
    • docker
    • helm【kubernetes的包管理工具】
    • ingress【使用ingress繫結域名和https證書,實現域名訪問】
  • Azure DevOps

作為CI/CD的工具

:以下所有的相關部署程式碼,都在下面這個倉庫

  • 倉庫內容只是我自己用的一個小工具,當然具體是什麼內容不重要,這篇只是演示部署相關的

https://github.com/lzw5399/TocGenerator


2. Net Core專案本身的準備

2.1 dockerfile

你需要一個dockerfile來構建一個docker image, 如果是.Net Core專案,vs提供了傻瓜式生成dockerfile的功能,可以免去初學時編寫dockerfile的煩惱

  • 本示例dockerfile路徑和內容

2.2 建立kubernetes用於helm的chart包

2.2.1 說明

這一部分需要有helm相關的知識,說白了就是將你的如果熟悉k8s但不熟悉helm,可以參照:

kubernetes系列(十六) - Helm安裝和入門

2.2.2 chart檔案目錄和檔案組成

自定義的chart包,位於以下路徑

https://github.com/lzw5399/TocGenerator/tree/master/kubernetes

如上圖可以看出是一個很經典的自定義chart包的檔案目錄,即:

.
├── Chart.yaml           【chart的name和version等資訊】
├── templates            【k8s的資源清單模板,可以引用values.yaml的變數】
|   ├── deployment.yaml
|   └── service.yaml
├── values.yaml          【定義變數,供template/下的yaml使用,實現動態替換yaml內容】

3. Azure Devops建立倉庫的pipeline

3.1 前言

Azure DevOps是微軟出品的DevOps平臺,裡面包含了Pipelines工具鏈,對個人免費,可以用於專案的CI/CD

https://dev.azure.com

3.2 使用azure devops準備操作

  • 如果之前使用過azure devops,這幾步可以視情況跳過。
  1. 進入azure devops註冊賬號
  2. 之後按照引導新建一個organization
  3. 再新建一個project
  4. 進入project

3.3 建立service connections

這裡要建立一個service connections,用於之後pipeline訪問k8s的master伺服器

  1. 點選peject setting
  2. 這裡點選service connections來建立一個連線,用於訪問k8s的master伺服器
  3. 然後填寫具體的憑證,之後的pipeline上需要

3.4 新建pipeline流水線

新建pipeline流水線用於自定義部署流程

  1. 點選pipelines,然後點選create pipelines,新建一條流水線來部署我們的應用
  2. 選擇程式碼倉庫位置,選github
  3. 然後會跳到github進行授權,授權完成後會顯示github的repo列表,選擇具體的倉庫
  4. 選擇完倉庫後,會自動按照你當前專案的語言,在github倉庫的根目錄生成一個預設的azure-pipelines.yml檔案,
  5. 替換檔案的內容,我們最終使用的yaml檔案步驟大概如下
    • 第一步:構建docker映象
    • 第二步:將自定義的chart包拷貝到master伺服器上
    • 第三步:執行deploy.sh指令碼,完成部署
# 哪條分支會觸發構建
trigger:
- master

resources:
- repo: self

# 定義變數
variables:
- name: appName
  value: tocgenerator

- name: tag
  value: $(Build.BuildNumber)

- name: imageNameWithoutTag
  value: $(dockerid)/$(appName)

- name: imageNameWithTag
  value: $(imageNameWithoutTag):$(tag)

- name: serverChartLocation
  value: /root/helm-chart-folder/toc

stages:
- stage: Build
  jobs:  
  - job: Build
    pool:
      vmImage: 'ubuntu-latest'
  
    # 這下面是每個我們要具體執行的任務
    steps:
    # build docker images並且push到倉庫
    - task: Docker@2
      displayName: docker build and push
      inputs:
        containerRegistry: 'my_docker_hub'
        repository: '$(imageNameWithoutTag)'
        command: 'buildAndPush'
        Dockerfile: '**/Dockerfile'
        buildContext: '.'
        tags: $(tag)
        addPipelineData: false

    # 將kubernetes資料夾,即chart包拷貝到k8s的master伺服器
    - task: CopyFilesOverSSH@0
      displayName: copy helm chart to server
      inputs:
        # 這個endpoint就是我們剛剛建立的service connection的名字
        sshEndpoint: 'my_server'
        sourceFolder: 'kubernetes'
        contents: '**'
        targetFolder: $(serverChartLocation)
        readyTimeout: '20000'
  
    # 在k8s的master伺服器上執行我們github倉庫的根目錄的deploy.sh,進行部署操作
    - task: SSH@0
      displayName: run deploy shell on server
      inputs:
        # 這個endpoint就是我們剛剛建立的service connection的名字
        sshEndpoint: 'my_server'
        runOptions: 'script'
        scriptPath: 'deploy.sh'
        args: '$(tag) $(serverChartLocation)'
        readyTimeout: '20000'

3.5 建立部署shell指令碼

部署指令碼的位置

https://github.com/lzw5399/TocGenerator/blob/master/deploy.sh

幾點說明

  1. echo純粹是為了記錄log使用的,下面的示例把echo部分刪除了
  2. $1 and $2 代表外部傳入的引數
  3. $1是image的tag,$2是k8s的master伺服器上我們自定義的chart的目錄
  4. 移除沒有tag的懸掛docker image,純粹為了節省伺服器空間,為可選項
#!/bin/bash

# 出現錯誤退出指令碼執行
set -o errexit

# $1 and $2 代表外部傳入的引數
# $1是image的tag,$2是k8s的master伺服器上我們自定義的chart的目錄
buildNumber=$1
serverChartLocation=$2
cd $serverChartLocation

# 安裝或者升級我們的helm release
# 即如果查詢到了有release存在就upgrade,沒有則install
if test -z "$(helm ls | grep toc-release)"; then
  helm install -f values.yaml --set env.buildnumber=$buildNumber --set image.tag=$buildNumber toc-release .
else
  helm upgrade -f values.yaml --set env.buildnumber=$buildNumber --set image.tag=$buildNumber toc-release .
fi

# 移除沒有tag的懸掛docker image(可選)
danglings=$(sudo docker images -f "dangling=true" -q)
if test -n "$danglings"; then
  sudo docker rmi $(sudo docker images -f "dangling=true" -q) >>/dev/null 2>&1
  if [[ $? != 0 ]]; then
    exit $?
  fi
fi

exit 0

4. 觸發pipeline部署流水線

這裡有兩種辦法,

  1. 點選我們剛剛建立的pipeline手動run一個
  2. 通過push程式碼到倉庫的指定分支(我們設定的master)觸發構建

顯示構建成功之後就可以檢視了!

5. 關於均衡負載

均衡負載是kubernetes自帶的基礎功能之一,這裡只是做了一個試驗可以更加直觀地感受到而已

如下

  1. 定義一個靜態的guid
  2. 在/version 路由下輸出guid

則如果有2個例項,且均衡負載成功的話,每次重新整理這個介面,會隨機顯示這兩個guid

  • deployment的replicas例項數需要設定2以上

最後均衡負載試驗的地址,也是本次例項專案的線上地址

https://toc.codepie.fun/version

  • 如下,會出現兩個不同的guid

相關文章