Kubernetes Pod 健康檢查


參考文檔: https://jimmysong.io/kubernetes-handbook/guide/configure-liveness-readiness-probes.html

一、Pod的liveness和readiness探針

  當你使用kuberentes的時候,有沒有遇到過Pod在啟動后一會就掛掉然后又重新啟動這樣的惡性循環?你有沒有想過kubernetes是如何檢測pod是否還存活?雖然容器已經啟動,但是kubernetes如何知道容器的進程是否准備好對外提供服務了呢?

  Kubelet使用liveness probe(存活探針)來確定何時重啟容器。例如,當應用程序處於運行狀態但無法做進一步操作,liveness探針將捕獲到deadlock,重啟處於該狀態下的容器,使應用程序在存在bug的情況下依然能夠繼續運行下去

  Kubelet使用readiness probe(就緒探針)來確定容器是否已經就緒可以接受流量。只有當Pod中的容器都處於就緒狀態時kubelet才會認定該Pod處於就緒狀態。該信號的作用是控制哪些Pod應該作為service的后端。如果Pod處於非就緒狀態,那么它們將會被從service的load balancer中移除。

  Probe支持以下三種檢查方法:

  • httpGet:發送HTTP請求,返回200-400范圍內狀態碼為成功
  • exec:執行shell命令,返回狀態碼0為成功
  • tcpSocket:發起TCP Socket建立則成功

二、定義liveness命令(exec)

  許多長時間運行的應用程序最終會轉換到broken狀態,除非重新啟動,否則無法恢復。Kubernetes提供了liveness probe來檢測和補救這種情況。 

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

  該配置文件給Pod配置了一個容器。periodSeconds 規定kubelet要每隔5秒執行一次liveness probe。initialDelaySeconds 告訴kubelet在第一次執行probe之前要的等待5秒鍾。探針檢測命令是在容器中執行 cat /tmp/healthy 命令。如果命令執行成功,將返回0,kubelet就會認為該容器是活着的並且很健康。如果返回非0值,kubelet就會殺掉這個容器並重啟它。

  容器啟動時,執行該命令:  

/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 將返回失敗的返回碼。

  創建Pod  

kubectl create -f exec-lineness.yaml

  在30秒內,查看Pod的event:   

kubectl describe pod liveness-exec

# 顯示正常
  Normal   Pulled                 34s (x3 over 3m)  kubelet, node-01   Successfully pulled image "busybox"
  Normal   Created                34s (x3 over 3m)  kubelet, node-01   Created container
  Normal   Started                33s (x3 over 3m)  kubelet, node-01   Started container

  啟動35秒后,再次查看pod的event:    

kubectl describe pod liveness-exec

# 顯示查詢不到/tmp/healthy
 Normal   Scheduled              1m                 default-scheduler   Successfully assigned liveness-exec to master-01
  Normal   SuccessfulMountVolume  1m                 kubelet, master-01  MountVolume.SetUp succeeded for volume "default-token-v5vw9"
  Normal   Pulled                 1m                 kubelet, master-01  Successfully pulled image "busybox"
  Normal   Created                1m                 kubelet, master-01  Created container
  Normal   Started                1m                 kubelet, master-01  Started container
  Warning  Unhealthy              40s (x3 over 50s)  kubelet, master-01  Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory
  Normal   Pulling                10s (x2 over 1m)   kubelet, master-01  pulling image "busybox"
  Normal   Killing                10s                kubelet, master-01  Killing container with id docker://liveness:Container failed liveness probe.. Container will be killed and recreated  

  然后就會將這個Pod刪掉重建  

[root@master-01 healthy]# kubectl get pod
NAME                                READY     STATUS    RESTARTS   AGE
liveness-exec                       1/1       Running   1          2m

# RESTARTS 已經為1了

  

三、定義一個liveness HTTP請求

  我們還可以使用HTTP GET請求作為liveness probe。 

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

  該配置文件只定義了一個容器,livenessProbe 指定kubelete需要每隔3秒執行一次liveness probe。initialDelaySeconds 指定kubelet在該執行第一次探測之前需要等待3秒鍾。該探針將向容器中的server的8080端口發送一個HTTP GET請求。如果server的/healthz路徑的handler返回一個成功的返回碼,kubelet就會認定該容器是活着的並且很健康。如果返回失敗的返回碼,kubelet將殺掉該容器並重啟它。

  任何大於200小於400的返回碼都會認定是成功的返回碼。其他返回碼都會被認為是失敗的返回碼。

  查看該server的源碼:server.go.

  最開始的10秒該容器是活着的, /healthz handler返回200的狀態碼。這之后將返回500的返回碼。  

http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
    duration := time.Now().Sub(started)
    if duration.Seconds() > 10 {
        w.WriteHeader(500)
        w.Write([]byte(fmt.Sprintf("error: %v", duration.Seconds())))
    } else {
        w.WriteHeader(200)
        w.Write([]byte("ok"))
    }
})

  容器啟動3秒后,kubelet開始執行健康檢查。第一次健康監測會成功,但是10秒后,健康檢查將失敗,kubelet將殺掉和重啟容器。

  創建Pod:  

