ASP.NET Core on K8S深刻學習(6)Health Check

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

1、關於K8S中的Health Check

  所謂Health Check,就是健康檢查,即防微杜漸。K8S是一個編排引擎能夠幫助咱們快捷地部署容器集羣,若是部署上錯誤的容器致使服務崩潰,一般狀況下咱們都會經過一些高可用機制進行故障轉移。可是,前提條件是有健康檢查。node

  K8S天然幫咱們考慮到了這個問題,健康檢查是K8S的重要特性之一,默認有健康檢查機制,此外還能夠主動設置一些自定義的健康檢查。nginx

  默認狀況下,每一個容器啓動時都會執行一個進程,由Dockerfile中的CMD或ENTRYPOINT指定。若是進程退出時的返回碼不爲0,則認爲容器發生了故障,K8S會根據重啓策略(restartPolicy)重啓容器。web

  例以下面這個例子,它模擬了容器發生故障的場景,注意下面配置文件中的args選項的定義:數據庫

apiVersion: v1 kind: Pod metadata: name: edc-healthcheck-demo labels: test: healthcheck spec: restartPolicy: OnFailure containers: - name: healthcheck image: busybox imagePullPolicy: IfNotPresent args: - /bin/sh
      - -c - sleep 10; exit 1

  其中 sleep 10; exit 1表明啓動10秒以後就非正常退出(返回碼不爲0),而後經過kubectl建立Pod:json

kubectl apply -f health-check.yaml

  過一段時間後查看Pod的狀態,以下圖所示:後端

  

   能夠看到,該容器已經重啓了2次。也能夠看出,restartPolicy簡單直接暴力有效,不禁感嘆重啓大法好!api

  可是,也要正視一個問題:必須等到進程退出後的返回值是非零纔會觸發重啓策略,不能直接監測容器是不是健康緩存

  那麼,K8S中有沒有更好的機制可以實現智能一點的健康檢查呢?答案就是使用Liveness與Readinesss。app

2、Liveness探測

2.1 Liveness初體驗

一句話Liveness:若是檢測有問題(若是健康檢查失敗),重啓pod!至於怎麼檢測,你說了算(自定義判斷容器是否健康的條件)!  

  Liveness提供了一些重要的參數:

initialDelaySeconds:容器啓動後第一次執行探測是須要等待多少秒,看運行的服務而定。 periodSeconds:執行探測的頻率,默認是10秒,最小1秒。 timeoutSeconds:探測超時時間,默認1秒,最小1秒。 successThreshold:探測失敗後,最少連續探測成功多少次才被認定爲成功,默認是1,對於liveness必須是1,最小值是1。 failureThreshold:探測成功後,最少連續探測失敗多少次才被認定爲失敗。默認是3。最小值是1.

  下面實踐一個小例子建立一個Pod:

#command本身定義,例子爲 /tmp/healthy 不存在則認爲pod有問題,你們根據實際業務來自定義。 apiVersion: v1 kind: Pod metadata: labels: test: liveness name: liveness-demo spec: containers: - name: liveness image: busybox args: - /bin/sh
    - -c - touch /tmp/healthy; sleep 30; rm -rf/tmp/healthy; sleep 10 livenessProbe: exec: command: - cat
        - /tmp/healthy initialDelaySeconds: 10 periodSeconds: 5

  這裏啓動pod後會建立文件夾 /tmp/healthy,30秒後刪除,在咱們的設置中,若是 /tmp/healthy 存在,則認爲容器處於正常狀態,不然認爲發生故障。

  須要注意的就是livenessProbe部分的定義了:

  (1)探測方法:經過cat命令查看/tmp/healthy是否存在;若是返回值爲0,則探測成功;不然,探測失敗;

  (2)initialDelaySeconds: 10 => 容器啓動10秒以後開始執行liveness探測;

  (3)periodSeconds: 5 => 每5秒執行一次liveness探測;若是連續執行3次探測都失敗,那麼就會殺掉並重啓容器;

  下面快速地驗證一下:

  (1)kubectl建立demo

kubectl apply -f liveness-demo.yaml

  (2)查看pod日誌

