ASP.NET Core on K8S深入學習(3-1)Deployment

  • 2019 年 10 月 3 日
  • 筆記

本篇已加入《.NET Core on K8S學習實踐系列文章索引》,可以點擊查看更多容器化技術相關係列文章。

上一篇《部署過程解析與安裝Dashboard》中我們了解K8S的部署過程,這一篇我們來了解一下K8S為我們提供的幾種應用運行方式:Deployment、DaemonSet與Job,它們是Kubernetes最重要的核心功能提供者。考慮到篇幅和更新速度,我將其分為兩篇文章,本篇會主要介紹Deployment,主要參考自CloudMan《每天5分鐘玩轉Kubernetes》,也推薦大家購買閱讀。

一、創建資源的兩種方式

  K8S支持兩種創建資源的方式,分別是 使用kubectl命令直接創建通過配置文件+kubectl apply創建,下面以上一篇中的ASP.NET Core示例來分別介紹下這兩種方式。

1.1 Kubectl命令直接創建

  第一種是通過kubectl命令直接創建:

kubectl run k8s-demo-deployment --image=edisonsaonian/k8s-demo:latest --replicas=2 --namespace=aspnetcore

  這樣我們就部署了一個具有2個副本的k8s-demo(一個ASP.NET Core API示例)。

1.2 YAML配置文件創建

  第二種是通過配置文件+kubectl apply(kubectl create也可以)創建:

apiVersion: apps/v1  kind: Deployment  metadata:    name: k8s-demo-deployment    namespace: aspnetcore  spec:    replicas: 2    template:      spec:        containers:        - name: k8s-demo          image: edisonsaonian/k8s-demo          ports:          - containerPort: 80

  不過,上面的配置文件可能並不能直接運行,因為默認情況下K8S還有一些必填項的驗證,完整你可以參考下面這段配置:

apiVersion: apps/v1  kind: Deployment  metadata:    name: k8s-demo-deployment    namespace: aspnetcore  spec:    replicas: 2    selector:      matchLabels:        app: aspnetcore_webapi    template:      metadata:        labels:          app: aspnetcore_webapi      spec:        containers:        - name: k8s-demo          image: edisonsaonian/k8s-demo          ports:          - containerPort: 80

View Code

  更多yaml文件的語法基礎,可以參考這一篇文章:https://www.kubernetes.org.cn/1414.html

  如上所示,我們將資源的屬性都寫在了一個yaml格式的配置文件中,有了這個配置文件,我們只需要執行一句:

kubectl apply -f k8s-demo-deployment.yaml

1.3 相關補充

  如果要刪除deployment,也只需要執行一句:

kubectl delete deployment k8s-demo-deployment

  或者是下面這一句:

kubectl delete -f k8s-demo-deployment.yaml

  執行之後,K8S會自動幫我們刪除相關Deployment、ReplicaSet(副本集)以及Pod。

  可以看出,直接通過kubectl創建會比較省力和快捷,但是它無法做到很好的管理,不適合正式的、規模化的部署,因此我們一般會更加傾向於採用配置文件的方式,但是使用配置文件要求我們熟悉yaml的語法,如果存在類似製表符之類的特殊字符都是無法成功執行的。

二、Deployment必知必會

2.1 Deployment類型應用運行

  這裡我們仍以上面提到的k8s-demo示例項目為例,通過下面這個配置文件來創建資源:

apiVersion: apps/v1  kind: Deployment  metadata:    name: k8s-demo-deployment    namespace: aspnetcore  spec:    replicas: 2    selector:      matchLabels:        app: aspnetcore_webapi    template:      metadata:        labels:          app: aspnetcore_webapi      spec:        containers:        - name: k8s-demo          image: edisonsaonian/k8s-demo          ports:          - containerPort: 80

  通過下面的命令創建資源:

kubectl apply -f k8s-demo-deployment.yaml

  下面我們來看看K8S到底為我們做了些什麼工作:

  (1)查看k8s-demo-deployment狀態

kubectl get deployment k8s-demo-deployment -n aspnetcore

  

   可以看到,對於我們的這個deployment,生成了2個副本且正常運行。

  如果想要獲得更加相信的信息,可以使用下面這句:

kubectl describe deployment k8s-demo-deployment -n aspnetcore

  從deployment的日誌中,可以看到如下圖所示的信息:

  

   可以看到,K8S的Deployment-Controller為k8s-demo創建了一個ReplicaSet名叫k8s-demo-deployment-54d5c97fb7,後面的Pod就是由這個ReplicaSet來管理的。

  (2)查看ReplicaSet的狀態

kubectl describe replicaset -n aspnetcore

  會得到以下兩個圖所示的信息:

  

   從上圖可以看出,這個ReplicaSet是由Deployment k8s-demo-deployment 創建的。

  

   從上圖中的日誌(Events代表日誌)可以看出,兩個副本Pod是由ReplicaSet-Controller創建的,且創建成功。

  (3)查看Pod的狀態

