W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
這篇文章介紹如何給容器配置活躍(Liveness)、就緒(Readiness)和啟動(Startup)探測器。
kubelet 使用存活探測器來確定什么時候要重啟容器。 例如,存活探測器可以探測到應用死鎖(應用程序在運行,但是無法繼續(xù)執(zhí)行后面的步驟)情況。 重啟這種狀態(tài)下的容器有助于提高應用的可用性,即使其中存在缺陷。
kubelet 使用就緒探測器可以知道容器何時準備好接受請求流量,當一個 Pod 內(nèi)的所有容器都就緒時,才能認為該 Pod 就緒。 這種信號的一個用途就是控制哪個 Pod 作為 Service 的后端。 若 Pod 尚未就緒,會被從 Service 的負載均衡器中剔除。
kubelet 使用啟動探測器來了解應用容器何時啟動。 如果配置了這類探測器,你就可以控制容器在啟動成功后再進行存活性和就緒態(tài)檢查, 確保這些存活、就緒探測器不會影響應用的啟動。 啟動探測器可以用于對慢啟動容器進行存活性檢測,避免它們在啟動運行之前就被殺掉。
你必須擁有一個 Kubernetes 的集群,同時你的 Kubernetes 集群必須帶有 kubectl 命令行工具。 建議在至少有兩個節(jié)點的集群上運行本教程,且這些節(jié)點不作為控制平面主機。 如果你還沒有集群,你可以通過 Minikube 構建一個你自己的集群,或者你可以使用下面任意一個 Kubernetes 工具構建:
許多長時間運行的應用最終會進入損壞狀態(tài),除非重新啟動,否則無法被恢復。 Kubernetes 提供了存活探測器來發(fā)現(xiàn)并處理這種情況。
在本練習中,你會創(chuàng)建一個 Pod,其中運行一個基于 ?k8s.gcr.io/busybox
? 鏡像的容器。 下面是這個 Pod 的配置文件。
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 -f /tmp/healthy; sleep 600
livenessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5
在這個配置文件中,可以看到 Pod 中只有一個 ?Container
?。 ?periodSeconds
?字段指定了 kubelet 應該每 5 秒執(zhí)行一次存活探測。 ?initialDelaySeconds
?字段告訴 kubelet 在執(zhí)行第一次探測前應該等待 5 秒。 kubelet 在容器內(nèi)執(zhí)行命令 ?cat /tmp/healthy
? 來進行探測。 如果命令執(zhí)行成功并且返回值為 0,kubelet 就會認為這個容器是健康存活的。 如果這個命令返回非 0 值,kubelet 會殺死這個容器并重新啟動它。
當容器啟動時,執(zhí)行如下的命令:
/bin/sh -c "touch /tmp/healthy; sleep 30; rm -f /tmp/healthy; sleep 600"
這個容器生命的前 30 秒,?/tmp/healthy
? 文件是存在的。 所以在這最開始的 30 秒內(nèi),執(zhí)行命令 ?cat /tmp/healthy
? 會返回成功代碼。 30 秒之后,執(zhí)行命令 ?cat /tmp/healthy
? 就會返回失敗代碼。
創(chuàng)建 Pod:
kubectl apply -f https://k8s.io/examples/pods/probe/exec-liveness.yaml
在 30 秒內(nèi),查看 Pod 的事件:
kubectl describe pod liveness-exec
輸出結果表明還沒有存活探測器失敗:
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
24s 24s 1 {default-scheduler } Normal Scheduled Successfully assigned liveness-exec to worker0
23s 23s 1 {kubelet worker0} spec.containers{liveness} Normal Pulling pulling image "k8s.gcr.io/busybox"
23s 23s 1 {kubelet worker0} spec.containers{liveness} Normal Pulled Successfully pulled image "k8s.gcr.io/busybox"
23s 23s 1 {kubelet worker0} spec.containers{liveness} Normal Created Created container with docker id 86849c15382e; Security:[seccomp=unconfined]
23s 23s 1 {kubelet worker0} spec.containers{liveness} Normal Started Started container with docker id 86849c15382e
35 秒之后,再來看 Pod 的事件:
kubectl describe pod liveness-exec
在輸出結果的最下面,有信息顯示存活探測器失敗了,這個容器被殺死并且被重建了。
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
37s 37s 1 {default-scheduler } Normal Scheduled Successfully assigned liveness-exec to worker0
36s 36s 1 {kubelet worker0} spec.containers{liveness} Normal Pulling pulling image "k8s.gcr.io/busybox"
36s 36s 1 {kubelet worker0} spec.containers{liveness} Normal Pulled Successfully pulled image "k8s.gcr.io/busybox"
36s 36s 1 {kubelet worker0} spec.containers{liveness} Normal Created Created container with docker id 86849c15382e; Security:[seccomp=unconfined]
36s 36s 1 {kubelet worker0} spec.containers{liveness} Normal Started Started container with docker id 86849c15382e
2s 2s 1 {kubelet worker0} spec.containers{liveness} Warning Unhealthy Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory
再等 30 秒,確認這個容器被重啟了:
kubectl get pod liveness-exec
輸出結果顯示 ?RESTARTS
?的值增加了 1。
NAME READY STATUS RESTARTS AGE
liveness-exec 1/1 Running 1 1m
另外一種類型的存活探測方式是使用 HTTP GET 請求。 下面是一個 Pod 的配置文件,其中運行一個基于 ?k8s.gcr.io/liveness
? 鏡像的容器。
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: Custom-Header
value: Awesome
initialDelaySeconds: 3
periodSeconds: 3
在這個配置文件中,你可以看到 Pod 也只有一個容器。 ?periodSeconds
?字段指定了 kubelet 每隔 3 秒執(zhí)行一次存活探測。 ?initialDelaySeconds
?字段告訴 kubelet 在執(zhí)行第一次探測前應該等待 3 秒。 kubelet 會向容器內(nèi)運行的服務(服務在監(jiān)聽 8080 端口)發(fā)送一個 HTTP GET 請求來執(zhí)行探測。 如果服務器上 ?/healthz
? 路徑下的處理程序返回成功代碼,則 kubelet 認為容器是健康存活的。 如果處理程序返回失敗代碼,則 kubelet 會殺死這個容器并將其重啟。
返回大于或等于 200 并且小于 400 的任何代碼都標示成功,其它返回代碼都標示失敗。
你可以訪問 server.go。 閱讀服務的源碼。 容器存活期間的最開始 10 秒中,?/healthz
? 處理程序返回 200 的狀態(tài)碼。 之后處理程序返回 500 的狀態(tài)碼。
http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
duration := time.Now().Sub(started)
if duration.Seconds() > 10 {
w.WriteHeader(500)
w.Write([]byte(fmt.Sprintf("error: %v", duration.Seconds())))
} else {
w.WriteHeader(200)
w.Write([]byte("ok"))
}
})
kubelet 在容器啟動之后 3 秒開始執(zhí)行健康檢測。所以前幾次健康檢查都是成功的。 但是 10 秒之后,健康檢查會失敗,并且 kubelet 會殺死容器再重新啟動容器。
創(chuàng)建一個 Pod 來測試 HTTP 的存活檢測:
kubectl apply -f https://k8s.io/examples/pods/probe/http-liveness.yaml
10 秒之后,通過查看 Pod 事件來確認活躍探測器已經(jīng)失敗,并且容器被重新啟動了。
kubectl describe pod liveness-http
在 1.13 之前(包括 1.13)的版本中,如果在 Pod 運行的節(jié)點上設置了環(huán)境變量 ?http_proxy
?(或者 ?HTTP_PROXY
?),HTTP 的存活探測會使用這個代理。 在 1.13 之后的版本中,設置本地的 HTTP 代理環(huán)境變量不會影響 HTTP 的存活探測。
第三種類型的存活探測是使用 TCP 套接字。 使用這種配置時,kubelet 會嘗試在指定端口和容器建立套接字鏈接。 如果能建立連接,這個容器就被看作是健康的,如果不能則這個容器就被看作是有問題的。
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
如你所見,TCP 檢測的配置和 HTTP 檢測非常相似。 下面這個例子同時使用就緒和存活探測器。kubelet 會在容器啟動 5 秒后發(fā)送第一個就緒探測。 探測器會嘗試連接 ?goproxy
?容器的 8080 端口。 如果探測成功,這個 Pod 會被標記為就緒狀態(tài),kubelet 將繼續(xù)每隔 10 秒運行一次檢測。
除了就緒探測,這個配置包括了一個存活探測。 kubelet 會在容器啟動 15 秒后進行第一次存活探測。 與就緒探測類似,活躍探測器會嘗試連接 ?goproxy
?容器的 8080 端口。 如果存活探測失敗,容器會被重新啟動。
kubectl apply -f https://k8s.io/examples/pods/probe/tcp-liveness-readiness.yaml
15 秒之后,通過看 Pod 事件來檢測存活探測器:
kubectl describe pod goproxy
FEATURE STATE: Kubernetes v1.24 [beta]
如果你的應用實現(xiàn)了 gRPC 健康檢查協(xié)議, kubelet 可以配置為使用該協(xié)議來執(zhí)行應用活躍性檢查。 你必須啟用 ?GRPCContainerProbe
?特性門控 才能配置依賴于 gRPC 的檢查機制。
下面是一個示例清單:
apiVersion: v1
kind: Pod
metadata:
name: etcd-with-grpc
spec:
containers:
- name: etcd
image: k8s.gcr.io/etcd:3.5.1-0
command: [ "/usr/local/bin/etcd", "--data-dir", "/var/lib/etcd", "--listen-client-urls", "http://0.0.0.0:2379", "--advertise-client-urls", "http://127.0.0.1:2379", "--log-level", "debug"]
ports:
- containerPort: 2379
livenessProbe:
grpc:
port: 2379
initialDelaySeconds: 10
要使用 gRPC 探測器,必須配置 ?port
?屬性。如果健康狀態(tài)端點配置在非默認服務之上, 你還必須設置 ?service
?屬性。
Note:
與 HTTP 和 TCP 探測器不同,gRPC 探測不能使用命名端口或定制主機。
配置問題(例如:錯誤的 ?port
?和 ?service
?、未實現(xiàn)健康檢查協(xié)議) 都被認作是探測失敗,這一點與 HTTP 和 TCP 探測器類似。
kubectl apply -f https://k8s.io/examples/pods/probe/grpc-liveness.yaml
15 秒鐘之后,查看 Pod 事件確認活躍性檢查并未失?。?
kubectl describe pod etcd-with-grpc
在 Kubernetes 1.23 之前,gRPC 健康探測通常使用 grpc-health-probe 來實現(xiàn)。 內(nèi)置的 gRPC 探測器行為與 ?grpc-health-probe
? 所實現(xiàn)的行為類似。 從 ?grpc-health-probe
? 遷移到內(nèi)置探測器時,請注意以下差異:
grpc-health-probe
? 那樣通常針對 ?127.0.0.1
? 執(zhí)行探測; 請一定配置你的 gRPC 端點使之監(jiān)聽于 Pod 的 IP 地址之上。
tls
?)。
ExecProbeTimeout
?特性門控被設置為 ?false
?,則 ?grpc-health-probe
? 不會考慮 ?timeoutSeconds
?設置狀態(tài)(默認值為 1s), 而內(nèi)置探測器則會在超時時返回失敗。對于 HTTP 或者 TCP 存活檢測可以使用命名的 ContainerPort。
ports:
- name: liveness-port
containerPort: 8080
hostPort: 8080
livenessProbe:
httpGet:
path: /healthz
port: liveness-port
有時候,會有一些現(xiàn)有的應用在啟動時需要較長的初始化時間。 要這種情況下,若要不影響對死鎖作出快速響應的探測,設置存活探測參數(shù)是要技巧的。 技巧就是使用相同的命令來設置啟動探測,針對 HTTP 或 TCP 檢測,可以通過將 ?failureThreshold * periodSeconds
? 參數(shù)設置為足夠長的時間來應對糟糕情況下的啟動時間。
這樣,前面的例子就變成了:
ports:
- name: liveness-port
containerPort: 8080
hostPort: 8080
livenessProbe:
httpGet:
path: /healthz
port: liveness-port
failureThreshold: 1
periodSeconds: 10
startupProbe:
httpGet:
path: /healthz
port: liveness-port
failureThreshold: 30
periodSeconds: 10
幸虧有啟動探測,應用程序?qū)凶疃?nbsp;5 分鐘(30 * 10 = 300s)的時間來完成其啟動過程。 一旦啟動探測成功一次,存活探測任務就會接管對容器的探測,對容器死鎖作出快速響應。 如果啟動探測一直沒有成功,容器會在 300 秒后被殺死,并且根據(jù) ?restartPolicy
?來 執(zhí)行進一步處置。
有時候,應用會暫時性地無法為請求提供服務。 例如,應用在啟動時可能需要加載大量的數(shù)據(jù)或配置文件,或是啟動后要依賴等待外部服務。 在這種情況下,既不想殺死應用,也不想給它發(fā)送請求。 Kubernetes 提供了就緒探測器來發(fā)現(xiàn)并緩解這些情況。 容器所在 Pod 上報還未就緒的信息,并且不接受通過 Kubernetes Service 的流量。
Note: 就緒探測器在容器的整個生命周期中保持運行狀態(tài)。
Caution: 活躍探測器 不等待 就緒性探測器成功。 如果要在執(zhí)行活躍探測器之前等待,應該使用 ?
initialDelaySeconds
?或 ?startupProbe
?。
就緒探測器的配置和存活探測器的配置相似。 唯一區(qū)別就是要使用 ?readinessProbe
?字段,而不是 ?livenessProbe
?字段。
readinessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5
HTTP 和 TCP 的就緒探測器配置也和存活探測器的配置完全相同。
就緒和存活探測可以在同一個容器上并行使用。 兩者都可以確保流量不會發(fā)給還未就緒的容器,當這些探測失敗時容器會被重新啟動。
Probe 有很多配置字段,可以使用這些字段精確地控制活躍和就緒檢測的行為:
initialDelaySeconds
?:容器啟動后要等待多少秒后才啟動存活和就緒探測器, 默認是 0 秒,最小值是 0。
periodSeconds
?:執(zhí)行探測的時間間隔(單位是秒)。默認是 10 秒。最小值是 1。
timeoutSeconds
?:探測的超時后等待多少秒。默認值是 1 秒。最小值是 1。
successThreshold
?:探測器在失敗后,被視為成功的最小連續(xù)成功數(shù)。默認值是 1。 存活和啟動探測的這個值必須是 1。最小值是 1。
failureThreshold
?:當探測失敗時,Kubernetes 的重試次數(shù)。 對存活探測而言,放棄就意味著重新啟動容器。 對就緒探測而言,放棄意味著 Pod 會被打上未就緒的標簽。默認值是 3。最小值是 1。Note:
在 Kubernetes 1.20 版本之前,?exec
?探針會忽略 ?timeoutSeconds
?: 探針會無限期地持續(xù)運行,甚至可能超過所配置的限期,直到返回結果為止。
這一缺陷在 Kubernetes v1.20 版本中得到修復。你可能一直依賴于之前錯誤的探測行為, 甚至都沒有覺察到這一問題的存在,因為默認的超時值是 1 秒鐘。 作為集群管理員,你可以在所有的 kubelet 上禁用 ?ExecProbeTimeout
?特性門控 (將其設置為 ?false
?),從而恢復之前版本中的運行行為。之后當集群中所有的 exec 探針都設置了 ?timeoutSeconds
?參數(shù)后,移除此標志重載。 如果你有 Pod 受到此默認 1 秒鐘超時值的影響,你應該更新這些 Pod 對應的探針的超時值, 這樣才能為最終去除該特性門控做好準備。
當此缺陷被修復之后,在使用 ?dockershim
?容器運行時的 Kubernetes 1.20+ 版本中,對于 exec 探針而言,容器中的進程可能會因為超時值的設置保持持續(xù)運行, 即使探針返回了失敗狀態(tài)。
Caution:
如果就緒態(tài)探針的實現(xiàn)不正確,可能會導致容器中進程的數(shù)量不斷上升。 如果不對其采取措施,很可能導致資源枯竭的狀況。
HTTP Probes 允許針對 ?httpGet
?配置額外的字段:
host
?:連接使用的主機名,默認是 Pod 的 IP。也可以在 HTTP 頭中設置 “Host” 來代替。
scheme
?:用于設置連接主機的方式(HTTP 還是 HTTPS)。默認是 "HTTP"。
path
?:訪問 HTTP 服務的路徑。默認值為 "/"。
httpHeaders
?:請求中自定義的 HTTP 頭。HTTP 頭字段允許重復。
port
?:訪問容器的端口號或者端口名。如果數(shù)字必須在 1~65535 之間。對于 HTTP 探測,kubelet 發(fā)送一個 HTTP 請求到指定的路徑和端口來執(zhí)行檢測。 除非 ?httpGet
?中的 ?host
?字段設置了,否則 kubelet 默認是給 Pod 的 IP 地址發(fā)送探測。 如果 ?scheme
?字段設置為了 ?HTTPS
?,kubelet 會跳過證書驗證發(fā)送 HTTPS 請求。 大多數(shù)情況下,不需要設置?host
?字段。 這里有個需要設置 ?host
?字段的場景,假設容器監(jiān)聽 127.0.0.1,并且 Pod 的 ?hostNetwork
?字段設置為了 ?true
?。那么 ?httpGet
?中的 ?host
?字段應該設置為 127.0.0.1。 可能更常見的情況是如果 Pod 依賴虛擬主機,你不應該設置 ?host
?字段,而是應該在 ?httpHeaders
?中設置 ?Host
?。
針對 HTTP 探針,kubelet 除了必需的 ?Host
?頭部之外還發(fā)送兩個請求頭部字段: ?User-Agent
? 和 ?Accept
?。這些頭部的默認值分別是 ?kube-probe/{{ skew latestVersion >}}
? (其中 1.24 是 kubelet 的版本號)和 ?*/*
?。
你可以通過為探測設置 ?.httpHeaders
? 來重載默認的頭部字段值;例如:
livenessProbe:
httpGet:
httpHeaders:
- name: Accept
value: application/json
startupProbe:
httpGet:
httpHeaders:
- name: User-Agent
value: MyUserAgent
你也可以通過將這些頭部字段定義為空值,從請求中去掉這些頭部字段。
livenessProbe:
httpGet:
httpHeaders:
- name: Accept
value: ""
startupProbe:
httpGet:
httpHeaders:
- name: User-Agent
value: ""
對于 TCP 探測而言,kubelet 在節(jié)點上(不是在 Pod 里面)發(fā)起探測連接, 這意味著你不能在 ?host
?參數(shù)上配置服務名稱,因為 kubelet 不能解析服務名稱。
FEATURE STATE: Kubernetes v1.22 [beta]
在 1.21 發(fā)行版之前,Pod 層面的 ?terminationGracePeriodSeconds
?被用來終止活躍探測或啟動探測失敗的容器。 這一行為上的關聯(lián)不是我們想要的,可能導致 Pod 層面設置了 ?terminationGracePeriodSeconds
?時容器要花非常長的時間才能重新啟動。
在 1.21 及更高版本中,當特性門控 ?ProbeTerminationGracePeriod
?被啟用時, 用戶可以指定一個探測器層面的 ?terminationGracePeriodSeconds
?作為探測器規(guī)約的一部分。 當該特性門控被啟用,并且 Pod 層面和探測器層面的 ?terminationGracePeriodSeconds
?都已設置,kubelet 將使用探測器層面設置的值。
在 Kubernetes 1.22 中,?ProbeTerminationGracePeriod
?特性門控只能用在 API 服務器上。 kubelet 始終遵守探針級別 ?terminationGracePeriodSeconds
?字段 (如果它存在于 Pod 上)。
如果你已經(jīng)為現(xiàn)有 Pod 設置了 ?terminationGracePeriodSeconds
?字段并且不再希望使用針對每個探針的終止寬限期,則必須刪除現(xiàn)有的這類 Pod。
當你(或控制平面或某些其他組件)創(chuàng)建替換 Pod,并且特性門控 ?ProbeTerminationGracePeriod
?被禁用時,API 服務器會忽略 Pod 級別的 ?terminationGracePeriodSeconds
?字段設置, 即使 Pod 或 Pod 模板指定了它。
例如:
spec:
terminationGracePeriodSeconds: 3600 # pod-level
containers:
- name: test
image: ...
ports:
- name: liveness-port
containerPort: 8080
hostPort: 8080
livenessProbe:
httpGet:
path: /healthz
port: liveness-port
failureThreshold: 1
periodSeconds: 60
# Override pod-level terminationGracePeriodSeconds #
terminationGracePeriodSeconds: 60
探測器層面的 ?terminationGracePeriodSeconds
?不能用于就緒態(tài)探針。 這一設置將被 API 服務器拒絕。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: