Kubernetes重啟策略+健康檢查詳解


 系統環境:

  • kubernetes 版本:1.19.0

Kubernetes 官方文檔地址:

 

一、Pod 的整個生命階段

  • Pending: 正在創建 Pod,但是 Pod 中的容器還沒有全部被創建完成,這其中也包含集群為容器創建網絡,或者下載鏡像的過程。
  • Running: Pod 內所有的容器都已經被創建,且至少一個容器正在處於運行狀態、正在啟動狀態或者重啟狀態。
  • Succeeded: Pod 中所以容器都執行成功后退出,並且沒有處於重啟的容器。
  • Failed: Pod 中所以容器都已退出,但是至少還有一個容器退出時為失敗狀態。
  • Unknown: 由於一些原因,Pod 的狀態無法獲取,通常是與 Pod 通信時出錯導致的。

 

 

 

 

二、Pod 重啟策略

 

Pod重啟策略(RestartPolicy)應用於Pod內的所有容器,並且僅在Pod所處的Node上由kubelet進行判斷和重啟操作。當某個容器異常退出或者健康檢查失敗時,kubelet將根據RestartPolicy的設置來進行相應操作。

Pod的重啟策略包括Always、OnFailure和Never,默認值為Always。

  • Always:當容器失效時,由kubelet自動重啟該容器;
  • OnFailure:當容器終止運行且退出碼不為0時,由kubelet自動重啟該容器;
  • Never:不論容器運行狀態如何,kubelet都不會重啟該容器。

  kubelet重啟失效容器的時間間隔以sync-frequency乘以2n來計算,例如1/2/4/8倍等,最長延時5min,並且在成功重啟后的10min后重置該時間。

  Pod的重啟策略與控制方式關聯,當前可用於管理Pod的控制器包括ReplicationController、Job、DaemonSet及直接管理kubelet管理(靜態Pod)。

 
不同控制器的重啟策略限制如下:
  • RC和DaemonSet:必須設置為Always,需要保證該容器持續運行;
  • Job:OnFailure或Never,確保容器執行完成后不再重啟;
  • kubelet:在Pod失效時重啟,不論將RestartPolicy設置為何值,也不會對Pod進行健康檢查。
 

 

三、Pod 常見狀態轉換場景

Pod中的容器數 Pod狀態 發生事件 不同重啟策略下的結果狀態
Always OnFailure Never
包含一個容器 Running 容器成功退出 Running Succeeded Succeeded
包含一個容器 Running 容器失敗退出 Running Running Failed
包含兩個容器 Running 1個容器失敗退出 Running Running Running
包含兩個容器 Running 容器內存溢出掛掉 Running Running Failed

 

 

四、Pod 的活性與就緒探針

1、Pod 探針機制

  在 Kubernetes 中 Pod 是最小的計算單元,而一個 Pod 又由多個容器組成,相當於每個容器就是一個應用,應用在運行期間,可能因為某也意外情況致使程序掛掉。那么如何監控這些容器狀態穩定性,保證服務在運行期間不會發生問題,發生問題后進行重啟等機制,就成為了重中之重的事情,考慮到這點 kubernetes 推出了活性探針機制。

  有了活性探針后能保證程序在運行中如果掛掉能夠自動重啟,但是還有個經常遇到的問題,比如說,在 Kubernetes 中啟動 Pod,顯示明明 Pod 已經啟動成功,且能訪問里面的端口,但是卻返回錯誤信息。還有就是在執行滾動更新時候,總會出現一段時間,Pod 對外提供網絡訪問,但是訪問卻發生 404,這兩個原因,都是因為 Pod 已經成功啟動,但是 Pod 的的容器中應用程序還在啟動中導致,考慮到這點 Kubernetes 推出了就緒探針機制。

 

2、Pod 兩種探針簡介

  • LivenessProbe(存活探針): 存活探針主要作用是,用指定的方式進入容器檢測容器中的應用是否正常運行,如果檢測失敗,則認為容器不健康,那么 Kubelet 將根據 Pod 中設置的 restartPolicy (重啟策略)來判斷,Pod 是否要進行重啟操作,如果容器配置中沒有配置 livenessProbe 存活探針,Kubelet 將認為存活探針探測一直為成功狀態。
  • ReadinessProbe(就緒探針): 用於判斷容器中應用是否啟動完成,當探測成功后才使 Pod 對外提供網絡訪問,設置容器 Ready 狀態為 true,如果探測失敗,則設置容器的 Ready 狀態為 false。對於被 Service 管理的 Pod,Service 與 Pod、EndPoint 的關聯關系也將基於 Pod 是否為 Ready 狀態進行設置,如果 Pod 運行過程中 Ready 狀態變為 false,則系統自動從 Service 關聯的 EndPoint 列表中移除,如果 Pod 恢復為 Ready 狀態。將再會被加回 Endpoint 列表。通過這種機制就能防止將流量轉發到不可用的 Pod 上。

 