kubectl describe pod liveness-demo

  結果以下圖所示:

  

   30秒以後,/tmp/healthy 被刪除了,liveness探測失敗,又過了幾十秒,重複探測均失敗後,開啓了重啓容器。

  

2.2 Liveness探針

  上面的例子使用的是Liveness的exec探針,此外K8S還有幾種其餘類型的探針:

  • exec:在容器中執行一個命令,若是命令退出碼返回0則表示探測成功,不然表示失敗
  • tcpSocket:對指定的容IP及端口執行一個TCP檢查,若是端口是開放的則表示探測成功,不然表示失敗
  • httpGet:對指定的容器IP、端口及路徑執行一個HTTP Get請求,若是返回的狀態碼在 [200,400)之間則表示探測成功,不然表示失敗

  針對tcpSocket的例子:這裏會檢測80端口是否能夠正常訪問;

#檢測80端口是否聯通 apiVersion: v1 kind: Pod metadata: labels: test: readiness name: readiness-tcp spec: containers: - name: readiness image: nginx readinessProbe: failureThreshold: 3 tcpSocket: port: 80 initialDelaySeconds: 10 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 10

  針對httpGet的例子:這裏會檢測index.html文件是否能夠正常訪問;

#訪問80端口的index.html文件是否存在 apiVersion: v1 kind: Pod metadata: labels: test: readiness name: readiness-httpget spec: containers: - name: readiness image: nginx readinessProbe: failureThreshold: 3 httpGet: path: /index.html port: 80 scheme: HTTP initialDelaySeconds: 10 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 10

3、Readiness探測

3.1 Readiness初體驗

一句話Readiness:若是檢查失敗,K8S會將該Pod從服務代理的分發後端去除,再也不讓其接客(分發請求給該Pod)。若是檢測成功,那麼K8S就會將容器加入到分發後端,從新對外接客(對外提供服務)。  

  下面繼續以上面Liveness的例子來實踐一下:

apiVersion: v1 kind: Pod metadata: labels: test: readiness name: readiness-demo spec: containers: - name: readiness image: busybox args: - /bin/sh
    - -c - touch /tmp/healthy; sleep 30; rm -rf/tmp/healthy; sleep 10 readinessProbe: exec: command: - cat
        - /tmp/healthy initialDelaySeconds: 10 periodSeconds: 5

  readinessProbe的配置語法與livenessProbe徹底一致,但執行後的效果卻不同,見下圖所示:

  

  能夠看出:

  (1)剛被建立時,其READY狀態爲不可用;

  (2)15秒(initialDelaySeconds + periodSeconds = 10 + 5 = 15)以後,第一次進行Readiness探測成功,其READY狀態變爲可用。

  (3)30秒以後,/tmp/healthy被刪除,連續3次Readiness探測均失敗後,其READY狀態又變爲了避免可用。

  此外,咱們也能夠經過 kubectl describe pod readiness-demo 查看到更想起的日誌信息。

3.2 與Liveness的對比

  Liveness與Readiness都是K8S的Health Check機制,Liveness探測是重啓容器,而Readiness探測則是將容器設置爲不可用,不讓其再接受Service轉發的請求。

  Liveness與Readiness是獨立執行的,兩者無依賴,能夠單獨使用也能夠同時使用。

4、Health Check在K8S中的應用

4.1 在Scale Up中的應用

  對於多副本應用,當執行Scale Up操做時,新的副本會做爲後端服務加入到Service的負載均衡列表中。可是,不少時候應用的啓動都須要必定的時間作準備(好比加載緩存、鏈接數據庫等等),這時咱們能夠經過Readiness探測判斷容器是否真正就緒,從而避免將請求發送到還未真正就緒的後端服務。

  下面一個示例YAML配置文件定義了Readiness探測,重點關注readinessProbe部分:

apiVersion: apps/v1 kind: Deployment metadata: name: edc-webapi-deployment namespace: aspnetcore spec: replicas: 2 selector: matchLabels: name: edc-webapi template: metadata: labels: name: edc-webapi spec: containers: - name: edc-webapi-container image: edisonsaonian/k8s-demo:1.2 ports: - containerPort: 80 imagePullPolicy: IfNotPresent readinessProbe: httpGet: scheme: HTTP path: /api/health port: 80 initialDelaySeconds: 10 periodSeconds: 5

