kubernetes之pod健康檢查


kubernetes之pod健康檢查

1、概述和分類

pod通過兩類探針來檢查容器的健康狀態。分別是LivenessProbe(存活性探測)和ReadinessProbe(就緒型探測)

2、LivenessProbe探針(存活性探測)

用於判斷容器是否健康(Running狀態)並反饋給kubelet。有不少應用程序長時間持續運行后會逐漸轉為不可用的狀態,並且僅能通過重啟操作恢復,kubernetes的容器存活性探測機制可發現諸如此類問題,並依據探測結果結合重啟策略觸發后的行為。存活性探測是隸屬於容器級別的配置,kubelet可基於它判定何時需要重啟一個容器。如果一個容器不包含LivenessProbe探針,那么kubelet認為該容器的LivenessProbe探針返回的值永遠是Success。Pod spec為容器列表中的相應容器定義其專用的探針即可啟用存活性檢測,目前,kubernetes的容器支持存活性檢測的方法包含以下三種:ExecAction、TCPSocketAction和HTTPGetAction。

3、ReadinessProbe探針(就緒型探測)

用於判斷容器服務是否可用(Ready狀態),達到Ready狀態的Pod才可以接收請求。對於被Service管理的Pod,Service與Pod Endpoint的關聯關系也將基於Pod是否Ready進行設置。Pod對象啟動后,容器應用通常需要一段時間才能完成其初始化的過程,例如加載配置或數據,甚至有些程序需要運行某類的預熱過程,若在此階段完成之前即接入客戶端的請求,勢必會因為等待太久而影響用戶體驗。因此應該避免於Pod對象啟動后立即讓其處理客戶端請求。而是等待容器初始化工作執行完成並轉為Ready狀態。尤其是存在其他提供相同服務的Pod對象的場景更是如此。如果在運行過程中Ready狀態變為False,則系統自動將其從Service的后端Endpoint列表中隔離出去,后續再把恢復到Ready狀態的Pod加回后端Endpoint列表。這樣就能保證客戶端在訪問Service時不會被轉發到服務不可用的Pod示例上。

4、探針的實現方式

LivenessProbeReadinessProbe均可配置以下三種探針實現方式:
可參考官方文檔:https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/

4.1、ExecAction

通過在目標容器中執行由用戶自定義的命令來判定容器的健康狀態,即在容器內部執行一個命令,如果改命令的返回碼為0,則表明容器健康。spec.containers.LivenessProbe字段用於定義此類檢測,它只有一個可用屬性command,用於指定要執行的命令,下面是在資源清單文件中使用liveness-exec方式的示例:

apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness-exec
  name: liveness-exec
spec:
  containers:
  - name: liveness-demo
    image: busybox
    args:
    - /bin/sh
    - -c
    - touch /tmp/healthy; sleep 60; rm -rf /tmp/healthy; sleep 600
    livenessProbe:
      exec:
        command:
        - test
        - -e
        - /tmp/healthy
      initialDelaySeconds: 15
      timeoutSeconds: 1

上面的資源清單中定義了一個Pod對象,基於busybox鏡像啟動一個運行“touch /tmp/healthy; sleep 60; rm -rf /tmp/healthy; sleep 600”命令的容器,此命令在容器啟動時創建/tmp/healthy文件,並於60秒之后將其刪除,存活性探針運行“test -e /tmp/healthy”命令檢查文件的存在性,若文件存在則返回狀態碼為0,表示成功通過測試。
創建該資源,並通過kubectl describe pods liveness-exec查看詳細信息

Containers:
  liveness-demo:
    Container ID:  docker://a2974585905bdeef4ab39ba9a87bf710a61beae5180f31907ba33c8725c0bf79
    Image:         busybox
    Image ID:      docker-pullable://busybox@sha256:895ab622e92e18d6b461d671081757af7dbaa3b00e3e28e12505af7817f73649
    Port:          <none>
    Host Port:     <none>
    Args:
      /bin/sh
      -c
      touch /tmp/healthy; sleep 60; rm -rf /tmp/healthy; sleep 600
    State:          Running
      Started:      Wed, 14 Aug 2019 11:26:09 +0800
    Last State:     Terminated
      Reason:       Error
      Exit Code:    137
      Started:      Wed, 14 Aug 2019 11:24:10 +0800
      Finished:     Wed, 14 Aug 2019 11:26:08 +0800
    Ready:          True
    Restart Count:  2
    Liveness:       exec [test -e /tmp/healthy] delay=0s timeout=1s period=10s #success=1 #failure=3
    Environment:    <none>
