linux運維、架構之路-K8s健康檢查Health Check


一、Health Check介紹

        強大的自愈能力是k8s容器編排引擎一個重要特性,自愈能力的默認實現方式為自動重啟發生故障的容器,另外還可以利用Liveness和Readiness探測機制設置更精細的健康檢查。

  • 零停機部署
  • 避免部署無效的鏡像
  • 更加安全的滾動升級

二、K8S健康檢查方式

1、k8s默認的健康檢查

       每個容器啟動時都會執行一個進程,此進程由Dockerfile的CMD或ENTRYPOINT指定。如果進程退出返回碼為非0,則認為容器發生故障,k8s會根據restartPolicy重啟容器。

①創建應用測試

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

②Pod的restartPolicy設置為OnFailure,默認策略為Always,執行創建Pod

kubectl apply -f healthcheck.yaml

③過幾分鍾查看Pod狀態,發現容器已經重啟了3次

[root@k8s-node1 health_check]# kubectl get pods healthcheck 
NAME          READY     STATUS    RESTARTS   AGE
healthcheck   0/1       Error     3          2m

容器進程返回值非0,k8s則認為容器發生故障,需要重啟,有不少場景下發生故障,但進程不會退出,比如訪問web服務時發生500內部錯誤,可能是負載過高,也可能是資源死鎖,此時httpd進程並沒有異常退出,在這種情況下重啟容器可能是最直接、最有效的解決方案,處理此類場景那就用到了k8s的Liveness探測。

2、Liveness探測

       Liveness探測讓用戶可以自定義判斷容器是否健康的條件,如果探測失敗,k8s就會重啟容器。

①創建應用演示

apiVersion: v1
kind: Pod
metadata:
  name: liveness
  labels:
    test: liveness
spec:
  restartPolicy: OnFailure
  containers:
  - name: liveness
    image: busybox
    args:
    - /bin/sh
    - -c
    - touch /tmp/healthy; sleep 30; rm -f /tmp/healthy; sleep 600
    livenessProbe:
      exec:
        command:
        - cat
        - /tmp/healthy
      initialDelaySeconds: 10
      periodSeconds: 5

以上yaml文件說明:啟動Pod后首先創建文件/tmp/healthy,30秒后刪除,如果文件/tmp/healthy存在,則認為容器處於正常狀態,反之發生故障。

探測方法:

  • 通過cat命令檢查/tmp/healthy文件是否存在,如果命令執行成功,返回值為0,k8s會認為本次Liveness探測成功;如果命令返回值非0,本次Liveness探測失敗
  • initialDelaySeconds: 10 指容器啟動10秒后開始執行Liveness探測,如果你的應用啟動要花30秒,那么initialDelaySeconds的值就應該大於30。
  • periodSeconds: 5 指每5秒執行一次Liveness探測,k8s如果連續執行3次Liveness探測均失敗,則會殺掉重啟容器

②創建Pod並查看

kubectl apply -f liveness.yaml
kubectl describe pod liveness

 ③35秒之后,日志顯示/tmp/healthy已經不存在了,Liveness連續幾次探測失敗,容器會被重啟

 ④再次查看pod,發現已經重啟1次

[root@k8s-node1 health_check]# kubectl get pods liveness 
NAME       READY     STATUS    RESTARTS   AGE
liveness   1/1       Running   1          1m

3、Readiness探測

        Liveness探測可以告訴k8s什么時候通過重啟容器實現自愈;Readiness探測告訴k8s什么時候可以將容器加入到service負載均衡池中,對外提供服務。

①Readiness探測配置與Liveness探測完全一樣

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

②創建並查看

kubectl apply -f readiness.yaml
[root@k8s-node1 health_check]# kubectl get pod readiness
NAME        READY     STATUS    RESTARTS   AGE
readiness   0/1       Running   0          8s

[root@k8s-node1 health_check]# kubectl get pod readiness
NAME        READY     STATUS    RESTARTS   AGE
readiness   1/1       Running   0          18s

[root@k8s-node1 health_check]# kubectl get pod readiness
NAME        READY     STATUS    RESTARTS   AGE
readiness   0/1       Running   0          49s

