一、探針概述

探針是有 kubelet 對容器執行的定期診斷,並不是由 Master 節點發起的探測,而是由每一個 Node 所在的 kubelet 進行探測,這樣可以減輕 Master 節點系統負載壓力。

kubelet 要執行診斷,kubelet 呼叫由容器實現的 Handler (處理程式)。一共有三種類型的處理程式:

  • ExecAction: 在容器內執行指定命令。如果命令退出時返回碼為 0 則認為診斷成功,非 0 都屬於不成功。

  • TCPSocketAction: 對容器的 IP 地址上的指定埠執行 TCP 檢查。如果埠開啟,則診斷被認為是成功的。

  • HTTPGetAction: 對容器的 IP 地址上指定埠和路徑執行 HTTP Get 請求。如果響應的狀態碼大於等於 200 且小於 400,則診斷被認為是成功的。

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

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

兩種探針方式:

liveness Probe:是一個存活探測器,會隨著 Pod 生命週期一直迴圈檢測。探測容器是否正在執行,如果存活探測失敗,則 kubelet 會殺死容器,然後根據其容器的重啟策略來對容器進行操作,預設為 Always,則 Pod 進行重啟。

readiness Probe:是一個就緒探測器,檢測 Pod 是否到達就緒狀態,只有達到就緒狀態了才可以對外提供服務,當一個 Pod 內的所有容器都準備好了,才能把這個 Pod 看作就緒了。

readiness Probe 應用場景:

就緒探針可以應用在 Service 後端的 Pod 探測上,在 Pod 還沒有準備好的時候,會從 Service 的負載均衡器中剔除。

二、探針例項測試

2.1 就緒探針 - HTTP Get

readiness-httpget.yaml如下:

apiVersion: v1
kind: Pod
metadata:
name: readiness-httpget # Pod 名稱
namespace: test # Pod 所在的名稱空間
spec:
containers:
- name: readiness-httpget-container # 容器名稱
image: hub.test.com/library/mynginx:v1 # 映象地址
imagePullPolicy: IfNotPresent # 映象下載策略
readinessProbe: # 就緒探測
httpGet: # 檢測方案
path: /index1.html # 檢測路徑
port: 80 # 檢測埠
initialDelaySeconds: 3 # 啟動後多少秒開始第一次檢測
periodSeconds: 3 # 每次間隔檢測時間

實際就是檢測:http://localhost/index1.html,是否正常。

建立 Pod

[root@k8s-master01 ~]# kubectl create -f readiness-httpget.yaml
pod/readiness-httpget created

檢視 Pod 狀態

雖然已經 Running 了,但是還沒就緒狀態,因為我們這個容器沒有index1.html這個頁面。

檢視該 Pod 的詳細詳細

[root@k8s-master01 ~]# kubectl describe pod readiness-httpget -n test
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 5m11s default-scheduler Successfully assigned test/readiness-httpget to k8s-node01
Normal Pulled 5m10s kubelet Container image "hub.test.com/library/mynginx:v1" already present on machine
Normal Created 5m10s kubelet Created container readiness-httpget-container
Normal Started 5m10s kubelet Started container readiness-httpget-container
Warning Unhealthy 8s (x100 over 5m5s) kubelet Readiness probe failed: HTTP probe failed with statuscode: 404

提示就緒檢測找不到該頁面,返回狀態碼 404。

接下來進入該容器手動建立index1.html頁面

[root@k8s-master01 ~]# kubectl exec readiness-httpget -n test -it -- /bin/bash
root@readiness-httpget:/# cd /usr/share/nginx/html/
root@readiness-httpget:/usr/share/nginx/html# ls
50x.html index.html
root@readiness-httpget:/usr/share/nginx/html# touch index1.html
root@readiness-httpget:/usr/share/nginx/html# exit

再次檢視 Pod 狀態已經就緒狀態了

2.2 存活探針 - exec

liveness-exec.yaml檔案如下:

apiVersion: v1
kind: Pod
metadata:
name: liveness-exec # Pod 名稱
namespace: test # Pod 所在的名稱空間
spec:
containers:
- name: liveness-exec-container # 容器名稱
image: hub.test.com/library/busybox:latest # 映象地址
imagePullPolicy: IfNotPresent # 映象下載策略
command: ["/bin/sh","-c","touch /tmp/live; sleep 60; rm -rf /tmp/live; sleep 3600"]
# 建立 live 檔案,休眠60秒,刪除 live 檔案,再休眠 1 分鐘。
livenessProbe: # 存活探測
exec: # 檢測方案
command: ["test","-e","/tmp/live"] # 檢測該檔案是否存在,返回值 0 成功,非 0 失敗
initialDelaySeconds: 3 # 啟動後多少秒開始第一次檢測
periodSeconds: 3 # 每次間隔檢測時間

建立 Pod

[root@k8s-master01 ~]# kubectl create -f liveness-exec.yaml
pod/liveness-exec created

檢視 Pod 狀態,加上-w實時檢視

[root@k8s-master01 ~]# kubectl get pod -n test -w

從上圖可以看到 RESTARTS 已經重啟一次了,它會迴圈重啟,因為重新建立 Pod 到時候 /tmp/live 就會被建立,但是 60 秒後又被刪除。

2.3 存活探針 - HTTPGet

liveness-httpgat.yaml檔案如下:

