4.Pod的生命周期和重啟策略
-
生命周期
- Pod 遵循一個(gè)預(yù)定義的生命周期吴叶,起始于
Pending
階段开呐,如果至少 其中有一個(gè)主要容器正常啟動杜耙,則進(jìn)入Running
搜骡,之后取決于 Pod 中是否有容器以 失敗狀態(tài)結(jié)束而進(jìn)入Succeeded
或者Failed
階段。
- Pod 遵循一個(gè)預(yù)定義的生命周期吴叶,起始于
-
Pod狀態(tài)
-
Pending(懸決)
Pod 已被 Kubernetes 系統(tǒng)接受佑女,但有一個(gè)或者多個(gè)容器尚未創(chuàng)建亦未運(yùn)行记靡。
此階段包括等待 Pod 被調(diào)度的時(shí)間和通過網(wǎng)絡(luò)下載鏡像的時(shí)間。
-
Running
(運(yùn)行中)Pod 已經(jīng)綁定到了某個(gè)節(jié)點(diǎn)团驱,Pod 中所有的容器都已被創(chuàng)建摸吠。
至少有一個(gè)容器仍在運(yùn)行,或者正處于啟動或重啟狀態(tài)嚎花。
-
Succeeded
(成功)- Pod 中的所有容器都已成功終止寸痢,并且不會再重啟。
-
Failed
(失斘裳 )Pod 中的所有容器都已終止啼止,并且至少有一個(gè)容器是因?yàn)槭〗K止道逗。
也就是說,容器以非 0 狀態(tài)退出或者被系統(tǒng)終止献烦。
如果某節(jié)點(diǎn)死掉或者與集群中其他節(jié)點(diǎn)失聯(lián)滓窍,Kubernetes 會實(shí)施一種策略,將失去的節(jié)點(diǎn)上運(yùn)行的所有 Pod 的
phase
設(shè)置為Failed
巩那。
-
Unknown
(未知)因?yàn)槟承┰驘o法取得 Pod 的狀態(tài)吏夯。
這種情況通常是因?yàn)榕c Pod 所在主機(jī)通信失敗。
-
-
Pod重啟策略
Pod的重啟策略(RestartPolicy)應(yīng)用于Pod內(nèi)的所有容器即横,并且僅在Pod所處的Node上由kubelet進(jìn)行判斷和重啟操作噪生。
當(dāng)某個(gè)容器異常退出或者健康檢查失敗時(shí),kubelet將根據(jù)RestartPolicy的設(shè)置來進(jìn)行相應(yīng)的操作东囚。
-
Pod的重啟策略包括Always跺嗽、OnFailure和Never,默認(rèn)值為Always舔庶。
Always:當(dāng)容器失效時(shí)抛蚁,由kubelet自動重啟該容器。
OnFailure:當(dāng)容器終止運(yùn)行且退出碼不為0時(shí)惕橙,由kubelet自動重啟該容器瞧甩。
Never:不論容器運(yùn)行狀態(tài)如何,kubelet都不會重啟該容器弥鹦。
kubelet重啟失效容器的時(shí)間間隔以sync-frequency乘以2n來計(jì)算肚逸,例如1、2彬坏、4朦促、8倍等,最長延時(shí)5min栓始,并且在成功重啟后的10min后重置該時(shí)間务冕。
-
Pod的重啟策略與<font color=red>控制方式</font>息息相關(guān),當(dāng)前可用于管理Pod的控制器包括ReplicationController幻赚、Job禀忆、DaemonSet及直接通過kubelet管理(靜態(tài)Pod)。每種控制器對Pod的重啟策略要求如下:
RC和DaemonSet:必須設(shè)置為Always落恼,需要保證該容器持續(xù)運(yùn)行箩退。
Job:OnFailure或Never,確保容器執(zhí)行完成后不再重啟佳谦。
kubelet:在Pod失效時(shí)自動重啟它戴涝,不論將RestartPolicy設(shè)置為什么值,也不會對Pod進(jìn)行健康檢查。
結(jié)合Pod的狀態(tài)和重啟策略啥刻,列出一些常見的狀態(tài)轉(zhuǎn)換場景:
5.Pod健康檢查和服務(wù)可用性檢查
5.1 Kubernetes 對 Pod 的健康狀態(tài)可以通過探針來檢查
? Kubernetes 對 Pod 的健康狀態(tài)可以通過探針來檢查奸鸯,kubelet定期執(zhí)行探針來診斷容器的健康狀況。
-
LivenessProbe探針:
-
用于判斷容器是否存活(Running狀態(tài))
如果LivenessProbe探針探測到容器不健康郑什,則kubelet將殺掉該容器府喳,并根據(jù)容器的重啟策略做相應(yīng)的處理。
如果一個(gè)容器不包含LivenessProbe探針蘑拯,那么kubelet認(rèn)為該容器的LivenessProbe探針返回的值永遠(yuǎn)是Success。
-
-
ReadinessProbe探針:
-
用于判斷容器服務(wù)是否可用(Ready狀態(tài))兜粘,達(dá)到Ready狀態(tài)的Pod才可以接收請求申窘。
對于被Service管理的Pod,Service與Pod Endpoint的關(guān)聯(lián)關(guān)系也將基于Pod是否Ready進(jìn)行設(shè)置孔轴。
如果在運(yùn)行過程中Ready狀態(tài)變?yōu)镕alse剃法,則系統(tǒng)自動將其從Service的后端Endpoint列表中隔離出去晶府,后續(xù)再把恢復(fù)到Ready狀態(tài)的Pod加回后端Endpoint列表规个。
這樣就能保證客戶端在訪問Service時(shí)不會被轉(zhuǎn)發(fā)到服務(wù)不可用的Pod實(shí)例上。
-
-
startupProbe探針:
-
指示容器中的應(yīng)用是否已經(jīng)啟動围俘。
如果提供了啟動探針晋柱,則所有其他探針都會被 禁用优构,直到此探針成功為止。
如果啟動探測失敗雁竞,
kubelet
將殺死容器钦椭,而容器依其 重啟策略進(jìn)行重啟。如果容器沒有提供啟動探測碑诉,則默認(rèn)狀態(tài)為
Success
彪腔。
-
5.2 LivenessProbe和ReadinessProbe均可配置以下三種實(shí)現(xiàn)方式
(1)定義存活命令
ExecAction:在容器內(nèi)部執(zhí)行一個(gè)命令,如果該命令的返回碼為0进栽,則表明容器健康德挣。
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 # kubelet 在容器內(nèi)執(zhí)行命令 `cat /tmp/healthy` 來進(jìn)行探測
initialDelaySeconds: 5 # `initialDelaySeconds` 字段告訴 kubelet 在執(zhí)行第一次探測前應(yīng)該等待 5 秒
periodSeconds: 5 # `periodSeconds` 字段指定了 kubelet 應(yīng)該每 5 秒執(zhí)行一次存活探測
? 在這個(gè)配置文件中,可以看到 Pod 中只有一個(gè)容器快毛。 periodSeconds
字段指定了 kubelet 應(yīng)該每 5 秒執(zhí)行一次存活探測格嗅。 initialDelaySeconds
字段告訴 kubelet 在執(zhí)行第一次探測前應(yīng)該等待 5 秒。 kubelet 在容器內(nèi)執(zhí)行命令 cat /tmp/healthy
來進(jìn)行探測祸泪。 如果命令執(zhí)行成功并且返回值為 0吗浩,kubelet 就會認(rèn)為這個(gè)容器是健康存活的。 如果這個(gè)命令返回非 0 值没隘,kubelet 會殺死這個(gè)容器并重新啟動它懂扼。
例子:
下面例子中,通過刪除/tmp/healthy,展示pod通過探針檢查健康狀態(tài)和重啟的過程阀湿。
當(dāng)容器啟動時(shí)赶熟,執(zhí)行如下的命令:
/bin/sh -c "touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600"
這個(gè)容器生命的前 30 秒, /tmp/healthy
文件是存在的陷嘴。 所以在這最開始的 30 秒內(nèi)映砖,執(zhí)行命令 cat /tmp/healthy
會返回成功代碼。 30 秒之后灾挨,執(zhí)行命令 cat /tmp/healthy
就會返回失敗錯(cuò)誤碼邑退。
創(chuàng)建 Pod:
kubectl apply -f exec-liveness.yaml
在 30 秒內(nèi),查看 Pod 的事件:
kubectl describe pod liveness-exec
輸出結(jié)果表明還沒有存活探測器失斃统巍:
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
//在輸出結(jié)果的最下面,有信息顯示存活探測器失敗了秒拔,這個(gè)容器被殺死并且被重建了莫矗。
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 秒,檢查看這個(gè)容器被重啟了:
#kubectl get pod liveness-exec
//輸出結(jié)果顯示 RESTARTS 的值增加了 1砂缩。
NAME READY STATUS RESTARTS AGE
liveness-exec 1/1 Running 1 1m
(2)定義TCP的存活探測
? TCPSocketAction:通過容器的IP地址和端口號執(zhí)行TCP檢查作谚,如果能夠建立TCP連接,則表明容器健康庵芭。
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: #tcp
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe: #存活探針
tcpSocket:
port: 8080
initialDelaySeconds: 15
periodSeconds: 20
就緒探針:kubelet 會在容器啟動 5 秒后發(fā)送第一個(gè)就緒探測妹懒。 這會嘗試連接 goproxy
容器的 8080 端口。 如果探測成功喳挑,這個(gè) Pod 會被標(biāo)記為就緒狀態(tài)彬伦,kubelet 將繼續(xù)每隔 10 秒運(yùn)行一次檢測。
存活探針:kubelet 會在容器啟動 15 秒后進(jìn)行第一次存活探測伊诵。 與就緒探測類似单绑,會嘗試連接 goproxy
容器的 8080 端口。 如果存活探測失敗曹宴,這個(gè)容器會被重新啟動搂橙。
(3)定義一個(gè)存活態(tài)HTTP請求接口
? HTTPGetAction:通過容器的IP地址、端口號及路徑調(diào)用HTTP Get方法笛坦,如果響應(yīng)的狀態(tài)碼大于等于200且小于400区转,則認(rèn)為容器健康。
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 #啟動容器后進(jìn)行首次健康檢查的等待時(shí)間版扩,單位為s废离。
periodSeconds: 3 #每隔3s檢查一次
timeoutSeconds:1 #健康檢查發(fā)送請求后等待響應(yīng)的超時(shí)時(shí)間,單位為s礁芦。當(dāng)超時(shí)發(fā)生時(shí)蜻韭,kubelet會認(rèn)為容器已經(jīng)無法提供服務(wù)悼尾,將會重啟該容器。
? 在這個(gè)配置文件中肖方,可以看到 Pod 也只有一個(gè)容器闺魏。 periodSeconds
字段指定了 kubelet 每隔 3 秒執(zhí)行一次存活探測。 initialDelaySeconds
字段告訴 kubelet 在執(zhí)行第一次探測前應(yīng)該等待 3 秒俯画。 kubelet 會向容器內(nèi)運(yùn)行的服務(wù)(服務(wù)會監(jiān)聽 8080 端口)發(fā)送一個(gè) HTTP GET 請求來執(zhí)行探測析桥。 如果服務(wù)器上 /healthz
路徑下的處理程序返回成功代碼,則 kubelet 認(rèn)為容器是健康存活的艰垂。 如果處理程序返回失敗代碼泡仗,則 kubelet 會殺死這個(gè)容器并且重新啟動它。
? 任何大于或等于 200 并且小于 400 的返回代碼標(biāo)示成功材泄,其它返回代碼都標(biāo)示失敗沮焕。