kubectl describe pod -n aspnetcore

  同樣,也會得到如下圖所示的兩個信息:

  

   可以看出,此Pod是由ReplicaSet k8s-demo-deployment-54d5c97fb7創建的。下圖的日誌記錄了Pod的啟動過程:

  

   從日誌中可以看到Pod的啟動過程,如果啟動過程中發生了異常(比如拉取鏡像失敗),都可以通過輸出的錯誤信息查看原因。

  下圖是整個Deployment的部署過程,即kubectl→Deployment→ReplicaSet→Pod,也可以看出對象的命名方式的規則:

  

2.2 伸縮Scale

  所謂伸縮,是指在線實時增加或減少Pod的副本數量。在剛剛的部署中,我們在配置文件中定義的是2個副本,如下圖所示:

  

   可以看到,兩個副本分別位於k8s-node1 和 k8s-node2上面。一般默認情況下,K8S不會將Pod調度到Master節點上,雖然Master節點也是可以作為Node節點曬用的。

  這時,如果我們想要擴展副本數量從2到3,只需要修改配置文件:

apiVersion: apps/v1  kind: Deployment  metadata:    name: k8s-demo-deployment    namespace: aspnetcore  spec:    replicas: 3
......

  然後再次apply:

kubectl apply -f k8s-demo-deployment.yaml

  最終結果如下圖所示:

  

  同理,如果想縮小副本數量,也是如上所述的步驟,不再贅述。

2.3 故障轉移FailOver

  所謂K8S中的故障轉移(FailOver),就是當某個Node節點失效或宕機時,會將該Node上所運行的所有Pod轉移到其他健康的Node節點上繼續運行。

  這裡繼續上例,我們有兩個Pod都運行在k8s-node2上,那麼我們這裡模擬k8s-node2故障,強制關閉該節點:

halt -h

  

  等待一段時間後(放心,不會很快),當K8S檢測到k8s-node2不可用,會將k8s-node2上的Pod最終標記為Terminating狀態,並在k8s-node1上新建兩個Pod,維持副本總數量為3。

  

  當然,也可以從Dashboard中直觀的看到:

  

  當k8s-node2恢復後,Terminating的Pod會自動被刪除,不過已經運行在k8s-node1的Pod是不會重新調度回k8s-node2的。

  

2.4 善用label控制Pod位置

  默認情況下,K8S的Scheduler會均衡調度Pod到所有可用的Node節點,但是有些時候希望將指定的Pod部署到指定的Node節點。例如,一個I/O密集型的Pod可以盡量部署在配置了SSD的Node節點,又或者一個需要GPU的Pod可以盡量部署在配置了GPU的Node節點上。

  不用擔心,K8S為我們提供了label來實現這個功能,label是一個key/value對,可以靈活設置各種自定義的屬性。比如,我們這裡假設我們的k8s-demo示例項目是一個I/O密集型的API,還假設k8s-node1是一個配置了SSD的Node節點:

kubectl label node k8s-node1 disktype=ssd
kubectl get node --show-labels

  顯示結果如下:可以看到,現在k8s-node多了一個label => disktype=ssd

  

  接下來,我們就可以在配置文件中為要部署的應用指定label了:

apiVersion: apps/v1  kind: Deployment  metadata:    name: k8s-demo-deployment    namespace: aspnetcore  spec:    replicas: 3    selector:      matchLabels:        app: aspnetcore_webapi    template:      metadata:        labels:          app: aspnetcore_webapi      spec:        containers:        - name: k8s-demo          image: edisonsaonian/k8s-demo          ports:          - containerPort: 80        nodeSelector:          disktype: ssd

   然後,再次apply創建資源:

kubectl apply -f k8s-demo-deployment.yaml

  驗證一下,所有的k8s-demo的Pod全都調度到了k8s-node1上面,符合預期:

  

   如果k8s-node1不再是配置SSD了,那麼我們就可以為其刪掉這個label了:

kubectl label node k8s-node1 disktype-

  注意,這裡的 – 就代表刪除,而且此時Pod不會重新部署,除非你刪除配置文件中的配置然後再次apply。

三、小結

  本文介紹了K8S中創建資源的兩種方式及對比,然後重點介紹了一下Deployment這個Controller,把玩了Deployment類型的應用運行、伸縮、故障轉移以及使用label來控制Pod的位置。運行應用是K8S最核心的功能,下一篇會繼續研究DaemonSet和Job這兩個Controller的應用方式和場景。當然,筆者也還是初學,有很多不足之處,也請多包涵。對於催更的童鞋,請耐心等待。

參考資料

(1)CloudMan,《每天5分鐘玩轉Kubernetes

(2)李振良,《一天入門Kubernets教程

(3)馬哥(馬永亮),《Kubernetes快速入門