......
Events:
  Type     Reason     Age                  From                  Message
  ----     ------     ----                 ----                  -------
  Normal   Scheduled  2m26s                default-scheduler     Successfully assigned default/liveness-exec to 172.16.1.66
  Warning  Unhealthy  57s (x3 over 77s)    kubelet, 172.16.1.66  Liveness probe failed:
  Normal   Pulling    27s (x2 over 2m23s)  kubelet, 172.16.1.66  pulling image "busybox"
  Normal   Pulled     27s (x2 over 2m23s)  kubelet, 172.16.1.66  Successfully pulled image "busybox"
  Normal   Killing    27s                  kubelet, 172.16.1.66  Killing container with id docker://liveness-demo:Container failed liveness probe.. Container will be killed and recreated.
  Normal   Created    26s (x2 over 2m22s)  kubelet, 172.16.1.66  Created container
  Normal   Started    25s (x2 over 2m21s)  kubelet, 172.16.1.66  Started container

輸出信息中清晰的顯示了容器健康狀態檢測變化的相關信息:容器當前處於Running狀態,但前一次是Terminated,原因是退出碼為137的錯誤信息,它表示進程是被外部信號所終止的。137事實上是由兩部分數字之和生成的:128+signum,其中signum是導致進程終止信號的數字標識。9標識SIGKILL,這意味着進程是被強行終止的
待容器重啟完成后再次查看,容器已經處於正常運行狀態,直到文件再次被刪除,存活性探測失敗而重啟,從下面結果可以看出,名為liveness-exec的pod在10分鍾內重啟了5次

[root@master01 demo]# kubectl get pods liveness-exec 
NAME            READY   STATUS    RESTARTS   AGE
liveness-exec   1/1     Running   5          10m

需要注意的是,exec指定的命令運行於容器中,會消耗容器的可用資源配額,另外,考慮到探針操作的效率本身等因素,探針操作的命令應該盡可能簡單和輕量。

4.2、HTTPGetAction

通過容器的ip地址,端口號及路徑調用HTTPGet方法,如果響應的狀態碼大於等於200且小於400,則認為容器健康,spec.containers.livenessProbe.httpGet字段用於定義此類檢測,它的可用配置字段包括如下幾個:

  • host :請求的主機地址,默認為 Pod IP;也可以在 httpHeaders中使用 Host:來定義
  • port :請求的端口,必選字段
  • httpHeader <[]Object>:自定義的請求報文首部
  • path :請求的HTTP資源路徑,即 URL path
  • scheme:建立連接使用的協議,僅可為HTTPHTTPS,默認為HTTP
    下面是在資源清單文件中使用liveness-http方式的示例,通過lifecycle最后那個的postStart hook創建了一個專用於httpGet測試的頁面文件healthz
apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-http
spec:
  containers:
  - name: liveness-demo
    image: nginx:1.12-alpine
    ports:
    - name: http
      containerPort: 80
    lifecycle:
      postStart:
        exec:
          command:
          - /bin/sh
          - -c
          - 'echo Healty > /usr/share/nginx/html/healthz'
    livenessProbe:
      httpGet:
        path: /healthz
        port: http
        scheme: HTTP
      initialDelaySeconds: 30
      timeoutSeconds: 1

上面的清單文件中定義的httpGet測試中,請求的資源路徑為/healthz,地址默認為Pod IP,端口使用了容器中定義的端口名稱HTTP,這也是明確為容器指明要暴露的端口的用途之一,通過kubectl describe pods liveness-http查看容器正常運行,健康狀態檢測為正常