3、Pod 探針的探測方式與結果

目前 LivenessProbe 和 ReadinessProbe 兩種探針都支持下面三種探測方法:

  • ExecAction: 在容器中執行指定的命令,如果執行成功,退出碼為 0 則探測成功。
  • HTTPGetAction: 通過容器的IP地址、端口號及路徑調用 HTTP Get方法,如果響應的狀態碼大於等於200且小於400,則認為容器 健康。
  • TCPSocketAction: 通過容器的 IP 地址和端口號執行 TCP 檢 查,如果能夠建立 TCP 連接,則表明容器健康。

探針探測結果有以下值:

  • Success:表示通過檢測。
  • Failure:表示未通過檢測。
  • Unknown:表示檢測沒有正常進行。

 

4、Pod 探針的相關屬性

探針(Probe)有許多可選字段,可以用來更加精確的控制Liveness和Readiness兩種探針的行為(Probe):

  • initialDelaySeconds: Pod 啟動后首次進行檢查的等待時間,單位“秒”。
  • periodSeconds: 檢查的間隔時間,默認為 10s,單位“秒”。
  • timeoutSeconds: 探針執行檢測請求后,等待響應的超時時間,默認為 1s,單位“秒”。
  • successThreshold: 探針檢測失敗后認為成功的最小連接成功次數,默認為 1s,在 Liveness 探針中必須為 1s,最小值為 1s。
  • failureThreshold: 探測失敗的重試次數,重試一定次數后將認為失敗,在 readiness 探針中,Pod會被標記為未就緒,默認為 3s,最小值為 1s。

 

5、兩種探針的區別

ReadinessProbe 和 livenessProbe 可以使用相同探測方式,只是對 Pod 的處置方式不同:

  • readinessProbe 當檢測失敗后,將 Pod 的 IP:Port 從對應的 EndPoint 列表中刪除。
  • livenessProbe 當檢測失敗后,將殺死容器並根據 Pod 的重啟策略來決定作出對應的措施。

 

 

五、探針使用示例

1、LivenessProbe 探針使用示例

1)通過exec方式做健康探測

示例文件 liveness-exec.yaml

apiVersion: v1
kind: Pod
metadata:
  name: liveness-exec
  labels:
    app: liveness
spec:
  containers:
  - name: liveness
    image: busybox
    args:                       #創建測試探針探測的文件
    - /bin/sh
    - -c
    - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
    livenessProbe:
      initialDelaySeconds: 10   #延遲檢測時間
      periodSeconds: 5          #檢測時間間隔
      exec:
        command:
        - cat
        - /tmp/healthy

查看Pod日志詳情

[root@k8s-master yaml]# kubectl describe pod liveness-exec
Events:
  Type     Reason     Age                    From                Message
  ----     ------     ----                   ----                -------
  Normal   Scheduled  7m4s                                       Successfully assigned default/liveness-exec to k8s-node1
  Normal   Pulled     6m47s                  kubelet, k8s-node1  Successfully pulled image "busybox" in 16.176728723s
  Normal   Pulled     5m20s                  kubelet, k8s-node1  Successfully pulled image "busybox" in 15.640787963s
  Normal   Created    3m50s (x3 over 6m47s)  kubelet, k8s-node1  Created container liveness
  Normal   Started    3m50s (x3 over 6m47s)  kubelet, k8s-node1  Started container liveness
  Normal   Pulled     3m50s                  kubelet, k8s-node1  Successfully pulled image "busybox" in 15.626708424s
  Normal   Killing    3m6s (x3 over 6m6s)    kubelet, k8s-node1  Container liveness failed liveness probe, will be restarted
  Normal   Pulling    2m35s (x4 over 7m4s)   kubelet, k8s-node1  Pulling image "busybox"
  Warning  Unhealthy  2m1s (x10 over 6m16s)  kubelet, k8s-node1  Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory
[root@k8s-master yaml]# kubectl get pods -o wide
NAME                     READY   STATUS    RESTARTS   AGE    IP             NODE        NOMINATED NODE   READINESS GATES
liveness-exec            1/1     Running   4          7m8s   10.244.36.75   k8s-node1   <none>           <none>

