一、為什么需要容器探針
如何保持Pod健康
只要將pod調度到某個節點,Kubelet就會運行pod的容器,如果該pod的容器有一個或者所有的都終止運行(容器的主進程崩潰),Kubelet將重啟容器,所以即使應用程序本身沒有做任何特殊的事,在Kubemetes中運行也能自動獲得自我修復的能力。
自動重啟容器以保證應用的正常運行,這是使用Kubernetes的優勢,不過在某些情況,即使進程沒有崩潰,有時應用程序運行也會出錯。默認情況下Kubernetes只是檢查Pod容器是否正常運行,但容器正常運行並不一定代表應用健康,在以下兩種情況下Kubernetes將不會重啟容器:
- 1.訪問Web服務器時顯示500內部錯誤
- 該報錯可能是系統超載,也可能是資源死鎖,不過此時httpd進程依舊運行,重啟容器可能是最直接有效的辦法。
- 2.具有內存泄漏的Java應用程序將開始拋出OutOfMemoryErrors
- 此時JVM進程會一直運行,Kubernetes也不會重啟容器,但此時對應用來講是異常的。
此時可以考慮從外部檢查應用程序的運行狀況:
- Kubemetes可以通過存活探針(liveness probe)檢查容器是否還在運行;
- 通過就緒探針(readiness probe)保證只有准備好了請求的Pod才能接收客戶端請求。
二、LivenessProbe
1. 概念
Kubemetes可以通過存活探針(liveness probe)檢查容器是否還在運行。可以為pod中的每個容器單獨指定存活探針。如果探測失敗,Kubemetes將定期執行探針並重新啟動容器。
Kubernetes 支持三種方式來執行探針:
- exec:在容器中執行一個命令,如果命令退出碼返回0則表示探測成功,否則表示失敗
- tcpSocket:對指定的容IP及端口執行一個TCP檢查,如果端口是開放的則表示探測成功,否則表示失敗
- httpGet:對指定的容器IP、端口及路徑執行一個HTTP Get請求,如果返回的狀態碼在 [200,400)之間則表示探測成功,否則表示失敗
2. exec探針
exec類型的探針通過在目標容器中執行由用戶自定義的命令來判斷容器的監控狀態,若命令狀態返回值為0則表示“成功”通過檢測,其他值則均為“失敗”狀態。
2.1 創建liveness-exec.yaml
[root@master ~]# more liveness-exec.yaml apiVersion: v1 kind: Pod metadata: labels: test: liveness-exec name: liveness-exec spec: restartPolicy: OnFailure containers: - name: liveness-exec image: busybox args: - /bin/sh - -c - touch /tmp/healthy; sleep 10; rm -rf /tmp/healthy; sleep 600 livenessProbe: exec: command: ["test","-e","/tmp/healthy"] initialDelaySeconds: 5 #探測延時時長,第一次探測前等待5秒,默認為0 periodSeconds: 5 #每5秒執行一次liveness探測,默認值10秒,最小1秒 timeoutSeconds: 2 #超長時長,默認為1s,最小值也為1s failureThreshold: 3 #處於成功狀態時,探測操作至少連續多少次的失敗才被視為檢測不通過,默認為3,最小為1 [root@master ~]# kubectl apply -f liveness-exec.yaml pod/liveness-exec created
2.2 查看Pod
[root@master ~]# kubectl get po -o wide [root@master ~]# kubectl describe po liveness-exec