apiVersion: v1
kind: Pod
metadata:
name: liveness-httpgat # Pod 名稱
namespace: test # Pod 所在的名稱空間
spec:
containers:
- name: liveness-httpgat-container # 容器名稱
image: hub.test.com/library/mynginx:v1 # 映象地址
imagePullPolicy: IfNotPresent # 映象下載策略
ports:
- name: http
containerPort: 80
livenessProbe: # 存活探測
httpGet: # 檢測方案
port: http
path: /index.html
initialDelaySeconds: 3 # 啟動後多少秒開始第一次檢測
periodSeconds: 3 # 每次間隔檢測時間
timeoutSeconds: 10 # 探測的超時時間

建立 Pod

[root@k8s-master01 ~]# kubectl create -f liveness-httpget.yaml
pod/liveness-httpgat created

檢視 Pod 狀態,此時是正常的

[root@k8s-master01 ~]# kubectl get pod -n test
NAME READY STATUS RESTARTS AGE
hpa-nginx-deploy-9f8676f85-5fk6c 1/1 Running 0 12m
liveness-httpgat 1/1 Running 0 30s

現在將 nginx 容器裡面的 index.html 檔案給刪除

[root@k8s-master01 ~]# kubectl exec liveness-httpgat -n test -it -- rm -rf /usr/share/nginx/html/index.html

重啟次數變為 1 ,由於 liveness沒有檢測到 index.html 檔案,則會刪掉主容器,主容器一旦被刪除 Pod 也會進行重啟。

2.4 存活探針 - TCP

liveness-tcp.yaml檔案如下:

apiVersion: v1
kind: Pod
metadata:
name: liveness-tcp # Pod 名稱
namespace: test # Pod 所在的名稱空間
spec:
containers:
- name: liveness-tcp-container # 容器名稱
image: hub.test.com/library/mynginx:v1 # 映象地址
imagePullPolicy: IfNotPresent # 映象下載策略
livenessProbe: # 存活探測
tcpSocket: # 檢測方案
port: 8080 # 檢測埠
initialDelaySeconds: 3 # 啟動後多少秒開始第一次檢測
periodSeconds: 3 # 每次間隔檢測時間

建立 Pod

[root@k8s-master01 ~]# kubectl create -f liveness-tcp.yaml
pod/liveness-tcp created

檢視 Pod 狀態,此時由於 nginx 埠為 80,所以檢測不到 8080 埠,會一直重啟。

2.5 就緒探針+存活探針 - HTTPGet

live-readi-httpgat.yaml檔案如下:

apiVersion: v1
kind: Pod
metadata:
name: live-readi-httpgat # Pod 名稱
namespace: test # Pod 所在的名稱空間
spec:
containers:
- name: live-readi-httpgat-container # 容器名稱
image: hub.test.com/library/mynginx:v1 # 映象地址
imagePullPolicy: IfNotPresent # 映象下載策略
ports:
- name: http
containerPort: 80 # 容器埠
readinessProbe: # 就緒探測
httpGet: # 檢測方案
path: /index1.html # 檢測路徑
port: 80 # 檢測埠
initialDelaySeconds: 3
periodSeconds: 3
livenessProbe: # 存活探測
httpGet: # 檢測方案
port: http # 檢測協議
path: /index.html # 檢測路徑
initialDelaySeconds: 3 # 啟動後多少秒開始第一次檢測
periodSeconds: 3 # 每次間隔檢測時間
timeoutSeconds: 10 # 探測的超時時間

建立 Pod

[root@k8s-master01 ~]# kubectl create -f live-read-httpget.yaml
pod/live-readi-httpgat created

檢視 Pod 狀態

雖然是 Running 狀態,但是還沒 Read,因為就緒探針沒有檢測到index1.html這個檔案存在。

進入容器手動建立測試

[root@k8s-master01 ~]# kubectl exec live-readi-httpgat -n test -it -- /bin/bash
root@live-readi-httpgat:/# cd /usr/share/nginx/html/
root@live-readi-httpgat:/usr/share/nginx/html# touch index1.html

再次檢視 Pod 狀態,現在已經就緒狀態

我們再測試liveness探針,刪除 index.html 檔案

[root@k8s-master01 ~]# kubectl exec live-readi-httpgat -n test -it -- rm -rf /usr/share/nginx/html/index.html

可以看到 Pod 重啟 1 次,又回到未就緒狀態了,因為重啟完後預設是沒有index1.html 檔案的

三、配置補充

使用啟動探測器保護慢啟動容器

有時候,會有一些現有的應用程式在啟動時需要較多的初始化時間。 要不影響對引起探測死鎖的快速響應,這種情況下,設定存活探測引數是要技巧的。 技巧就是使用一個命令來設定啟動探測,針對HTTP 或者 TCP 檢測,可以通過設定 failureThreshold * periodSeconds 引數來保證有足夠長的時間應對糟糕情況下的啟動時間。

例項:

startupProbe:
httpGet:
path: /test
port: liveness-port
failureThreshold: 30
periodSeconds: 10

應用程式可以有最多 5 分鐘(30 * 10 = 300s) 的時間來完成它的啟動。

還有很多配置欄位,可以使用這些欄位精確的控制存活和就緒檢測的行為:

  • initialDelaySeconds:容器啟動後要等待多少秒後存活和就緒探測器才被初始化,預設是 0 秒,最小值是 0。
  • periodSeconds:執行探測的時間間隔(單位是秒)。預設是 10 秒。最小值是 1。
  • timeoutSeconds:探測的超時後等待多少秒。預設值是 1 秒。最小值是 1。
  • successThreshold:探測器在失敗後,被視為成功的最小連續成功數。預設值是 1。 存活和啟動探測的這個值必須是 1。最小值是 1。
  • failureThreshold:當探測失敗時,Kubernetes 的重試次數。 存活探測情況下的放棄就意味著重新啟動容器。 就緒探測情況下的放棄 Pod 會被打上未就緒的標籤。預設值是 3。最小值是 1。