Containers:
  liveness-demo:
    Container ID:   docker://bf05e0a9e6e1ac95f67b91f0b167b9fc2e3ad0bd0ffa4336debcc4b3c24978a7
    Image:          nginx:1.12-alpine
    Image ID:       docker-pullable://nginx@sha256:3a7edf11b0448f171df8f4acac8850a55eff30d1d78c46cd65e7bc8260b0be5d
    Port:           80/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Wed, 14 Aug 2019 12:01:31 +0800
    Ready:          True
    Restart Count:  0
    Liveness:       http-get http://:http/healthz delay=30s timeout=1s period=10s #success=1 #failure=3
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-g7ls6 (ro)
Conditions:
  Type              Status
  Initialized       True 
  Ready             True 
  ContainersReady   True 
  PodScheduled      True 
Volumes:
  default-token-g7ls6:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-g7ls6
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason     Age    From                  Message
  ----    ------     ----   ----                  -------
  Normal  Scheduled  6m51s  default-scheduler     Successfully assigned default/liveness-http to 172.16.1.66
  Normal  Pulling    6m48s  kubelet, 172.16.1.66  pulling image "nginx:1.12-alpine"
  Normal  Pulled     6m43s  kubelet, 172.16.1.66  Successfully pulled image "nginx:1.12-alpine"
  Normal  Created    6m43s  kubelet, 172.16.1.66  Created container
  Normal  Started    6m42s  kubelet, 172.16.1.66  Started container

通過kubectl exec命令刪除經由postStart hook創建的測試頁面healthz

kubectl exec liveness-http rm /usr/share/nginx/html/healthz

再次查看資源詳細信息,事件輸出中的信息表明探測失敗,容器被殺掉后被重新創建

......
Events:
  Type     Reason     Age               From                  Message
  ----     ------     ----              ----                  -------
  Normal   Scheduled  12m               default-scheduler     Successfully assigned default/liveness-http to 172.16.1.66
  Normal   Pulling    12m               kubelet, 172.16.1.66  pulling image "nginx:1.12-alpine"
  Normal   Pulled     12m               kubelet, 172.16.1.66  Successfully pulled image "nginx:1.12-alpine"
  Warning  Unhealthy  3s (x3 over 23s)  kubelet, 172.16.1.66  Liveness probe failed: HTTP probe failed with statuscode: 404
  Normal   Created    2s (x2 over 12m)  kubelet, 172.16.1.66  Created container
  Normal   Killing    2s                kubelet, 172.16.1.66  Killing container with id docker://liveness-demo:Container failed liveness probe.. Container will be killed and recreated.
  Normal   Pulled     2s                kubelet, 172.16.1.66  Container image "nginx:1.12-alpine" already present on machine
  Normal   Started    1s (x2 over 12m)  kubelet, 172.16.1.66  Started container

一般來說,HTTP類型的探測操作應該針對專用的URL路徑進行,例如,示例中為其准備的/healthz,另外,此URL路徑對應的web資源應該以輕量化的方式在內部對應用程序的各關鍵組件進行全面檢測以確保它們可以正常向客戶端提供完整的服務。
這種檢測方式僅對分層架構中的當前一層有效,例如,它能檢測應用程序工作正常與否的狀態,但重啟操作卻無法解決其后端服務(如數據庫或緩存服務)導致的故障,此時,容器可能會被一次次重啟,直到后端服務恢復正常為止。

4.3、TCPSocketAction

通過容器的IP地址和端口號進行TCP檢查,如果能夠建立TCP連接,則表明容器健康。相比較來說,它比基於HTTP的探測要更高效,更節約資源,但精准度略低,畢竟建立連接成功未必意味着頁面資源可用,spec.containers.livenessProbe.tcpSocket字段用於定義此類檢測,它主要包含以下兩個可用的屬性:

  • host :請求連接的目標 IP地址,默認為 Pod IP
  • port :請求連接的目標端口,必選字段
    下面是在資源清單文件中使用 liveness-tcp方式的示例,它向 Pod IP的80/tcp端口發起連接請求,並根據連接建立的狀態判定測試結果:
apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-tcp
spec:
  containers:
  - name: liveness-tcp-demo
    image: nginx:1.12-alpine
    ports:
    - name: http
      containerPort: 80
    livenessProbe:
      tcpSocket:
        port: 80
      initialDelaySeconds: 30
      timeoutSeconds: 1

通過kubectl describe pods liveness-http查看容器正常運行,健康狀態檢測為正常