--- apiVersion: v1 kind: Service metadata: name: edc-webapi-service namespace: aspnetcore spec: type: NodePort ports: - nodePort: 31000 port: 8080 targetPort: 80 selector: name: edc-webapi

  對於readinessProbe部分:

  (1)schema指定了協議,這裏是HTTP協議,也能夠是HTTPS協議;

  (2)path指定訪問路徑,這裏是咱們自定義的一個Controller中的接口:簡單地返回一個狀態碼爲200的響應;

[Produces("application/json")] [Route("api/Health")] public class HealthController : Controller { [HttpGet] public IActionResult Get() => Ok("ok"); }

  (3)port指定端口,這裏是容器的端口80;

  (4)initialDelaySeconds和periodSeconds指定了容器啓動10秒以後開始探測,而後每隔5秒執行探測,若是發生3次以上探測失敗,則該容器會從Service的負載均衡中移除,直到下次探測成功後纔會從新加入。

4.2 在Rolling Update中的應用

  假設如今有一個正常運行的多副本應用,咱們要對其進行滾動更新即Rolling Update,K8S會逐步用新Pod替換舊Pod,結果就有可能發生這樣的一個場景:當全部舊副本被替換以後,而新的Pod因爲人爲配置錯誤一直沒法啓動,所以整個應用將沒法處理請求,沒法對外提供服務,後果很嚴重!

  所以,Readiness探測還提供了用於避免滾動更新中出現這種狀況的一些解決辦法,好比maxSurge和maxUnavailable兩個參數,用來控制副本替換的數量。

  繼續以上面的YAML配置文件爲例,重點關注strategy部分:

apiVersion: apps/v1 kind: Deployment metadata: name: edc-webapi-deployment namespace: aspnetcore spec: strategy: rollingupdate: maxSurge: 25% maxUnavailable: 25% replicas: 10 selector: matchLabels: name: edc-webapi template: metadata: labels: name: edc-webapi spec: containers: - name: edc-webapi-container image: edisonsaonian/k8s-demo:1.2 ports: - containerPort: 80 imagePullPolicy: IfNotPresent readinessProbe: httpGet: scheme: HTTP path: /api/health port: 80 initialDelaySeconds: 10 periodSeconds: 5

--- apiVersion: v1 kind: Service metadata: name: edc-webapi-service namespace: aspnetcore spec: type: NodePort ports: - nodePort: 31000 port: 8080 targetPort: 80 selector: name: edc-webapi

  (1)maxSurge : 25% => 控制滾動更新過程當中副本總數超過預期(這裏預期是10個副本 replicas: 10)的上限,能夠是數值也能夠是百分比,而後向上取整。這裏寫的百分比,默認值是25%;

  若是預期副本數爲10,那麼副本總數的最大值爲RoundUp(10 + 10 * 25%)=13個。

  (2)maxUnavailable : 25% => 控制滾動更新過程當中不可用的副本(這裏預期是10個副本 replicas: 10)佔預期的最大比例,能夠是數值也能夠是百分比,而後向下取整,一樣地默認值也是25%;

  若是預期副本總數爲10,那麼可用的副本數至少要爲10-roundDown(10 * 25%)=10-2=8個。

  綜上看來,maxSurge的值越大,初始建立的新副本數量就越多;maxUnavaliable值越大,初始銷燬的舊副本數量就越多;

5、小結

  本文探索了K8S中的默認健康檢查機制以及Liveness和Readiness兩種各有特色的探測機制,並經過一些小例子進行了說明。不過因爲筆者也是初學,對於這一塊沒有過多實踐經驗,所以也是講的比較粗淺,也但願之後可以有更多的實際經驗分享與各位。

參考資料

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

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

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

(4)華仔,《[譯]Kubernetes最佳實踐:使用Readiness和Liveness探測作Health Check

(5)benjanmin楊,《K8S中的Health Check

(6)條子在洗澡,《K8S健康性檢查-探測

 

做者:周旭龍

出處:https://edisonchou.cnblogs.com

本文版權歸做者和博客園共有,歡迎轉載,但未經做者贊成必須保留此段聲明,且在文章頁面明顯位置給出原文連接。

相關文章
相關標籤/搜索