Kubernetes-POD的健康檢查

&UnstopPable發表於2024-08-10

目錄
  • 簡介
  • 什麼是探針
    • Liveness Probe(存活探針)
    • Readiness Probe(就緒探針)
    • Startup Probe(啟動探針)
  • 什麼時候使用探針?
    • 何時使用存活探針(Liveness Probe)
    • 何時使用就緒探針(Read iness Probe)
    • 何時使用啟動探針(Startup Probe)
  • 容器探測方法
    • exec
    • httpGet
    • tcpSocket
  • 容器探測使用
    • livenessProbe使用
      • exec使用
      • httpGet使用
      • tcpSocket
    • readinessProbe使用
      • exec使用
      • httpGet使用
      • tcpSocket使用
    • startupProbe使用
      • httpGet使用
      • tcpSocket使用

簡介

在Pod的生命週期中,可以執行多種操作如下圖:

  1. 初始化容器:主容器啟動前,可以先執行一個或多個初始化容器。初始化容器是序列執行的,必須全部成功完成後才會啟動主容器。初始化容器執行結束後即退出,不再佔用資源。
  2. Post Start鉤子:主容器啟動後,可以指定一個Post Start鉤子,用於在主容器啟動後執行一些額外的操作。
  3. Pre Stop鉤子:在主容器終止之前,可以指定一個Pre Stop鉤子,用於在主容器結束前執行必要的清理或其他操作。
  4. 健康探針:Pod啟動後,其健康狀態由以下幾類探針進行檢測:
    • Startup Probe(啟動探針):用於確保容器成功啟動,在啟動完成前其他探針不會干擾容器的啟動過程。
    • Liveness Probe(存活探針):用於檢測容器是否存活。如果探測失敗,Kubernetes會重啟該容器。
    • Readiness Probe(就緒探針):用於檢測容器是否已準備好接收流量。如果探測失敗,該Pod將暫時從服務端點中移除,直到其恢復就緒狀態。

什麼是探針

在Kubernetes中,探針(Probe)用於管理容器的生命週期,主要包括以下三種型別:

Liveness Probe(存活探針)

  • 作用:判斷容器是否處於執行狀態(即容器是否存活)。
  • 行為
    1. 如果Liveness Probe探測到容器處於非健康狀態,kubelet會殺掉該容器,並根據容器的重啟策略進行處理。
    2. 如果未配置Liveness Probe,kubelet會預設認為容器始終處於“成功”狀態。
  • 場景:Liveness Probe用於捕捉容器死鎖等問題。例如,當應用程式雖然執行但無法處理請求時,探針會檢測到這個問題,並重啟容器,使應用在存在bug的情況下依然能夠繼續執行。

Readiness Probe(就緒探針)

  • 作用:判斷容器是否已啟動完成並準備好接受請求。
  • 行為
    1. 如果Readiness Probe探測失敗,Pod的狀態會被修改,Endpoint Controller會將該Pod從Service的Endpoint中移除。
    2. 如果未配置Readiness Probe,kubelet會預設認為容器處於“成功”狀態。
  • 場景:Readiness Probe用於控制哪些Pod可以作為Service的後端。如果Pod處於非就緒狀態,它將被從Service的負載均衡中移除。

Startup Probe(啟動探針)

  • 作用:檢測應用程式是否已完全啟動。
  • 行為
    1. 在Startup Probe成功之前,其他探針(Liveness和Readiness)將被禁用。
    2. 如果Startup Probe探測失敗,kubelet將終止容器並根據重啟策略重啟它。
    3. 如果未配置Startup Probe,kubelet會預設認為容器已成功啟動。
  • 場景:Startup Probe適用於啟動時間較長的應用程式,確保應用完全啟動後再啟用其他探針。

透過合理配置這三類探針,可以確保Kubernetes中的容器在生命週期的各個階段都處於健康狀態,並能夠及時處理異常情況。

什麼時候使用探針?

何時使用存活探針(Liveness Probe)

  • 容器可能卡死或無響應:如果你的應用程式在遇到問題時可能卡死或進入無響應狀態,而不會自行崩潰,那麼就應該使用存活探針。Liveness Probe 可以檢測到這些狀態,並觸發 kubelet 終止並重啟容器。
  • 確保自動重啟:如果你希望容器在探測失敗時被殺死並重新啟動,以確保應用的持續可用性,那麼應配置存活探針。此時,可以將 restartPolicy 設定為 AlwaysOnFailure,以確保在探針檢測到問題時容器能夠自動重啟。