Containers:
  liveness-tcp-demo:
    Container ID:   docker://816b27781aeb384e1305e0a5badebd5ea21ea98c834e62179cd1dac2a704ccd7
    Image:          nginx:1.12-alpine
    Image ID:       docker-pullable://nginx@sha256:3a7edf11b0448f171df8f4acac8850a55eff30d1d78c46cd65e7bc8260b0be5d
    Port:           80/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Wed, 14 Aug 2019 12:29:12 +0800
    Ready:          True
    Restart Count:  0
    Liveness:       tcp-socket :80 delay=30s timeout=1s period=10s #success=1 #failure=3
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-g7ls6 (ro)
Conditions:
  Type              Status
  Initialized       True 
  Ready             True 
  ContainersReady   True 
  PodScheduled      True 
Volumes:
  default-token-g7ls6:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-g7ls6
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason     Age   From                  Message
  ----    ------     ----  ----                  -------
  Normal  Scheduled  62s   default-scheduler     Successfully assigned default/liveness-tcp to 172.16.1.66
  Normal  Pulled     60s   kubelet, 172.16.1.66  Container image "nginx:1.12-alpine" already present on machine
  Normal  Created    60s   kubelet, 172.16.1.66  Created container
  Normal  Started    59s   kubelet, 172.16.1.66  Started container

5、探測行為屬性

使用kubectl describe命令查看配置了存活性探測或者就緒型探測對象的詳細信息時,其相關內容中會包含如下內容:

Liveness:       exec [test -e /tmp/healthy] delay=15s timeout=1s period=10s #success=1 #failure=3

它給出了探測方式及其額外的配置屬性delaytimeoutperiodsuccessfailure及其各自的相關屬性值,用戶沒有明確定義這些屬性字段時,他們會使用各自的默認值,這些屬性值可通過spec.containers.livenessProbe的如下屬性字段來給出:

  • initialDelaySeconds <integer> :存活性探測延遲時長,即容器啟動多久后再開始第一次探測操作,顯示為delay屬性,默認為0秒,即容器啟動后立刻開始進行探測。
  • timeoutSeconds <integer>:存活性探測的超時時長,顯示為timeout屬性,默認為1s,最小值也為1s。
  • periodSeconds <integer>:存活性探測的頻度,顯示為period屬性,默認為10s,最小值為1s;過高的頻率會對pod對象帶來較大的額外開銷,而過低的頻率又會使得對錯誤的反應不及時。
  • successThreshold <integer>:處於失敗狀態時,探測操作至少連續多少次的成功才被認為是通過檢測,顯示為#success屬性,默認值為1,最小值也為1。
  • failureThreshold:處於成功狀態時,探測操作至少連續多少次的失敗才被視為是檢測不通過,顯示為#failure屬性,默認值為3,最小值為1。

6、擴展的探測機制

kubernetesReadinessProbe機制可能無法滿足某些復雜應用對容器內服務可用狀態的判斷,所以kubernetes1.11版本開始引入了Pod Ready++特性對Readiness探測機制進行擴展,在1.14版本時達到GA穩定版本,稱其為Pod Readiness Gates
通過Pod Readiness Gates機制,用戶可以將自定義的ReadinessProbe探測方式設置在Pod上,輔助kubernetes設置Pod何時達到服務可用狀態Ready,為了使自定義的ReadinessProbe生效,用戶需要提供一個外部的控制器Controller來設置相應的Condition狀態。PodReadiness Gatespod定義中的ReadinessGates字段進行設置,如下示例設置了一個類型為www.example.com/feature-1的新Readiness Gates

Kind: Pod
......
spec:
  readinessGates:
    - conditionType: "www.example.com/feature-1"
status:
  conditions:
    - type: Ready  # kubernetes系統內置的名為Ready的Condition
      status: "True"
      lastProbeTime: null
      lastTransitionTime: 2018-01-01T00:00:00Z
    - type: "www.example.com/feature-1"   # 用戶定義的Condition
      status: "False"
      lastProbeTime: null
      lastTransitionTime: 2018-01-01T00:00:00Z
  containerStatuses:
    - containerID: docker://abcd...
      ready: true
......

新增的自定義Condition的狀態status將由用戶自定義的外部控制器設置,默認值為Falsekubernetes將在判斷全部readinessGates條件都為True時,才設置pod為服務可用狀態(Ready或True)
參考地址:https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-readiness-gate


免責聲明!

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



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