kubernetes+Azure DevOps實現.Net Core專案的自動化部署&均衡負載
阿新 • • 發佈:2020-07-19
- [1. 前言](#head1)
- [2. Net Core專案本身的準備](#head2)
- [2.1 dockerfile](#head3)
- [2.2 建立kubernetes用於helm的chart包](#head4)
- [2.2.1 說明](#head5)
- [2.2.2 chart檔案目錄和檔案組成](#head6)
- [3. Azure Devops建立倉庫的pipeline](#head7)
- [3.1 前言](#head8)
- [3.2 使用azure devops準備操作](#head9)
- [3.3 建立service connections](#head10)
- [3.4 新建pipeline流水線](#head11)
- [3.5 建立部署shell指令碼](#head12)
- [4. 觸發pipeline部署流水線](#head13)
- [5. 關於均衡負載](#head14)
## 1. 前言
前前後後學習kubernetes也有一個來月了,關於kubernetes的部落格也寫了有十多篇。但是技術如果無法落地到實際的應用場景終歸是紙上談兵,所以就有了這一出:通過結合`kubernetes`和`azure devops`實現專案的`CI/CD`以及均衡負載
寫完這篇後`kubernetes`的相關學習也暫時告一段落了,有種終於闖關成功了啊的感覺,當然這是題外話了。
**注1**:**以下只是以Net Core專案為例,實際運用場景中,除了dockfile的編寫有差別,剩下整個自動化部署鏈條中的技術也好,工具也好,都可以複用,與語言和語言框架本身無關。**
**注2**:**本文演示的也只是其中一種簡便的方式,具體的自動化流程中,由於自由度非常高,所以實際的流程可能會更加複雜,這裡就不做贅述了**
以下場景需要用到的工具或者技術:
- .Net Core
> 部署的應用本身
- [Github](https://github.com/)
> 作為程式碼倉庫
- [kubernetes](https://kubernetes.io/)
- docker
- helm【kubernetes的包管理工具】
- ingress【使用ingress繫結域名和https證書,實現域名訪問】
- [Azure DevOps](https://dev.azure.com/)
> 作為CI/CD的工具
**注**:以下所有的相關部署程式碼,都在下面這個倉庫
- 倉庫內容只是我自己用的一個小工具,當然具體是什麼內容不重要,這篇只是演示部署相關的
> https://github.com/lzw5399/TocGenerator
----
## 2. Net Core專案本身的準備
### 2.1 dockerfile
你需要一個`dockerfile`來構建一個`docker image`, 如果是`.Net Core`專案,vs提供了傻瓜式生成`dockerfile`的功能,可以免去初學時編寫`dockerfile`的煩惱
- 本示例dockerfile路徑和內容
![](https://tva1.sinaimg.cn/large/007S8ZIlgy1ggvh3hxjjxj30ok0j4q5d.jpg)
### 2.2 建立kubernetes用於helm的chart包
#### 2.2.1 說明
這一部分需要有helm相關的知識,說白了就是將你的如果熟悉k8s但不熟悉helm,可以參照:
> [kubernetes系列(十六) - Helm安裝和入門](https://www.cnblogs.com/baoshu/p/13296659.html)
#### 2.2.2 chart檔案目錄和檔案組成
自定義的chart包,位於以下路徑
> https://github.com/lzw5399/TocGenerator/tree/master/kubernetes
![](https://tva1.sinaimg.cn/large/007S8ZIlgy1ggvgcbyvl7j318e0cv75t.jpg)
如上圖可以看出是一個很經典的自定義chart包的檔案目錄,即:
```shell
.
├── 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`
![](https://tva1.sinaimg.cn/large/007S8ZIlgy1ggvhl8guzhj30v50f83z5.jpg)
4. 進入`project`
### 3.3 建立service connections
這裡要建立一個service connections,用於之後pipeline訪問k8s的master伺服器
1. 點選peject setting
![](https://tva1.sinaimg.cn/large/007S8ZIlgy1ggvi4z24nsj307t0kvwf9.jpg)
2. 這裡點選`service connections`來建立一個連線,**用於訪問k8s的master伺服器**
![](https://tva1.sinaimg.cn/large/007S8ZIlgy1ggvi8xaz5fj31gu0mq795.jpg)
3. 然後填寫具體的憑證,之後的pipeline上需要
### 3.4 新建pipeline流水線
新建`pipeline`流水線用於自定義部署流程
1. 點選`pipelines`,然後點選`create pipelines`,新建一條流水線來部署我們的應用
![](https://tva1.sinaimg.cn/large/007S8ZIlgy1ggvhp1mr1fj31ad0mwn08.jpg)
2. 選擇程式碼倉庫位置,選github
![](https://tva1.sinaimg.cn/large/007S8ZIlgy1ggvhqcdfjaj30sk0iewgv.jpg)
3. 然後會跳到github進行授權,授權完成後會顯示github的repo列表,選擇具體的倉庫
4. 選擇完倉庫後,會自動按照你當前專案的語言,在github倉庫的根目錄生成一個預設的`azure-pipelines.yml`檔案,
5. 替換檔案的內容,我們最終使用的yaml檔案步驟大概如下
- 第一步:構建docker映象
- 第二步:將自定義的chart包拷貝到master伺服器上
- 第三步:執行`deploy.sh`指令碼,完成部署
```yaml
# 哪條分支會觸發構建
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,純粹為了節省伺服器空間,為可選項
``` shell
#!/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`)觸發構建
![](https://tva1.sinaimg.cn/large/007S8ZIlgy1ggviwgsdagj31gx0go77x.jpg)
顯示構建成功之後就可以查看了!
## 5. 關於均衡負載
均衡負載是kubernetes自帶的基礎功能之一,這裡只是做了一個試驗可以更加直觀地感受到而已
**如下**
1. 定義一個**靜態的**guid
![](https://tva1.sinaimg.cn/large/007S8ZIlgy1ggvj3duxkaj30o605r0tn.jpg)
2. 在/version 路由下輸出guid
![](https://tva1.sinaimg.cn/large/007S8ZIlgy1ggvj4k0n9yj30p8062q3s.jpg)
則如果有2個例項,且均衡負載成功的話,每次重新整理這個介面,會隨機顯示這兩個guid
- deployment的replicas例項數需要設定2以上
![](https://tva1.sinaimg.cn/large/007S8ZIlgy1ggvj7j7jmej30th0dmjsl.jpg)
最後均衡負載試驗的地址,也是本次例項專案的線上地址
> https://toc.codepie.fun/version
- 如下,會出現兩個不同的guid
![](https://tva1.sinaimg.cn/large/007S8ZIlgy1ggvj8rdni2j30gr06k3ym.jpg)
![](https://tva1.sinaimg.cn/large/007S8ZIlgy1ggvj97bqydj30hq05qt