何時使用就緒探針(Read iness Probe)

  • 控制流量路由:如果你希望只有在探測成功時才開始向 Pod 傳送請求流量,就需要指定就緒探針。就緒探針常與存活探針相同,但它確保 Pod 在啟動階段不會接收任何資料,只有探測成功後才開始接收流量。
  • 維護狀態:如果希望容器能自行進入維護狀態,可以使用就緒探針,檢查與存活探針不同的特定端點。對於依賴於後端服務的應用程式,可以同時使用存活探針和就緒探針。存活探針檢測容器本身的健康狀況,而就緒探針則確保所需的後端服務可用,避免將流量導向出錯的 Pod。
  • Pod 刪除:注意,如果只是想在 Pod 被刪除時排空請求,通常不需要使用就緒探針。Pod 在刪除時會自動進入未就緒狀態,無論是否有就緒探針,直到容器停止為止。

何時使用啟動探針(Startup Probe)

  • 應用啟動慢:如果容器在啟動期間需要載入大型資料或配置檔案,可以使用啟動探針。它確保在啟動完成前不會觸發其他探針。

容器探測方法

exec

	執行一段命令,根據返回值判斷執行結果。
	返回值為0, 非0兩種結果,可以理解為"echo $?"。

httpGet

	透過發起HTTTP協議的GET請求檢測某個http請求的返回狀態碼,從而判斷服務是否正常。
    常見的狀態碼分為很多類,比如: "2xx,3xx"正常, "4xx,5xx"錯誤。
    	200: 返回狀態碼成功。
    	301: 永久跳轉,會將跳轉資訊快取到瀏覽器本地。
    	302: 臨時跳轉,並不會將本次跳轉快取到本地。
    	401: 驗證失敗。
    	403: 許可權被拒絕。
    	404: 檔案找不到。
    	413: 檔案上傳過大。
    	500: 伺服器內部錯誤。
    	502: 無效的請求。
    	504: 後端應用閘道器相應超時。

tcpSocket

測試某個TCP埠是否能夠連線,類似於telnet這樣的工具。

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

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

容器探測使用

livenessProbe使用

exec使用

apiVersion: v1
kind: Pod
metadata:
  name: livenessprobe-exec
spec:
  containers:  
    - name: nginx  
      image: nginx:1.18 
      ports:
        - containerPort: 80  
      args:  
        - /bin/sh
        - -c
        - touch /tmp/healthy; sleep 10; rm -rf /tmp/healthy; sleep 600
      # 定義健康檢查探針
      livenessProbe: 
        # 指定探針的檢測方法為exec。
        exec:  
          # 指定exec要執行的命令
          command:  
            - cat
            - /tmp/healthy
        # 指定第一次進行健康檢查的秒數,該值在生產環境中應該確保這個延遲時間內容器可以正常啟動執行。
        initialDelaySeconds: 15 
        # 指定每次週期的健康檢查的間隔時間。
        periodSeconds: 5 
        # 指定執行exec定義命令的超時的秒數。
        timeoutSeconds: 1  
        # 檢查1次成功就認為服務是健康的。
        successThreshold: 1  
        # 檢查連續3次失敗就認為服務是不健康的。
        failureThreshold: 3  

httpGet使用

apiVersion: v1
kind: Pod
metadata:
  name: livenessprobe-httpGet
spec:
  containers:  
    - name: nginx  
      image: nginx:1.18 
      ports:
        - containerPort: 80  
      # 定義健康檢查探針
      livenessProbe:
        httpGet:  # 指定探針的檢測方法為httpGet。
          path: /index.html  # 指定訪問的檔案路徑資訊即可,無需指定IP地址,因為預設就是訪問本機,可以理解為127.0.0.1。
          port: 80  # 指定對容器的哪個埠傳送GET請求。
        initialDelaySeconds: 15 
        # 指定每次週期的健康檢查的間隔時間。
        periodSeconds: 5 
        timeoutSeconds: 1  
        successThreshold: 1  
        failureThreshold: 3  

tcpSocket

apiVersion: apps/v1
kind: Deployment
metadata:
  name: livenessprobe-tcpsocket
spec:
  replicas: 1
  selector:
    matchLabels:
      app: livenessprobe-tcpsocket
  template:
    metadata:
      labels:
        app: livenessprobe-tcpsocket
    spec:
      containers:
        - name: nginx
          image: registry.cn-guangzhou.aliyuncs.com/jiajia-k8s/nginx:1.21
          ports:
            - containerPort: 80
          args:
            - /bin/sh
            - -c
            - tail -f /etc/hosts
          livenessProbe:
            tcpSocket:
              port: 80  # 檢測80埠是否可以連通,若連不通則會丟擲檢查容器出現問題,而後重啟容器。
            initialDelaySeconds: 10
            periodSeconds: 3
            successThreshold: 1  
            failureThreshold: 2