pod運行正常,10秒內文件/tmp/healthy還存在,probe檢測正常。
第15秒,probe再次檢測,由於文件被刪,檢測失敗,此后容器會進行多次重啟操作。
3. HTTP探針
基於HTTP的探測(HTTPGetAction)向目標容器發起一個HTTP請求,根據其相應碼進行結果判定,響應碼如2xx或3xx時表示檢測通過。
3.1 創建liveness-http.yaml
[root@master ~]# more liveness-http.yaml apiVersion : v1 kind: Pod metadata: labels: test: liveness name: liveness-http spec: containers: - name: liveness-http image: nginx ports: - name: http containerPort: 80 lifecycle: postStart: exec: command: ["/bin/sh" ,"-c","echo liveness-http test > /usr/share/nginx/html/health"] livenessProbe: httpGet: path: /health port: http scheme: HTTP [root@master ~]# kubectl apply -f liveness-http.yaml pod/liveness-http created
3.2 查看Pod
[root@master ~]# kubectl get po -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES liveness-http 1/1 Running 0 5s 10.244.2.206 node02 <none> <none> [root@master ~]# curl 10.244.2.206/health liveness-http test
3.3 刪除測試頁面health
[root@master ~]# kubectl exec -it liveness-http rm /usr/share/nginx/html/health
探測失敗,返回碼404,重啟容器。
4. TCP探針
基於TCP的存活性探測(TCPSocketAction)用於向容器的特定端口發起TCP請求並嘗試建立連接,連接成功即為通過檢測。
4.1 創建liveness-tcp.yaml
```bash [root@master ~]# more liveness-tcp.yaml apiVersion: v1 kind: Pod metadata: labels: test: liveness name: liveness-tcp spec: containers: - name: liveness-tcp image: nginx ports: - name: http containerPort: 80 livenessProbe: tcpSocket: port: http [root@master ~]# kubectl apply -f liveness-tcp.yaml pod/liveness-tcp created [root@master ~]# kubectl get po -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES liveness-tcp 1/1 Running 0 4s 10.244.2.217 node02 <none> <none> [root@master ~]# curl 10.244.2.217:80
4.2 修改默認端口
[root@master ~]# kubectl exec -it liveness-tcp -- sed -i 's/^ *listen 80/ listen 81/g' /etc/nginx/conf.d/default.conf
如果kubectl exec在容器內執行命令時如果帶參數則需加上'--'
加載nginx
[root@master ~]# kubectl exec -it liveness-tcp -- nginx -s reload
4.3 查看Pod
[root@master ~]# kubectl describe po liveness-tcp
80是nginx的默認端口,開始發起TCP連接的端口也是80,默認端口改成81后連接報錯,容器重啟。
三、ReadinessProbe
1. 概念
用於容器的自定義准備狀態檢查。如果ReadinessProbe檢查失敗,Kubernetes會將該Pod從服務代理的分發后端去除,不再分發請求給該Pod。
2. readinessprobe使用場景
Pod對象啟動后,容器應用通常需要一段時間才能完成其初始化過程,例如加載配置或數據,甚至有些程序需要運行某類的預熱過程,若在此階段完成之前接入客戶端的請求,勢必會因為等待太久而影響用戶體驗,這時就需要就緒探針。
如果沒有將就緒探針添加到pod中,它們幾乎會立即成為服務端點。如果應用程序需要很長時間才能開始監聽傳入連接,則在服務啟動但尚未准備好接收傳入連接時,客戶端請求將被轉發到該pod。因此,客戶端會看到"連接被拒絕"類型的錯誤。
3. 機制
與存活探針機制相同,就緒探針也支持Exec、HTTP GET和TCP Socket三種探測方式,且各自的定義機制相同,將容器定義中的livenessProbe字段名替換為readinessProbe即可定義出就緒探測的配置,這里不再贅述。
4. 創建readiness-exec.yaml
本文以exec方式為例實踐
[root@master ~]# more liveness-exec.yaml apiVersion: v1 kind: Pod metadata: labels: test: liveness-exec name: liveness-exec spec: restartPolicy: OnFailure containers: - name: liveness-exec image: busybox args: - /bin/sh - -c - touch /tmp/healthy; sleep 10; rm -rf /tmp/healthy; sleep 600 livenessProbe: exec: command: ["test","-e","/tmp/healthy"] initialDelaySeconds: 5 #探測延時時長,第一次探測前等待5秒,默認為0 periodSeconds: 5 #每5秒執行一次liveness探測,默認值10秒,最小1秒 timeoutSeconds: 2 #超長時長,默認為1s,最小值也為1s failureThreshold: 3 #處於成功狀態時,探測操作至少連續多少次的失敗才被視為檢測不通過,默認為3,最小為1 [root@master ~]# kubectl apply -f readiness-exec.yaml pod/readiness-exec created
5. 查看Pod
[root@master ~]# kubectl get po readiness-exec -w NAME READY STATUS RESTARTS AGE readiness-exec 0/1 ContainerCreating 0 2s readiness-exec 0/1 Running 0 3s readiness-exec 1/1 Running 0 9s readiness-exec 0/1 Running 0 24s
'-w'選項可以監視pod資源變動,剛開始盡管pod處於Running狀態,但知道就緒探測命令執行成功后pod資源才ready
剛開始處於'預熱'階段,pod為running狀態但不可用;當10秒后(initialDelaySeconds + periodSeconds),readinessprobe開始第一次探測,成功后pod處於ready狀態,45秒后(sleep30 + periodSeconds * failureThreshold)探測失敗,pod再次為running但not ready狀態。
6. 與livenessprobe區別
- 如果容器中的進程能夠在遇到問題或不健康的情況下自行崩潰,則不一定需要存活探針; kubelet 將根據Pod的restartPolicy自動執行正確的操作。
- 如果您希望容器在探測失敗時被殺死並重新啟動,那么請指定一個存活探針,並指定restartPolicy為Always或OnFailure。
- 如果要僅在探測成功時才開始向 Pod 發送流量,請指定就緒探針。在這種情況下,就緒探針可能與存活探針相同,但是spec中的就緒探針的存在意味着Pod將在沒有接收到任何流量的情況下啟動,並且只有在探針探測成功后才開始接收流量。
- 兩種探測的配置方法完全一樣,支持的配置參數也一樣,既可單獨探測又可結合者一起執行。