kubectl create -f http-liveness.yaml

  10秒后,查看Pod的event,確認liveness probe失敗並重啟了容器。 

  Normal   Scheduled              24s               default-scheduler   Successfully assigned liveness-http to master-01
  Normal   SuccessfulMountVolume  24s               kubelet, master-01  MountVolume.SetUp succeeded for volume "default-token-v5vw9"
  Normal   Pulled                 19s               kubelet, master-01  Successfully pulled image "tomtsang/dockerlibraryk8s-liveness"
  Normal   Created                19s               kubelet, master-01  Created container
  Normal   Started                19s               kubelet, master-01  Started container
  Warning  Unhealthy              2s (x3 over 8s)   kubelet, master-01  Liveness probe failed: HTTP probe failed with statuscode: 500
  Normal   Pulling                1s (x2 over 23s)  kubelet, master-01  pulling image "tomtsang/dockerlibraryk8s-liveness"
  Normal   Killing                1s                kubelet, master-01  Killing container with id docker://liveness:Container failed liveness probe..

  

四、定義TCP liveness探針

  第三種liveness probe使用TCP Socket。 使用此配置,kubelet將嘗試在指定端口上打開容器的套接字。 如果可以建立連接,容器被認為是健康的,如果不能就認為是失敗的。 

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

  如您所見,TCP檢查的配置與HTTP檢查非常相似。 此示例同時使用了readiness和liveness probe。 容器啟動后5秒鍾,kubelet將發送第一個readiness probe。 這將嘗試連接到端口8080上的goproxy容器。如果探測成功,則該pod將被標記為就緒。Kubelet將每隔10秒鍾執行一次該檢查。

  除了readiness probe之外,該配置還包括liveness probe。 容器啟動15秒后,kubelet將運行第一個liveness probe。 就像readiness probe一樣,這將嘗試連接到goproxy容器上的8080端口。如果liveness probe失敗,容器將重新啟動。

五、使用命名端口

  可以使用命名的ContainerPort作為HTTP或TCP liveness檢查:  

ports:
- name: liveness-port
  containerPort: 8080
  hostPort: 8080

livenessProbe:
  httpGet:
  path: /healthz
  port: liveness-port

  

六、定義readiness探針

  有時,應用程序暫時無法對外部流量提供服務。 例如,應用程序可能需要在啟動期間加載大量數據或配置文件。 在這種情況下,你不想殺死應用程序,但你也不想發送請求。 Kubernetes提供了readiness probe來檢測和減輕這些情況。 Pod中的容器可以報告自己還沒有准備,不能處理Kubernetes服務發送過來的流量。

  Readiness probe的配置跟liveness probe很像。唯一的不同是使用 readinessProbe而不是livenessProbe。 

readinessProbe:
  exec:
    command:
    - cat
    - /tmp/healthy
  initialDelaySeconds: 5
  periodSeconds: 5

  Readiness probe的HTTP和TCP的探測器配置跟liveness probe一樣。

  Readiness和livenss probe可以並行用於同一容器。 使用兩者可以確保流量無法到達未准備好的容器,並且容器在失敗時重新啟動。

  

七、配置Probe  

Probe中有很多精確和詳細的配置,通過它們你能准確的控制liveness和readiness檢查:

  • initialDelaySeconds:容器啟動后第一次執行探測是需要等待多少秒。
  • periodSeconds:執行探測的頻率。默認是10秒,最小1秒。
  • timeoutSeconds:探測超時時間。默認1秒,最小1秒。
  • successThreshold:探測失敗后,最少連續探測成功多少次才被認定為成功。默認是1。對於liveness必須是1。最小值是1。
  • failureThreshold:探測成功后,最少連續探測失敗多少次才被認定為失敗。默認是3。最小值是1。

HTTP probe中可以給 httpGet設置其他配置項:

  • host:連接的主機名,默認連接到pod的IP。你可能想在http header中設置"Host"而不是使用IP。
  • scheme:連接使用的schema,默認HTTP。
  • path: 訪問的HTTP server的path。
  • httpHeaders:自定義請求的header。HTTP運行重復的header。
  • port:訪問的容器的端口名字或者端口號。端口號必須介於1和65525之間。

對於HTTP探測器,kubelet向指定的路徑和端口發送HTTP請求以執行檢查。 Kubelet將probe發送到容器的IP地址,除非地址被httpGet中的可選host字段覆蓋。 在大多數情況下,你不想設置主機字段。 有一種情況下你可以設置它。 假設容器在127.0.0.1上偵聽,並且Pod的hostNetwork字段為true。 然后,在httpGet下的host應該設置為127.0.0.1。 如果你的pod依賴於虛擬主機,這可能是更常見的情況,你不應該是用host,而是應該在httpHeaders中設置Host頭。

 


免責聲明!

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



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