探測方法:

  • 剛創建時,READY狀態不可用
  • 15秒后,第一次進行Readiness探測並成功返回,設置READY為可用
  • 30秒后,/tmp/healthy被刪除,連續3次Readiness探測失敗后,READY被設置為不可用

③查看日志詳情

kubectl describe pod readiness

 4、Readiness探測與Liveness探測區別

  • Readiness探測與Liveness探測是兩種Health Check機制,如果不特意配置,k8s對兩種探測采取相同的默認行為,均通過判斷容器啟動進程的返回值是否為0判斷探測是否成功。
  • 兩種探測配置方法完全一樣,支持的配置參數也一樣,不同在於探測失敗后,Liveness探測是重啟容器,Readiness探測則將容器設置為不可用,不接收service轉發的請求
  • Readiness探測與Liveness探測是獨立執行的,二者之間沒有依賴,可以單獨使用,也可以同時使用,用Liveness探測判斷容器是否需要重啟以實現自愈,用Readiness探測判斷容器是否已經准備好對外提供服務

 三、Health Check在Scale UP中的應用

            在多副本應用中,當執行Scale Up新增一個副本的場景中,考慮到應用啟動需要一些時間,比如加載緩存數據、連接數據庫等,這里就可以通過Readiness探測判斷容器是否就緒,避免將請求發送到還沒准備好的
后端。

1、創建應用測試

apiVersion: apps/v1beta2
kind: Deployment
metadata:
  name: web
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: web
        image: httpd
        ports:
        - containerPort: 8080 readinessProbe: httpGet: scheme: HTTP     #指定協議,默認為HTTP path: /healthy   #訪問路徑 port: 8080 initialDelaySeconfs: 10 periodSeconds: 5  
---
apiVersion: v1
kind: Service
metadata:
  name: web-svc
spec:
  selector:
    app: web
  ports:
   - protocol: TCP
     port: 8080
     targetPort: 80

注:這里使用了不同與exec的另一種探測方法httpGet,k8s對該方法探測成功的判斷是http請求返回碼在200~400之間

2、上面配置作用

  • 容器啟動10秒后開始探測
  • 如果http://[container_ip]:8080/healthy返回碼不是200~400,表示容器沒有就緒,不接收Service web-svc的請求。
  • 每隔5秒探測一次
  • 直到返回碼為200~400,表明容器已經就緒,然后將其加入到web-svc的負載中,開始處理請求。
  • 探測繼續以5秒的間隔執行,如果連續3次失敗,容器會從負載中移除,直到再次探測成功后重新加入負載

四、Health Check在滾動更新中的應用

            Health Check另一個重要場景就是滾動更新,現有一個正常運行的多副本應用,接下來要對應用進行更新,比如升級成高版本的image,k8s會啟動新副本的過程如下:

  • 正常情況一下啟動的新副本需要10秒左右完成准備工作,在此之前無法響應業務請求
  • 由於人為配置錯誤,副本始終無法完成准備工作,比如無法連接后端的數據庫
生產環境中,如果沒有配置Health Check,默認Health Check機制會認為容器已經就緒,進行會逐步用新副本替換現有副本,當所有舊副本都被替換后,整個應用將無法處理請求,無法提供服務,
如果正確配置了Health Check,新副本只有通過了Readiness探測才會被添加到Service,如果探測不成功,現有副本不會被會部替換,業務仍然正常進行。

1、創建應用測試

kubectl apply -f app-v1.yaml --record
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: app
spec:
  replicas: 10
  template:
    metadata:
      labels:
        run: app
    spec:
      containers:
      - name: app
        image: busybox
        args:
        - /bin/sh
        - -c
        - sleep 10; touch /tmp/healthy; sleep 30000
        readinessProbe:
          exec:
            command:
            - cat
            - /tmp/healthy
          initialDelaySeconds: 10
          periodSeconds: 5

2、10秒后查看所有副本通過了Readiness探測