容器在初始化后,首先創建一個 /tmp/healthy 文件,然后執行睡眠命令,睡眠 30 秒,到時間后執行刪除 /tmp/healthy 文件命令。而設置的存活探針檢檢測方式為執行 shell 命令,用 cat 命令輸出 healthy 文件的內容,如果能成功執行這條命令,存活探針就認為探測成功,否則探測失敗。在前 30 秒內,由於文件存在,所以存活探針探測時執行 cat /tmp/healthy 命令成功執行。30 秒后 healthy 文件被刪除,所以執行命令失敗,Kubernetes 會根據 Pod 設置的重啟策略來判斷,是否重啟 Pod。

 

2)通過HTTP方式做健康探測

示例文件 liveness-http.yaml

apiVersion: v1
kind: Pod
metadata:
  name: liveness-http
  labels:
    test: liveness
spec:
  containers:
  - name: liveness
    image: wuxinchun/springboot-helloworld:v1
    livenessProbe:
      initialDelaySeconds: 20   #延遲加載時間
      periodSeconds: 5          #重試時間間隔
      timeoutSeconds: 10        #超時時間設置
      httpGet:
        scheme: HTTP
        port: 8081
        path: /actuator/healthtest  #這是測試path,正確的地址為:/actuator/health

查看Pod日志

[root@k8s-master yaml]# kubectl describe pod liveness-http
Events:
  Type     Reason     Age                  From                Message
  ----     ------     ----                 ----                -------
  Normal   Scheduled  2m28s                                    Successfully assigned default/liveness-http to k8s-node1
  Normal   Pulled     46s (x4 over 2m28s)  kubelet, k8s-node1  Container image "mydlqclub/springboot-helloworld:0.0.1" already present on machine
  Normal   Created    46s (x4 over 2m28s)  kubelet, k8s-node1  Created container liveness
  Normal   Killing    46s (x3 over 116s)   kubelet, k8s-node1  Container liveness failed liveness probe, will be restarted
  Normal   Started    45s (x4 over 2m28s)  kubelet, k8s-node1  Started container liveness
  Warning  Unhealthy  21s (x10 over 2m6s)  kubelet, k8s-node1  Liveness probe failed: HTTP probe failed with statuscode: 404
[root@k8s-master yaml]# kubectl get pods -o wide
NAME                     READY   STATUS    RESTARTS   AGE     IP             NODE        NOMINATED NODE   READINESS GATES
liveness-http            1/1     Running   4          2m33s   10.244.36.77   k8s-node1   <none>           <none>
nginx-6799fc88d8-s4nqr   1/1     Running   0          3d3h    10.244.36.65   k8s-node1   <none>           <none>

上面 Pod 中啟動的容器是一個 SpringBoot 應用,其中引用了 Actuator 組件,提供了 /actuator/health 健康檢查地址,存活探針可以使用 HTTPGet 方式向服務發起請求,請求 8081 端口的 /actuator/health 路徑來進行存活判斷:

  • 任何大於或等於200且小於400的代碼表示探測成功。
  • 任何其他代碼表示失敗。

如果探測失敗,則會殺死 Pod 進行重啟操作。

httpGet探測方式有如下可選的控制字段:

  • scheme: 用於連接host的協議,默認為HTTP。
  • host: 要連接的主機名,默認為Pod IP,可以在http request head中設置host頭部。
  • port: 容器上要訪問端口號或名稱。
  • path: http服務器上的訪問URI。
  • httpHeaders: 自定義HTTP請求headers,HTTP允許重復headers。

 

3)通過TCP方式做健康探測

示例文件 liveness-tcp.yaml

apiVersion: v1
kind: Pod
metadata:
  name: liveness-tcp
  labels:
    app: liveness
spec:
  containers:
  - name: liveness
    image: nginx
    livenessProbe:
      initialDelaySeconds: 15   #執行第一次探測之前等待15秒
      periodSeconds: 20         #每20秒執行一次活躍度探測
      tcpSocket:
        port: 81                #測試端口81,實際端口為80

 

查看Pod日志

[root@k8s-master yaml]# kubectl describe pod liveness-tcp
Events:
  Type     Reason     Age               From                Message
  ----     ------     ----              ----                -------
  Normal   Scheduled  77s                                   Successfully assigned default/liveness-tcp to k8s-node1
  Normal   Pulled     72s               kubelet, k8s-node1  Successfully pulled image "nginx" in 4.873943634s
  Normal   Created    72s               kubelet, k8s-node1  Created container liveness
  Normal   Started    72s               kubelet, k8s-node1  Started container liveness
  Normal   Pulling    4s (x2 over 77s)  kubelet, k8s-node1  Pulling image "nginx"
  Warning  Unhealthy  4s (x3 over 44s)  kubelet, k8s-node1  Liveness probe failed: dial tcp 10.244.36.79:81: connect: connection refused
  Normal   Killing    4s                kubelet, k8s-node1  Container liveness failed liveness probe, will be restarted      #探針檢測失敗嘗試重啟容器
