配置Liveness和Readiness探針

本文將向您展現如何配置容器的存活和可讀性探針。git

kubelet 使用 liveness probe(存活探針)來肯定什麼時候重啓容器。例如,當應用程序處於運行狀態但沒法作進一步操做,liveness 探針將捕獲到 deadlock,重啓處於該狀態下的容器,使應用程序在存在 bug 的狀況下依然可以繼續運行下去。github

Kubelet 使用 readiness probe(就緒探針)來肯定容器是否已經就緒能夠接受流量。只有當 Pod 中的容器都處於就緒狀態時 kubelet 纔會認定該 Pod處於就緒狀態。該信號的做用是控制哪些 Pod應該做爲service的後端。若是 Pod 處於非就緒狀態,那麼它們將會被從 service 的 load balancer中移除。web

Before you begin

You need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using Minikube, or you can use one of these Kubernetes playgrounds:docker

To check the version, enter kubectl version.後端

定義 liveness 命令

許多長時間運行的應用程序最終會轉換到 broken 狀態,除非從新啓動,不然沒法恢復。Kubernetes 提供了 liveness probe 來檢測和補救這種狀況。api

在本次練習將基於 gcr.io/google_containers/busybox鏡像建立運行一個容器的 Pod。如下是 Pod 的配置文件exec-liveness.yamlapp

exec-liveness.yaml 
apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-exec
spec:
  containers:
  - name: liveness
    image: k8s.gcr.io/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

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

容器啓動時,執行該命令:ide

/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 https://k8s.io/docs/tasks/configure-pod-container/exec-liveness.yaml

在30秒內,查看 Pod 的 event:

kubectl describe pod liveness-exec

結果顯示沒有失敗的 liveness probe:

FirstSeen    LastSeen    Count   From            SubobjectPath           Type        Reason      Message
--------- --------    -----   ----            -------------           --------    ------      -------
24s       24s     1   {default-scheduler }                    Normal      Scheduled   Successfully assigned liveness-exec to worker0
23s       23s     1   {kubelet worker0}   spec.containers{liveness}   Normal      Pulling     pulling image "gcr.io/google_containers/busybox"
23s       23s     1   {kubelet worker0}   spec.containers{liveness}   Normal      Pulled      Successfully pulled image "gcr.io/google_containers/busybox"
23s       23s     1   {kubelet worker0}   spec.containers{liveness}   Normal      Created     Created container with docker id 86849c15382e; Security:[seccomp=unconfined]
23s       23s     1   {kubelet worker0}   spec.containers{liveness}   Normal      Started     Started container with docker id 86849c15382e

35秒後,再次查看 Pod 的 event:

kubectl describe pod liveness-exec

在最下面有一條信息顯示 liveness probe 失敗,容器被刪掉並從新建立。

FirstSeen LastSeen    Count   From            SubobjectPath           Type        Reason      Message
--------- --------    -----   ----            -------------           --------    ------      -------
37s       37s     1   {default-scheduler }                    Normal      Scheduled   Successfully assigned liveness-exec to worker0
36s       36s     1   {kubelet worker0}   spec.containers{liveness}   Normal      Pulling     pulling image "gcr.io/google_containers/busybox"
36s       36s     1   {kubelet worker0}   spec.containers{liveness}   Normal      Pulled      Successfully pulled image "gcr.io/google_containers/busybox"
36s       36s     1   {kubelet worker0}   spec.containers{liveness}   Normal      Created     Created container with docker id 86849c15382e; Security:[seccomp=unconfined]
36s       36s     1   {kubelet worker0}   spec.containers{liveness}   Normal      Started     Started container with docker id 86849c15382e
2s        2s      1   {kubelet worker0}   spec.containers{liveness}   Warning     Unhealthy   Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory

再等30秒,確認容器已經重啓:

kubectl get pod liveness-exec

從輸出結果來RESTARTS值加1了。

NAME            READY     STATUS    RESTARTS   AGE
liveness-exec   1/1       Running   1          1m

定義 liveness HTTP請求

咱們還可使用 HTTP GET 請求做爲 liveness probe。下面是一個基於gcr.io/google_containers/liveness鏡像運行了一個容器的 Pod 的例子http-liveness.yaml

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

該配置文件只定義了一個容器,livenessProbe 指定 kubelet 須要每隔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 來測試一下 HTTP liveness檢測:

kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/http-liveness.yaml

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

kubectl describe pod liveness-http

定義 TCP liveness probe

第三種 liveness probe 使用 TCP Socket。 使用此配置,kubelet 將嘗試在指定端口上打開容器的套接字。 若是能夠創建鏈接,容器被認爲是健康的,若是不能就認爲是失敗的。

tcp-liveness-readiness.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: goproxy
  labels:
    app: goproxy
spec:
  containers:
  - name: goproxy
    image: k8s.gcr.io/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秒鐘執行一次該檢查。

如您所見,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 probe

有時,應用程序暫時沒法對外部流量提供服務。 例如,應用程序可能須要在啓動期間加載大量數據或配置文件。 在這種狀況下,您不想殺死應用程序,也不想發送請求。 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 能夠並行用於同一容器。 使用二者能夠確保流量沒法到達未準備好的容器,而且容器在失敗時從新啓動。

Configure Probes

配置 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頭。

What’s next

相關文章
相關標籤/搜索