應用在執行過程中難免會出現錯誤,如程式異常、軟體異常、硬體故障、網路故障等。因此,系統通過一些手段來判斷應用是否執行正常,這些手段稱之為健康檢查(診斷)。
前置知識
回顧一下Pod的生命週期:
檢查機制(Check mechanisms)
有以下幾種方法來檢查容器:
- exec:在容器內執行指定命令。如果命令退出時返回碼為 0 則認為診斷成功。
- gRPC:使用gRPC執行遠端過程呼叫。目標應該實施gRPC執行狀況檢查。如果響應的狀態為
SERVING
,則認為診斷成功。gRPC檢查是一項Alpha功能,僅當您啟用GRPCContainerProbe時才可用。 - httpGet:對容器的 IP 地址上指定埠和路徑執行 HTTP Get 請求。如果響應的狀態碼大於等於 200 且小於 400,則診斷被認為是成功的。
- tcpSocket:對容器的 IP 地址上的指定埠執行 TCP 檢查。如果埠開啟,則診斷被認為是成功的。
每次探測都將獲得以下三種結果之一:
Success
(成功):容器通過了診斷。Failure
(失敗):容器未通過診斷。Unknown
(未知):診斷失敗,因此不會採取任何行動。
針對執行中的容器,kubelet
可以選擇是否執行以下三種探針,以及如何針對探測結果作出反應:
livenessProbe
:指示容器是否正在執行。如果存活態探測失敗,則 kubelet 會殺死容器, 並且容器將根據其重啟策略決定未來。如果容器不提供存活探針, 則預設狀態為Success
。readinessProbe
:指示容器是否準備好為請求提供服務。如果就緒態探測失敗, 端點控制器將從與 Pod 匹配的所有服務的端點列表中刪除該 Pod 的 IP 地址。 初始延遲之前的就緒態的狀態值預設為Failure
。 如果容器不提供就緒態探針,則預設狀態為Success
。startupProbe
: 指示容器中的應用是否已經啟動。如果提供了啟動探針,則所有其他探針都會被 禁用,直到此探針成功為止。如果啟動探測失敗,kubelet
將殺死容器,而容器依其重啟策略進行重啟。 如果容器沒有提供啟動探測,則預設狀態為Success
。
exec方式檢測存活示例
建立一個 Pod,其中執行一個基於 busybox
映象的容器:
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-exec
spec:
containers:
- name: liveness
image: registry.aliyuncs.com/google_containers/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
當容器啟動時,執行如下的命令:
/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
就會返回失敗程式碼。
事件如下:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 41s default-scheduler Successfully assigned default/liveness-exec to node-1
Normal Pulling 40s kubelet Pulling image "registry.aliyuncs.com/google_containers/busybox"
Normal Pulled 39s kubelet Successfully pulled image "registry.aliyuncs.com/google_containers/busybox" in 727.748993ms
Normal Created 39s kubelet Created container liveness
Normal Started 39s kubelet Started container liveness
Warning Unhealthy 1s (x2 over 6s) kubelet Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory
檢檢視這個容器被重啟了:
[root@master test]# kubectl get pod
NAME READY STATUS RESTARTS AGE
liveness-exec 1/1 Running 1 82s
httpGet方式檢測存活示例
建立一個 Pod ,其中執行一個基於 liveness
映象的容器:
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-http
spec:
containers:
- name: liveness
image: mirrorgooglecontainers/liveness
args:
- /server
livenessProbe:
httpGet:
path: /healthz
port: 8080
httpHeaders:
- name: Custom-Header
value: Awesome
initialDelaySeconds: 3
periodSeconds: 3
通過看 Pod 事件來檢測存活探測器已經失敗了並且容器被重新啟動了。
kubectl describe pod liveness-http
事件如下:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 100s default-scheduler Successfully assigned default/liveness-http to node-1
Normal Pulled 84s kubelet Successfully pulled image "mirrorgooglecontainers/liveness" in 15.537483195s
Normal Pulled 52s kubelet Successfully pulled image "mirrorgooglecontainers/liveness" in 15.375906607s
Normal Pulled 19s kubelet Successfully pulled image "mirrorgooglecontainers/liveness" in 15.388654652s
Normal Created 18s (x3 over 83s) kubelet Created container liveness
Normal Started 18s (x3 over 83s) kubelet Started container liveness
Warning Unhealthy 1s (x9 over 73s) kubelet Liveness probe failed: HTTP probe failed with statuscode: 500
Normal Killing 1s (x3 over 67s) kubelet Container liveness failed liveness probe, will be restarted
Normal Pulling 1s (x4 over 99s) kubelet Pulling image "mirrorgooglecontainers/liveness"
tcpSocket方式檢測存活示例
建立一個 Pod ,其中執行一個基於 goproxy
映象的容器:
apiVersion: v1
kind: Pod
metadata:
name: goproxy
labels:
app: goproxy
spec:
containers:
- name: goproxy
image: mirrorgooglecontainers/goproxy:0.1
ports:
- containerPort: 8080
readinessProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 15
periodSeconds: 20
kubelet 會在容器啟動 5 秒後傳送第一個就緒探測。 這會嘗試連線 goproxy
容器的 8080 埠。 如果探測成功,這個 Pod 會被標記為就緒狀態,kubelet 將繼續每隔 10 秒執行一次檢測。
除了就緒探測,這個配置包括了一個存活探測。 kubelet 會在容器啟動 15 秒後進行第一次存活探測。 與就緒探測類似,會嘗試連線 goproxy
容器的 8080 埠。 如果存活探測失敗,這個容器會被重新啟動。