[root@k8s-node1 health_check]# kubectl get deployment app
NAME      DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
app       10        10        10           10          7m
[root@k8s-node1 health_check]# kubectl get pods
NAME                       READY     STATUS    RESTARTS   AGE
app-58594c894-4bfzn        1/1       Running   0          6m
app-58594c894-5wnxv        1/1       Running   0          6m
app-58594c894-9jspd        1/1       Running   0          6m
app-58594c894-bmgp9        1/1       Running   0          6m
app-58594c894-d8r72        1/1       Running   0          6m
app-58594c894-k42zf        1/1       Running   0          6m
app-58594c894-rvnpl        1/1       Running   0          6m
app-58594c894-ssg9w        1/1       Running   0          6m
app-58594c894-z2qd6        1/1       Running   0          6m
app-58594c894-zb6d8        1/1       Running   0          6m

3、進行滾動更新,創建app-v2.yaml

apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: app
spec:
  replicas: 10
  template:
    metadata:
      labels:
        run: app
    spec:
      containers:
      - name: app
        image: busybox
        args:
        - /bin/sh
        - -c
        - sleep 3000
        readinessProbe:
          exec:
            command:
            - cat
            - /tmp/healthy
          initialDelaySeconds: 10
          periodSeconds: 5

4、驗證新副本中不存在/tmp/healthy,能否通過Readiness探測

[root@k8s-node1 health_check]# kubectl get deployment app
NAME      DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
app       10        13        5            8           1h
#DESIRED 10:表示期望狀態是10個副本
#CURRENT 13: 表示當前副本總數,8個舊副本+5個新副本
#UP-TO-DATE 5:表示當前已完成更新的副本數
#AVAILABLE 8:表示當前處於可用的副本數 [root@k8s
-node1 health_check]# kubectl get pods NAME READY STATUS RESTARTS AGE app-58594c894-4bfzn 1/1 Running 0 1h app-58594c894-5wnxv 1/1 Running 0 1h app-58594c894-9jspd 1/1 Running 0 1h app-58594c894-bmgp9 1/1 Running 0 1h app-58594c894-d8r72 1/1 Running 0 1h app-58594c894-k42zf 1/1 Running 0 1h app-58594c894-ssg9w 1/1 Running 0 1h app-58594c894-z2qd6 1/1 Running 0 1h app-67f89fbd77-4fkq5 0/1 Running 0 1m app-67f89fbd77-7fgjg 0/1 Running 0 1m app-67f89fbd77-krf8w 0/1 Running 0 1m app-67f89fbd77-r25rx 0/1 Running 0 1m app-67f89fbd77-wdrsr 0/1 Running 0 1m

5、為什么新創建副本數是5個,同時只銷毀2個舊副本

  • 1、maxSurge
  • 此參數控制滾動更新過程中副本總數超過DESIRED的上限,默認值為25%,也可以是具體的整數,上面例子中,DESIRED為10,副本總數CURRENT最大值即為:10+10*25%=13,maxSurge值越大,初始創建的新副本就越多。
  • 2、maxUnavailable
  • 此參數控制滾動更新過程中,不可用的副本占DESIRED的最大比例。同樣maxUnavailable默認值也為25%,那么可用的副本至少為10-10*25%=8,maxUnavailable值越大,初始銷毀的副本數量就越多

6、正常滾動更新過程

  • 創建3個新副本使副本總數達到13個
  • 銷毀2個舊副本使可用的副本數降到8個
  • 當2個舊副本成功銷毀后,再創建2個新副本,保持副本總數為13個
  • 當新副本通過Readiness探測后,會使可用副本數增加,超過8個
  • 進而可以繼續銷毀更多的副本,使可用副本數回到8
  • 舊副本的銷毀使副本總數低於13,這樣可以繼續創建新的副本
  • 這個過程一直持續進行,最終所有的舊副本被新副本替換,滾動更新完成
  • 如果滾動更新失敗,使用命令kubectl rollout undo deployment app快速回滾到上一版本

7、自定義maxSurge和maxUnavailable

apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: app
spec:
 strategy: rollingUpdate: maxSurge: 35% maxUnavailable: 35%
  replicas: 10
  template:
    metadata:
      labels:
        run: app
    spec:
      containers:
      - name: app
        image: busybox
        args:
        - /bin/sh
        - -c
        - sleep 10; touch /tmp/healthy; sleep 30000
        readinessProbe:
          exec:
            command:
            - cat
            - /tmp/healthy
          initialDelaySeconds: 10
          periodSeconds: 5

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM