寫在前面
K8S對Pod的健康狀態可以通過兩類探針來檢查:livenessProbe和readinessProbe,kubelet通過定期執行這兩類探針來診斷容器的健康狀況。
livenessProbe簡介
存活指針,判斷Pod(中的應用容器)是否健康,可以理解為健康檢查。我們使用livenessProbe來定期的去探測,如果探測成功,則Pod狀態可以判定為Running;如果探測失敗,可kubectl會根據Pod的重啟策略來重啟容器。
如果未給Pod設置livenessProbe,則默認探針永遠返回Success。
當我們執行kubectl get pods
命令,輸出信息中STATUS
一列我們可以看到Pod是否處於Running
狀態。
readinessProbe簡介
就緒指針,就緒的意思是已經准備好了,Pod的就緒我們可以理解為這個Pod可以接受請求和訪問。我們使用readinessProbe來定期的去探測,如果探測成功,則Pod 的Ready狀態判定為True;如果探測失敗,Pod的Ready狀態判定為False。
與livenessProbe不同的是,kubelet不會對readinessProbe的探測情況有重啟操作。
當我們執行kubectl get pods
命令,輸出信息中READY
一列我們可以看到Pod的READY
狀態是否為True。
定義參數
livenessProbe和readinessProbe的定義參數是一致的,可以通過kubectl explain pods.spec.containers.readinessProbe
或kubectl explain pods.spec.containers.livenessProbe
命令了解:
就緒探針的幾種類型:
httpGet
向容器發送Http Get請求,調用成功(通過Http狀態碼判斷)則確定Pod就緒;
使用方式:
livenessProbe:
httpGet:
path: /app/healthz
port: 80
exec
在容器內執行某命令,命令執行成功(通過命令退出狀態碼為0判斷)則確定Pod就緒;
使用方式:
livenessProbe:
exec:
command:
- cat
- /app/healthz
tcpSocket
打開一個TCP連接到容器的指定端口,連接成功建立則確定Pod就緒。
使用方式:
livenessProbe:
tcpSocket:
port: 80
一般就緒探針會在啟動容器一段時間后才開始第一次的就緒探測,之后做周期性探測。所以在定義就緒指針時,會給以下幾個參數:
- initialDelaySeconds:在初始化容器多少秒后開始第一次就緒探測;
- timeoutSeconds:如果該次就緒探測超過多少秒后還未成功,判定為超時,該次探測失敗,Pod不就緒。默認值1,最小值1;
- periodSeconds:如果Pod未就緒,則每隔多少秒周期性的做就緒探測。默認值10,最小值1;
- failureThreshold:如果容器之前探測成功,后續連續幾次探測失敗,則確定容器未就緒。默認值3,最小值1;
- successThreshold:如果容器之前探測失敗,后續連續幾次探測成功,則確定容器就緒。默認值1,最小值1。
使用示例
目前我在docker hub有一個測試鏡像:med1tator/helloweb:v1,容器啟動后,有一個健康檢查路由/healthz/return200,訪問該路由狀態碼返回200;有一個檢查路由/health/return404,訪問該路由狀態碼返回404。
readinessProbe示例
在實驗之前先了解一下Pod和Service的負載均衡關系:在K8S中,Service作為Pod的負載均衡器,是通過Label Selector匹配Pod的。但是這句話沒有說完整,因為還有一個必要條件:Pod當前已經就緒。也就是說,Service通過Label Selector匹配當前就緒的Pod,還未就緒的Pod就算labelSelector匹配上了,也不會出現在Service的endpoints中,請求是不會被轉發過去的,如下圖示例。
示例說明:我們使用med1tator/helloweb:v1
鏡像啟動三個Pod,三個Pod的Label都設置成一樣,為了使Service匹配到;三個Pod其中兩個readinessProbe使用httpGet探測/health/return200,模擬探測成功,一個readinessProbe使用httpGet探測/health/return404,模擬探測失敗。
編寫我們的helloweb-readinessProbe.yaml文件如下:
apiVersion: v1
kind: Pod
metadata:
name: helloweb1
labels:
app: helloweb
spec:
containers:
- name: helloweb
image: med1tator/helloweb:v1
readinessProbe:
httpGet:
path: /healthz/return200
port: 80
initialDelaySeconds: 30
timeoutSeconds: 10
ports:
- containerPort: 80
---
apiVersion: v1
kind: Pod
metadata:
name: helloweb2
labels:
app: helloweb
spec:
containers:
- name: helloweb
image: med1tator/helloweb:v1
readinessProbe:
httpGet:
path: /healthz/return200
port: 80
initialDelaySeconds: 30
timeoutSeconds: 10
ports:
- containerPort: 80
---
apiVersion: v1
kind: Pod
metadata:
name: helloweb3
labels:
app: helloweb
spec:
containers:
- name: helloweb
image: med1tator/helloweb:v1
readinessProbe:
httpGet:
path: /healthz/return404
port: 80
initialDelaySeconds: 30
timeoutSeconds: 10
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: helloweb
spec:
selector:
app: helloweb
type: ClusterIP
ports:
- name: http
port: 80
targetPort: 80
運行命令部署Pod和Service:
kubectl apply -f helloweb-readinessProbe.yaml
之后,我們查看Pod的就緒情況:
可以看到Pod只有helloweb1和helloweb2當前使處於READY
(就緒)的狀態,helloweb3尚未Ready,我們接着查看helloweb service的endpoints:
可以看到Service的EndPoints只將helloweb1、helloweb2 pod的IP負載上了。
查看日志訪問情況:
可以看到每隔10秒(readniessProbe.periodSeconds默認10s)就會做一次就緒探測。
livenessProbe示例
編寫我們的helloweb-livenessProbe.yaml文件如下:
apiVersion: v1
kind: Pod
metadata:
name: helloweb4
labels:
app: helloweb
spec:
containers:
- name: helloweb
image: med1tator/helloweb:v1
livenessProbe:
httpGet:
path: /healthz/return200
port: 80
initialDelaySeconds: 30
timeoutSeconds: 10
ports:
- containerPort: 80
---
apiVersion: v1
kind: Pod
metadata:
name: helloweb5
labels:
app: helloweb
spec:
containers:
- name: helloweb
image: med1tator/helloweb:v1
livenessProbe:
httpGet:
path: /healthz/return404
port: 80
initialDelaySeconds: 30
timeoutSeconds: 10
ports:
- containerPort: 80
運行命令部署Pod和Service:
kubectl apply -f helloweb-livenessProbe.yaml
之后,我們查看Pod的就緒情況:
可以看到helloweb4的STATUS狀態為Running
,而helloweb5的STATUS狀態最終變為CrashLoopBackOff
,並且一直在重啟。
相信到這里,你已經對readniessProbe
和livenessProbe
有一個清晰的了解了。