[root@k8s-master yaml]# kubectl get pods -o wide
NAME                     READY   STATUS    RESTARTS   AGE    IP             NODE        NOMINATED NODE   READINESS GATES
liveness-tcp             1/1     Running   0          83s    10.244.36.79   k8s-node1   <none>           <none>

TCP 檢查方式和 HTTP 檢查方式非常相似,在容器啟動 initialDelaySeconds 參數設定的時間后,kubelet 將發送第一個 livenessProbe 探針,嘗試連接容器的 80 端口,如果連接失敗則將殺死 Pod 重啟容器。

 

2、ReadinessProbe 探針使用示例

Pod 的 ReadinessProbe 探針使用方式和 LivenessProbe 探針探測方法一樣,也是支持三種,只是一個是用於探測應用的存活,一個是判斷是否對外提供流量的條件。這里用一個 Springboot 項目,設置 ReadinessProbe 探測 SpringBoot 項目的 8081 端口下的 /actuator/health 接口,如果探測成功則代表內部程序以及啟動,就開放對外提供接口訪問,否則內部應用沒有成功啟動,暫不對外提供訪問,直到就緒探針探測成功。

示例文件 readiness-exec.yaml

apiVersion: v1
kind: Service
metadata:
  name: springboot
  labels:
    app: springboot
spec:
  type: NodePort
  ports:
  - name: server
    port: 8080
    targetPort: 8080
    nodePort: 31180
  - name: management
    port: 8081
    targetPort: 8081
    nodePort: 31181
  selector:
    app: springboot
---
apiVersion: v1
kind: Pod
metadata:
  name: springboot
  labels:
    app: springboot
spec:
  containers:
  - name: springboot
    image: wuxinchun/springboot-helloworld:v1
    ports:
    - name: server
      containerPort: 8080
    - name: management
      containerPort: 8081
    readinessProbe:
      initialDelaySeconds: 20   
      periodSeconds: 5          
      timeoutSeconds: 10   
      httpGet:
        scheme: HTTP
        port: 8081
        path: /actuator/healthtest     #測試地址,實際path為:/actuator/health

查看日志

[root@k8s-master yaml]# kubectl describe pod springboot
Events:
  Type     Reason     Age                  From                Message
  ----     ------     ----                 ----                -------
  Normal   Scheduled  20m                                      Successfully assigned default/springboot to k8s-node1
  Normal   Pulled     20m                  kubelet, k8s-node1  Container image "mydlqclub/springboot-helloworld:0.0.1" already present on machine
  Normal   Created    20m                  kubelet, k8s-node1  Created container springboot
  Normal   Started    20m                  kubelet, k8s-node1  Started container springboot
  Warning  Unhealthy  53s (x237 over 20m)  kubelet, k8s-node1  Readiness probe failed: HTTP probe failed with statuscode: 404
[root@k8s-master yaml]# kubectl get ep
NAME         ENDPOINTS          AGE
springboot                      21m

readinessProbe探測失敗,會將 Pod 的 IP:Port 從對應的 EndPoint 列表中刪除

 

3、ReadinessProbe + LivenessProbe 配合使用示例

一般程序中需要設置兩種探針結合使用,並且也要結合實際情況,來配置初始化檢查時間和檢測間隔,下面列一個簡單的 SpringBoot 項目的 Deployment 例子。

apiVersion: v1
kind: Service
metadata:
  name: springboot
  labels:
    app: springboot
spec:
  type: NodePort
  ports:
    - name: server
      port: 8080
      targetPort: 8080
      nodePort: 31180
    - name: management
      port: 8081
      targetPort: 8081
      nodePort: 31181
  selector:
    app: springboot
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: springboot
  labels:
    app: springboot
spec:
  replicas: 1
  selector:
    matchLabels:
      app: springboot
  template:
    metadata:
      name: springboot
      labels:
        app: springboot
    spec:
      containers:
        - name: readiness
          image: wuxinchun/springboot-helloworld:v1
          ports:
            - name: server
              containerPort: 8080
            - name: management
              containerPort: 8081
          readinessProbe:
            initialDelaySeconds: 20
            periodSeconds: 5
            timeoutSeconds: 10
            httpGet:
              scheme: HTTP
              port: 8081
              path: /actuator/health
          livenessProbe:
            initialDelaySeconds: 30
            periodSeconds: 10
            timeoutSeconds: 5
            httpGet:
              scheme: HTTP
              port: 8081
              path: /actuator/health

 


免責聲明!

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



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