Kubernetes:健康檢查

不羈的羅恩發表於2022-02-17

Blog:部落格園 個人

應用在執行過程中難免會出現錯誤,如程式異常、軟體異常、硬體故障、網路故障等。因此,系統通過一些手段來判斷應用是否執行正常,這些手段稱之為健康檢查(診斷)。

前置知識

回顧一下Pod的生命週期:

image-20220217105117106

檢查機制(Check mechanisms)

有以下幾種方法來檢查容器:

  • exec:在容器內執行指定命令。如果命令退出時返回碼為 0 則認為診斷成功。
  • gRPC:使用gRPC執行遠端過程呼叫。目標應該實施gRPC執行狀況檢查。如果響應的狀態為SERVING,則認為診斷成功。gRPC檢查是一項Alpha功能,僅當您啟用GRPCContainerProbe時才可用。
  • httpGet:對容器的 IP 地址上指定埠和路徑執行 HTTP Get 請求。如果響應的狀態碼大於等於 200 且小於 400,則診斷被認為是成功的。
  • tcpSocket:對容器的 IP 地址上的指定埠執行 TCP 檢查。如果埠開啟,則診斷被認為是成功的。

每次探測都將獲得以下三種結果之一:

  • Success(成功):容器通過了診斷。
  • Failure(失敗):容器未通過診斷。
  • Unknown(未知):診斷失敗,因此不會採取任何行動。

針對執行中的容器,kubelet 可以選擇是否執行以下三種探針,以及如何針對探測結果作出反應:

  • livenessProbe:指示容器是否正在執行。如果存活態探測失敗,則 kubelet 會殺死容器, 並且容器將根據其重啟策略決定未來。如果容器不提供存活探針, 則預設狀態為 Success
  • readinessProbe:指示容器是否準備好為請求提供服務。如果就緒態探測失敗, 端點控制器將從與 Pod 匹配的所有服務的端點列表中刪除該 Pod 的 IP 地址。 初始延遲之前的就緒態的狀態值預設為 Failure。 如果容器不提供就緒態探針,則預設狀態為 Success
  • startupProbe: 指示容器中的應用是否已經啟動。如果提供了啟動探針,則所有其他探針都會被 禁用,直到此探針成功為止。如果啟動探測失敗,kubelet 將殺死容器,而容器依其重啟策略進行重啟。 如果容器沒有提供啟動探測,則預設狀態為 Success

exec方式檢測存活示例

建立一個 Pod,其中執行一個基於 busybox 映象的容器:

apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-exec
spec:
  containers:
  - name: liveness
    image: registry.aliyuncs.com/google_containers/busybox
    args:
    - /bin/sh
    - -c
    - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
    livenessProbe:
      exec:
        command:
        - cat
        - /tmp/healthy
      initialDelaySeconds: 5
      periodSeconds: 5

當容器啟動時,執行如下的命令:

/bin/sh -c "touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600"

這個容器生命的前 30 秒, /tmp/healthy 檔案是存在的。 所以在這最開始的 30 秒內,執行命令 cat /tmp/healthy 會返回成功程式碼。 30 秒之後,執行命令 cat /tmp/healthy 就會返回失敗程式碼。

事件如下:

Events:
  Type     Reason     Age              From               Message
  ----     ------     ----             ----               -------
  Normal   Scheduled  41s              default-scheduler  Successfully assigned default/liveness-exec to node-1
  Normal   Pulling    40s              kubelet            Pulling image "registry.aliyuncs.com/google_containers/busybox"
  Normal   Pulled     39s              kubelet            Successfully pulled image "registry.aliyuncs.com/google_containers/busybox" in 727.748993ms
  Normal   Created    39s              kubelet            Created container liveness
  Normal   Started    39s              kubelet            Started container liveness
  Warning  Unhealthy  1s (x2 over 6s)  kubelet            Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory

檢檢視這個容器被重啟了:

[root@master test]# kubectl get pod
NAME            READY   STATUS    RESTARTS   AGE
liveness-exec   1/1     Running   1          82s

httpGet方式檢測存活示例

建立一個 Pod ,其中執行一個基於 liveness 映象的容器:

apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-http
spec:
  containers:
  - name: liveness
    image: mirrorgooglecontainers/liveness
    args:
    - /server
    livenessProbe:
      httpGet:
        path: /healthz
        port: 8080
        httpHeaders:
        - name: Custom-Header
          value: Awesome
      initialDelaySeconds: 3
      periodSeconds: 3

通過看 Pod 事件來檢測存活探測器已經失敗了並且容器被重新啟動了。

kubectl describe pod liveness-http

事件如下:

Events:
  Type     Reason     Age                From               Message
  ----     ------     ----               ----               -------
  Normal   Scheduled  100s               default-scheduler  Successfully assigned default/liveness-http to node-1
  Normal   Pulled     84s                kubelet            Successfully pulled image "mirrorgooglecontainers/liveness" in 15.537483195s
  Normal   Pulled     52s                kubelet            Successfully pulled image "mirrorgooglecontainers/liveness" in 15.375906607s
  Normal   Pulled     19s                kubelet            Successfully pulled image "mirrorgooglecontainers/liveness" in 15.388654652s
  Normal   Created    18s (x3 over 83s)  kubelet            Created container liveness
  Normal   Started    18s (x3 over 83s)  kubelet            Started container liveness
  Warning  Unhealthy  1s (x9 over 73s)   kubelet            Liveness probe failed: HTTP probe failed with statuscode: 500
  Normal   Killing    1s (x3 over 67s)   kubelet            Container liveness failed liveness probe, will be restarted
  Normal   Pulling    1s (x4 over 99s)   kubelet            Pulling image "mirrorgooglecontainers/liveness"

tcpSocket方式檢測存活示例

建立一個 Pod ,其中執行一個基於 goproxy 映象的容器:

apiVersion: v1
kind: Pod
metadata:
  name: goproxy
  labels:
    app: goproxy
spec:
  containers:
  - name: goproxy
    image: mirrorgooglecontainers/goproxy:0.1
    ports:
    - containerPort: 8080
    readinessProbe:
      tcpSocket:
        port: 8080
      initialDelaySeconds: 5
      periodSeconds: 10
    livenessProbe:
      tcpSocket:
        port: 8080
      initialDelaySeconds: 15
      periodSeconds: 20

kubelet 會在容器啟動 5 秒後傳送第一個就緒探測。 這會嘗試連線 goproxy 容器的 8080 埠。 如果探測成功,這個 Pod 會被標記為就緒狀態,kubelet 將繼續每隔 10 秒執行一次檢測。

除了就緒探測,這個配置包括了一個存活探測。 kubelet 會在容器啟動 15 秒後進行第一次存活探測。 與就緒探測類似,會嘗試連線 goproxy 容器的 8080 埠。 如果存活探測失敗,這個容器會被重新啟動。

相關文章