基礎概念
探針 是由 kubelet 對容器執行的定期診斷。
針對運行中的容器,kubelet 可以選擇是否執行以下三種探針,以及如何針對探測結果作出反應:
- livenessProbe:指示容器是否正在運行。如果存活態探測失敗,則 kubelet 會殺死容器, 並且容器將根據其重啟策略決定未來。如果容器不提供存活探針, 則默認狀態為 Success。
- readinessProbe:指示容器是否准備好為請求提供服務。如果就緒態探測失敗, 端點控制器將從與 Pod 匹配的所有服務的端點列表中刪除該 Pod 的 IP 地址。 初始延遲之前的就緒態的狀態值默認為 Failure。 如果容器不提供就緒態探針,則默認狀態為 Success。
- startupProbe: 指示容器中的應用是否已經啟動。如果提供了啟動探針,則所有其他探針都會被 禁用,直到此探針成功為止。如果啟動探測失敗,kubelet 將殺死容器,而容器依其 重啟策略進行重啟。 如果容器沒有提供啟動探測,則默認狀態為 Success。
要執行診斷,kubelet 調用由容器實現的 Handler (處理程序)。有三種類型的處理程序:
- ExecAction: 在容器內執行指定命令。如果命令退出時返回碼為 0 則認為診斷成功。
- TCPSocketAction: 對容器的 IP 地址上的指定端口執行 TCP 檢查。如果端口打開,則診斷被認為是成功的。
- HTTPGetAction: 對容器的 IP 地址上指定端口和路徑執行 HTTP Get 請求。如果響應的狀態碼大於等於 200 且小於 400,則診斷被認為是成功的。
每次探測都將獲得以下三種結果之一:
- Success(成功):容器通過了診斷。
- Failure(失敗):容器未通過診斷。
- Unknown(未知):診斷失敗,因此不會采取任何行動。
常見配置
Probe 中有很多精確和詳細的配置,通過它們您能准確的控制 liveness 和 readiness 檢查:
- initialDelaySeconds:容器啟動后第一次執行探測是需要等待多少秒。
- periodSeconds:執行探測的頻率。默認是10秒,最小1秒。
- timeoutSeconds:探測超時時間。默認1秒,最小1秒。
- successThreshold:探測失敗后,最少連續探測成功多少次才被認定為成功。默認是 1。對於 liveness 必須是 1。最小值是 1。
- failureThreshold:探測成功后,最少連續探測失敗多少次才被認定為失敗。默認是 3。最小值是 1。
HTTP probe 中可以給 httpGet設置其他配置項:
- host:連接的主機名,默認連接到 pod 的 IP。您可能想在 http header 中設置 “Host” 而不是使用 IP。
- scheme:連接使用的 schema,默認HTTP。
- path: 訪問的HTTP server 的 path。
- httpHeaders:自定義請求的 header。HTTP運行重復的 header。
- port:訪問的容器的端口名字或者端口號。端口號必須介於 1 和 65525 之間。
對於 HTTP 探測器,kubelet 向指定的路徑和端口發送 HTTP 請求以執行檢查。 Kubelet 將 probe 發送到容器的 IP 地址,除非地址被httpGet中的可選host字段覆蓋。 在大多數情況下,您不想設置主機字段。 有一種情況下您可以設置它。 假設容器在127.0.0.1上偵聽,並且 Pod 的hostNetwork字段為 true。 然后,在httpGet下的host應該設置為127.0.0.1。 如果您的 pod 依賴於虛擬主機,這可能是更常見的情況,您不應該是用host,而是應該在httpHeaders中設置Host頭。
示例
官網例子中提供的鏡像是k8s.gcr.io/busybox,在國內拉取不了,需要換成地址,具體看這篇文章:https://www.cnblogs.com/saolv/p/12996115.html
或者換成其他鏡像進行測試,比如下方說的nginx鏡像
測試的話可以把鏡像換成nginx,探測80端口,等pod起來后,登錄進容器,手動修改nginx使用的80端口,然后重啟nginx服務,從而觸發有關探針,進而實現pod重啟
liveness ExecAction
以下是 Pod 的配置文件 exec-liveness.yaml:
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-exec
spec:
containers:
- name: liveness
image: k8s.gcr.io/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
該配置文件給 Pod 配置了一個容器。periodSeconds 規定 kubelet 要每隔5秒執行一次 liveness probe。 initialDelaySeconds 告訴 kubelet 在第一次執行 probe 之前要的等待5秒鍾。探針檢測命令是在容器中執行 cat /tmp/healthy 命令。如果命令執行成功,將返回0,kubelet 就會認為該容器是活着的並且很健康。如果返回非0值,kubelet 就會殺掉這個容器並重啟它。
在容器生命的最初30秒內有一個 /tmp/healthy 文件,在這30秒內 cat /tmp/healthy命令會返回一個成功的返回碼。30秒后, cat /tmp/healthy 將返回失敗的返回碼。
# 創建pod
kubectl create -f exec-liveness.yaml
# 在30秒內,查看 Pod 的 event,結果顯示沒有失敗的 liveness probe
kubectl describe pod liveness-exec
# 35秒后,再次查看 Pod 的 event,在最下面有一條信息顯示 liveness probe 失敗,容器被刪掉並重新創建
# 再等30秒,確認容器已經重啟
kubectl get pod liveness-exec
# 從輸出結果來RESTARTS值加1了。
liveness HTTP請求
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-http
spec:
containers:
- name: liveness
image: k8s.gcr.io/liveness
args:
- /server
livenessProbe:
httpGet:
path: /healthz
port: 8080
httpHeaders:
- name: X-Custom-Header
value: Awesome
initialDelaySeconds: 3
periodSeconds: 3
liveness tcpSocket
apiVersion: v1
kind: Pod
metadata:
name: goproxy
labels:
app: goproxy
spec:
containers:
- name: goproxy
image: k8s.gcr.io/goproxy:0.1
ports:
- containerPort: 8080
readinessProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 15
periodSeconds: 20
readiness probe
Readiness probe的配置跟liveness probe很像。唯一的不同是使用 readinessProbe而不是livenessProbe。
readinessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5
Readiness probe 的 HTTP 和 TCP 的探測器配置跟 liveness probe 一樣。
Readiness 和 livenss probe 可以並行用於同一容器。 使用兩者可以確保流量無法到達未准備好的容器,並且容器在失敗時重新啟動。
何時該使用存活態探針
如果容器中的進程能夠在遇到問題或不健康的情況下自行崩潰,則不一定需要存活態探針; kubelet 將根據 Pod 的restartPolicy 自動執行修復操作。
如果你希望容器在探測失敗時被殺死並重新啟動,那么請指定一個存活態探針, 並指定restartPolicy 為 "Always" 或 "OnFailure"。
何時該使用就緒態探針
如果要僅在探測成功時才開始向 Pod 發送請求流量,請指定就緒態探針。 在這種情況下,就緒態探針可能與存活態探針相同,但是規約中的就緒態探針的存在意味着 Pod 將在啟動階段不接收任何數據,並且只有在探針探測成功后才開始接收數據。
如果你的容器需要加載大規模的數據、配置文件或者在啟動期間執行遷移操作,可以添加一個 就緒態探針。
如果你希望容器能夠自行進入維護狀態,也可以指定一個就緒態探針,檢查某個特定於 就緒態的因此不同於存活態探測的端點。
何時該使用啟動探針
對於所包含的容器需要較長時間才能啟動就緒的 Pod 而言,啟動探針是有用的。 你不再需要配置一個較長的存活態探測時間間隔,只需要設置另一個獨立的配置選定, 對啟動期間的容器執行探測,從而允許使用遠遠超出存活態時間間隔所允許的時長。
如果你的容器啟動時間通常超出 initialDelaySeconds + failureThreshold × periodSeconds 總值,你應該設置一個啟動探測,對存活態探針所使用的同一端點執行檢查。 periodSeconds 的默認值是 30 秒。你應該將其 failureThreshold 設置得足夠高, 以便容器有充足的時間完成啟動,並且避免更改存活態探針所使用的默認值。 這一設置有助於減少死鎖狀況的發生。
匯總
使用tcpSocket方式探測端口是否啟動,使用httpGet方式探測服務是否就緒
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-v1
namespace: blue-green
spec:
replicas: 1
selector:
matchLabels:
app: myapp
version: v1
template:
metadata:
labels:
app: myapp
version: v1
spec:
containers:
- name: myapp
image: jdd.io/demo:20210402174646
imagePullPolicy: IfNotPresent
livenessProbe:
tcpSocket:
port: 8888
initialDelaySeconds: 15
periodSeconds: 20
readinessProbe:
httpGet:
path: /hello/test
port: 8888
initialDelaySeconds: 5
periodSeconds: 10
imagePullSecrets:
- name: regcred
額外補充:使用命名的端口
可以使用命名的 ContainerPort 作為 HTTP 或 TCP liveness檢查:
ports:
- name: liveness-port
containerPort: 8080
hostPort: 8080
livenessProbe:
httpGet:
path: /healthz
port: liveness-port