一、探針概述
探針是有 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 # 每次間隔檢測時間
創建 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。