很明顯,上述案例暴露了80埠,由於啟動容器時並沒有啟動nginx,而是去使用tail指令去檢視一個檔案內容達到阻塞容器的目的,因此在容器啟動10後就開始第一次檢查,而後每個3秒檢查1次,達到指定次數後會觸發重啟操作,可以看到55秒內探測了4次,52秒內重啟了兩次

image.png

readinessProbe使用

exec使用

apiVersion: apps/v1
kind: Deployment
metadata:
  name: readinessProbe-exec
  labels:
     apps: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      apps: nginx
  template:
     metadata:
       name: nginx
       labels:
         apps: nginx
     spec:
       containers:
       - name: nginx
         image: nginx:1.18
         command: 
         - /bin/bash
         - -c
         - touch /tmp/nginx-healthy; sleep 60; rm -f /tmp/nginx-healthy; sleep 60;
         livenessProbe:
           exec:
             command:
             - cat
             - /tmp/nginx-healthy
           failureThreshold: 3
           initialDelaySeconds: 15
           periodSeconds: 1
           successThreshold: 1
           timeoutSeconds: 1
         readinessProbe:
           exec:
             command:
             - cat
             - /tmp/nginx-healthy-2023
           failureThreshold: 3
           initialDelaySeconds: 15
           periodSeconds: 1
           successThreshold: 1
           timeoutSeconds: 1

從事件日誌來看,Liveness ProbeReadiness Probe 都因為無法找到 /tmp/nginx-healthy 檔案而失敗。這是由於容器中的命令在 60 秒後刪除了該檔案,導致探針在檢查時無法訪問該檔案。

  • Liveness Probe 失敗觸發了容器重啟。此探針用於檢測容器是否健康,不健康時會重啟容器。
  • Readiness Probe 失敗使得 Pod 從 Service 的 Endpoints 列表中移除,導致 Pod 無法接收流量。這表示 Pod 當前無法處理請求。

image.png
image.png
image.png

httpGet使用

apiVersion: apps/v1
kind: Deployment
metadata:
  name: readinessprobe-httpget
spec:
  replicas: 1
  selector:
    matchLabels:
      app: readinessprobe-httpget
  template:
    metadata:
      labels:
        app: readinessprobe-httpget
    spec:
      containers:
        - name: nginx
          image: nginx:1.21
          ports:
            - containerPort: 80
          readinessProbe:
            httpGet:
              path: /healthz        # HTTP 請求的路徑
              port: 80              # 容器內服務的埠
            initialDelaySeconds: 15
            periodSeconds: 5
            failureThreshold: 3
            successThreshold: 1
            timeoutSeconds: 1

tcpSocket使用

apiVersion: apps/v1
kind: Deployment
metadata:
  name: readinessprobe-tcpsocket
spec:
  replicas: 1
  selector:
    matchLabels:
      app: readinessprobe-tcpsocket
  template:
    metadata:
      labels:
        app: readinessprobe-tcpsocket
    spec:
      containers:
        - name: nginx
          image: nginx:1.21
          ports:
            - containerPort: 80
          livenessProbe:
            tcpSocket:
              port: 80
            failureThreshold: 3
            initialDelaySeconds: 30
            periodSeconds: 1
            successThreshold: 1
            timeoutSeconds: 1
          readinessProbe:
            tcpSocket:
              port: 80
            initialDelaySeconds: 15
            periodSeconds: 5
            failureThreshold: 3
            successThreshold: 1
            timeoutSeconds: 1

startupProbe使用

httpGet使用

apiVersion: apps/v1
kind: Deployment
metadata:
  name: startupprobe-httpget
spec:
  replicas: 1
  selector:
    matchLabels:
      app: startupprobe-httpget
  template:
    metadata:
      labels:
        app: startupprobe-httpget
    spec:
      containers:
        - name: nginx
          image: nginx:1.21
          ports:
            - containerPort: 80
          startupProbe:
            httpGet:
              path: /startup
              port: 80
            initialDelaySeconds: 30
            periodSeconds: 10
            failureThreshold: 10
            timeoutSeconds: 5

tcpSocket使用

apiVersion: apps/v1
kind: Deployment
metadata:
  name: startupprobe-tcpsocket
spec:
  replicas: 1
  selector:
    matchLabels:
      app: startupprobe-tcpsocket
  template:
    metadata:
      labels:
        app: startupprobe-tcpsocket
    spec:
      containers:
        - name: nginx
          image: nginx:1.21
          ports:
            - containerPort: 80
          startupProbe:
            tcpSocket:
              port: 80
            initialDelaySeconds: 30
            periodSeconds: 10
            failureThreshold: 10
            timeoutSeconds: 5

相關文章