保持 pod 健康 P84
只要 pod 調(diào)度到某個節(jié)點(diǎn),該節(jié)點(diǎn)上的 Kubelet 就會運(yùn)行 pod 的容器障斋,從此只要該 pod 存在,就會保持運(yùn)行徐鹤。如果容器的主進(jìn)程奔潰垃环, Kubelet 就會自動重啟容器;如果應(yīng)用程序奔潰返敬, Kubelet 就會自動重啟應(yīng)用程序晴裹。 P84
應(yīng)用程序也可能因?yàn)闊o限循環(huán)或死鎖等情況而停止響應(yīng)。為確保應(yīng)用在這種情況下可以重新啟動救赐,必須從外部檢查應(yīng)用程序的運(yùn)行狀況涧团,而不是依賴于應(yīng)用的內(nèi)部檢測。 P84
介紹存活探測器 P84
Kubernetes 可以通過存活探測器 (liveness probe) 檢查容器是否還在運(yùn)行经磅∶谛澹可以為 pod 中的每個容器單獨(dú)指定存活探測器。 Kubernetes 將定期執(zhí)行探測器预厌,如果探測失敗阿迈,就會自動重啟容器。 P84
注意:Kubernetes 還支持就緒探測器 (readiness probe) 轧叽,兩者適用于兩種不同的場景苗沧。 P84
Kubernetes 有三種探測容器的機(jī)制: P84
-
HTTP GET
探測器:對容器的 IP 地址(指定的端口和路徑)執(zhí)行HTTP GET
請求。如果探測器收到響應(yīng)炭晒,并且響應(yīng)狀態(tài)碼不代表錯誤(狀態(tài)碼為 2xx 或 3xx )待逞,則認(rèn)為探測成功。如果服務(wù)器返回錯誤響應(yīng)狀態(tài)碼或者沒有響應(yīng)网严,那么探測就被認(rèn)為是失敗的识樱,容器將被重啟。 -
TCP Socket
探測器:嘗試與容器指定端口建立 TCP 連接。如果連接成功建立怜庸,則探測成功当犯。否則,容器將被重啟割疾。 -
Exec
探測器:在容器內(nèi)執(zhí)行任意命令嚎卫,并檢查命令的退出狀態(tài)碼。如果狀態(tài)碼是 0 宏榕,則探測成功拓诸。所有其他狀態(tài)碼都被認(rèn)為失敗,容器將被重啟担扑。
創(chuàng)建基于 HTTP 的存活探測器 P85
為了讓 HTTP GET
探測器探測失敗,我們需要修改 kubia 源碼趣钱,使得其從第五次訪問之后開始一直返回 500 狀態(tài)碼 (Internal Server Error) 涌献。 P85
然后我們可以通過以下描述文件 kubia-liveness-probe.yaml
創(chuàng)建一個包含 HTTP GET
存活探測器的 pod 。 P85
# 遵循 v1 版本的 Kubernetes API
apiVersion: v1
# 資源類型為 Pod
kind: Pod
metadata:
# pod 的名稱
name: kubia-liveness
spec:
containers:
# 創(chuàng)建容器所使用的鏡像
- image: idealism/kubia-unhealthy
# 容器的名稱
name: kubia
ports:
# 應(yīng)用監(jiān)聽的端口
- containerPort: 8080
protocol: TCP
# 開啟一個存活探測器
livenessProbe:
# 存活探測器的類型為 HTTP GET
httpGet:
# 探測器連接的網(wǎng)絡(luò)端口
port: 8080
# 探測器請求的路徑
path: /
使用存活探測器 P86
使用 kubectl create -f kubia-liveness-probe.yaml
創(chuàng)建完 pod 后首有,等待一段時間后燕垃,容器將會重啟【可以通過 kubectl get pod kubia-liveness
看到容器會重啟卜壕,并且無限循環(huán)下去: 86
NAME READY STATUS RESTARTS AGE
kubia-liveness 1/1 Running 2 4m9s
kubectl logs kubia-liveness --previous
: 查看前一個容器的日志,可以了解前一個容器停止的原因烙常。 P86
kubectl describe pod kubia-liveness
: 查看 pod 詳情轴捎。可以發(fā)現(xiàn)在 Containers 和 Events 里面有終止的相關(guān)信息蚕脏。 P86
...
Containers:
kubia:
...
State: Running # 容器目前正常運(yùn)行
Started: Sun, 07 Jun 2020 17:59:35 +0800
Last State: Terminated # 前一個容器由于錯誤被終止侦副,錯誤碼是 137
Reason: Error
Exit Code: 137
Started: Sun, 07 Jun 2020 17:57:44 +0800
Finished: Sun, 07 Jun 2020 17:59:27 +0800
Ready: True
Restart Count: 2 # 該容器已被重啟 2 次
Liveness: http-get http://:8080/ delay=0s timeout=1s period=10s #success=1 #failure=3
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled <unknown> default-scheduler Successfully assigned default/kubia-liveness to minikube-m02
Warning Unhealthy 48s (x6 over 2m58s) kubelet, minikube-m02 Liveness probe failed: HTTP probe failed with statuscode: 500 # 發(fā)現(xiàn)容器不健康
Normal Killing 48s (x2 over 2m38s) kubelet, minikube-m02 Container kubia failed liveness probe, will be restarted # 終止該容器
...
錯誤碼 137 是兩個數(shù)字的總和: 128 + x , x 是終止進(jìn)程的信號編號驼鞭。 P86
- x=9 表示是
SIGKILL
的信號編號秦驯,意味著這個進(jìn)程被強(qiáng)行終止,這個信號不能被捕獲或忽略挣棕,并且在接收過程中不能執(zhí)行任何清理在接收到該信號 - x=15 表示是
SIGTERM
的信號編號译隘,意味著這個進(jìn)程被終止,先進(jìn)行詢問進(jìn)程終止洛心,讓其清理文件和關(guān)閉固耘,可以被捕獲和解釋或忽略
底部列出的事件顯示了 Kubernetes 發(fā)現(xiàn)容器不健康,所以終止并重新創(chuàng)建词身。 P86
注意:當(dāng)容器被強(qiáng)行終止時玻驻,會創(chuàng)建一個全新的容器,而不是重啟原來的容器。 P86
配置存活探測器的附加屬性 P87
可以使用 kubectl explain pod.spec.containers.livenessProbe
查看存活探測器能使用的自定義附加參數(shù)璧瞬。
基于 kubia-liveness-probe.yaml
創(chuàng)建一個新的描述文件 kubia-liveness-probe-initial-delay.yaml
户辫,并添加 pod.spec.containers.livenessProbe.initialDelaySeconds
屬性,值為 15 嗤锉,表示在第一次探測器等待 15 秒渔欢。
...
spec:
containers:
# 創(chuàng)建容器所使用的鏡像
- image: idealism/kubia-unhealthy
...
# 開啟一個存活探測器
livenessProbe:
...
# 第一次探測前等待 15 秒
initialDelaySeconds: 15
這樣可以在應(yīng)用程序準(zhǔn)備好之后再進(jìn)行探測,以免應(yīng)用程序啟動時間過長導(dǎo)致一直探測失敗而無限重啟瘟忱。
創(chuàng)建有效的存活探測器 P88
- 存活探測器應(yīng)該檢查什么:簡易的存活探測器可以僅檢查服務(wù)器是否響應(yīng)奥额,但為了更好地進(jìn)行存活檢查,需要將探測器配置為請求特定的 URL 路徑(如
/health
)访诱,并讓應(yīng)用從內(nèi)部對內(nèi)部運(yùn)行的所有重要組件執(zhí)行狀態(tài)檢查垫挨,以確保它們都沒有終止或停止響應(yīng)。P88
- 確保
/health
不需要認(rèn)證触菜,否則探測會一直失敗九榔,導(dǎo)致容器無限重啟 - 檢查應(yīng)用的內(nèi)部,檢查結(jié)果不能受任何外部因素的影響涡相。例如數(shù)據(jù)庫連不上時哲泊,存活探測器不應(yīng)該返回失敗,如果問題在數(shù)據(jù)庫催蝗,那么重啟容器不會解決問題切威。
- 確保
- 保持探測器輕量
P89
- 不應(yīng)消耗太多計(jì)算資源
- 運(yùn)行不應(yīng)花太長時間。默認(rèn)情況下丙号,探測器執(zhí)行的頻率相對較高先朦,必須在一秒之內(nèi)執(zhí)行完畢
- 無須在探測器中實(shí)現(xiàn)重試:探測器的失敗閾值是可配置的,并且通常在容器被終止之前探測器必須失敗多次
P89
- 存活探測器小結(jié):存活探測由 pod 上的 Kubelet 執(zhí)行犬缨, Kubernetes 控制面板不會參與烙无。因此節(jié)點(diǎn)奔潰時,控制面板會為所有隨節(jié)點(diǎn)停止運(yùn)行的 pod 創(chuàng)建替代者遍尺,但不會為直接創(chuàng)建的 pod 創(chuàng)建替代者截酷,因?yàn)檫@些 pod 只被節(jié)點(diǎn)上的 Kubelet 管理。為了避免這種情況發(fā)生乾戏,我們應(yīng)該使用控制器或類似機(jī)制管理 pod 迂苛。
P89
了解 Deployment
P89
注:本節(jié)中提到的 pod 受 Deployment
管理等說法為簡化說法,實(shí)際上 pod 由受 Deployment
管理創(chuàng)建的 ReplicaSet
進(jìn)行管理創(chuàng)建鼓择。
Deployment
是一種 Kubernetes 資源三幻,可確保它的 pod 始終保持運(yùn)行狀態(tài)。如果 pod 因?yàn)槿魏卧蛳Вɡ绻?jié)點(diǎn)從集群中消失或由于該 pod 已從節(jié)點(diǎn)中逐出)呐能,則 Deployment
會注意到缺少了 pod 并創(chuàng)建替代者念搬。 P89
上圖的節(jié)點(diǎn) 1 有兩個節(jié)點(diǎn), Pod A 是被直接創(chuàng)建的朗徊,而 Pod B 由 Deployment
管理首妖。節(jié)點(diǎn)異常退出后, Deployment
會創(chuàng)建一個新的 Pod B2 來替換減少的 Pod B 爷恳,而 Pod A 由于沒有東西負(fù)責(zé)重建而完全丟失有缆。 P89
Deployment
的操作 P90
Deployment
會持續(xù)監(jiān)控正在運(yùn)行的 pod 列表,并保證匹配標(biāo)簽選擇器(03. pod: 運(yùn)行于 Kubernetes 中的容器 中介紹過標(biāo)簽選擇器及使用方式)的 pod 數(shù)目與期望相符温亲。 P90
介紹控制器的協(xié)調(diào)流程 P91
Deployment
的工作是確保 pod 數(shù)量始終與其標(biāo)簽選擇器匹配棚壁。 P91
了解 Deployment 的三部分 P91
- 標(biāo)簽選擇器 (label selector) :用于確定
Deployment
作用域中有哪些 pod - 副本個數(shù) (replica count) :指定應(yīng)運(yùn)行的 pod 數(shù)量
- pod 模版 (pod template) :用于創(chuàng)建新的 pod 副本
Deployment
的副本個數(shù)、標(biāo)簽選擇器和 pod 模版都可以隨時修改栈虚,但只有副本數(shù)目但變更會影響現(xiàn)有的 pod 袖外。 P92
更改控制器的標(biāo)簽選擇器或 pod 模版的效果 P92
更改標(biāo)簽選擇器和 pod 模版對現(xiàn)有的 pod 沒有影響。更改標(biāo)簽選擇器會使現(xiàn)有的 pod 脫離 Deployment
的范圍魂务,因此控制器會停止關(guān)注它們曼验。更改模版僅影響由此 Deployment
創(chuàng)建的新 pod 。 P92
使用 Deployment
的好處 P92
- 確保 pod 持續(xù)運(yùn)行:在現(xiàn)有 pod 丟失時啟動一個新 pod
- 集群節(jié)點(diǎn)發(fā)生故障時头镊,為故障節(jié)點(diǎn)上運(yùn)行的受
Deployment
管理的所有 pod 創(chuàng)建替代副本 - 輕松實(shí)現(xiàn) pod 水平伸縮——手動和自動都可以
注意: pod 實(shí)例永遠(yuǎn)不會重新安置到另一個節(jié)點(diǎn)蚣驼。 Deployment
會創(chuàng)建一個全新的 pod 實(shí)例魄幕,它與正在替換的實(shí)例無關(guān)相艇。 P92
創(chuàng)建一個 Deployment
P92
我們可以通過以下描述文件 kubia-deployment.yaml
創(chuàng)建一個 Deployment
,它確保符合標(biāo)簽選擇器 app=kubia
的 pod 實(shí)例始終是三個纯陨。
# 遵循 v1 版本的 Kubernetes API
apiVersion: apps/v1
# 資源類型為 Deployment
kind: Deployment
metadata:
# Deployment 的名稱
name: kubia
spec:
# 指定與標(biāo)簽選擇器匹配的 pod 數(shù)目為 3
replicas: 3
# 指定 Deployment 操作對象
selector:
# 需要匹配以下指定的標(biāo)簽
matchLabels:
app: kubia
# 啟動 pod 使用的模版(可以發(fā)現(xiàn)模版內(nèi)容與 kubia-manual.yaml 對應(yīng)部分一致)
template:
metadata:
# 指定標(biāo)簽為 app=kubia
labels:
app: kubia
spec:
containers:
# 容器的名稱
- name: kubia
# 創(chuàng)建容器所使用的鏡像
image: idealism/kubia
# 應(yīng)用監(jiān)聽的端口
ports:
- containerPort: 8080
protocol: TCP
模版中的 pod 標(biāo)簽必須和 Deployment
的標(biāo)簽選擇器匹配坛芽, API 服務(wù)器會校驗(yàn) Deployment
的定義,不會接受錯誤配置翼抠。 P93
若不指定選擇器咙轩,它會自動根據(jù) pod 模版中的標(biāo)簽自動配置,這樣可以讓描述文件更簡潔阴颖。 P93
使用 Deployment
P94
kubectl create -f kubia-deployment.yaml
會創(chuàng)建一個名為 kubia 的 Deployment
活喊,它會根據(jù) pod 模版啟動三個新 pod 。 P94
kubectl get pods
可以查看當(dāng)前創(chuàng)建的所有 pod :
NAME READY STATUS RESTARTS AGE
kubia-9495d9bf5-5dwj7 1/1 Running 0 3m53s
kubia-9495d9bf5-5j6zr 1/1 Running 0 3m53s
kubia-9495d9bf5-w98f6 1/1 Running 0 3m53s
查看 Deployment
對已刪除的 pod 的響應(yīng) P94
kubectl delete pod kubia-9495d9bf5-5dwj7
會刪除一個 pod 量愧,然后再次查看當(dāng)前所有 pod 钾菊,可以發(fā)現(xiàn)會有 4 個 pod ,因?yàn)閯h除的 pod 正在終止偎肃,并且正在創(chuàng)建一個新的 pod : P94
NAME READY STATUS RESTARTS AGE
kubia-9495d9bf5-5dwj7 1/1 Terminating 0 24m
kubia-9495d9bf5-5j6zr 1/1 Running 0 24m
kubia-9495d9bf5-kxcw5 0/1 ContainerCreating 0 9s
kubia-9495d9bf5-w98f6 1/1 Running 0 24m
控制器如何創(chuàng)建新的 pod P95
控制器通過創(chuàng)建一個新的替代 pod 來響應(yīng) pod 的刪除操作煞烫。但它并沒有對刪除本身作出反應(yīng),而是針對由此產(chǎn)生對狀態(tài)—— pod 數(shù)量不足作出反應(yīng)累颂。 P95
應(yīng)對節(jié)點(diǎn)故障 P96
接下來我們將關(guān)閉一個節(jié)點(diǎn)的網(wǎng)絡(luò)接口來模擬節(jié)點(diǎn)故障。 P96
-
minikube ssh --node='m02'
: 進(jìn)入節(jié)點(diǎn)內(nèi)部 -
sudo ifconfig eth0 down
: 關(guān)閉該節(jié)點(diǎn)的網(wǎng)絡(luò)接口 -
kubectl get nodes
: 發(fā)現(xiàn)節(jié)點(diǎn)minikube-m02
的狀態(tài)為未就緒 (NotReady
) -
kubectl get pods
: 可能仍然會看到與之前相同的三個 pod ,因?yàn)?Kubernetes 在重新調(diào)度 pod 之前會等待一段時間(如果節(jié)點(diǎn)因臨時網(wǎng)絡(luò)故障或 Kubelet 重啟而無法訪問)料饥。如果節(jié)點(diǎn)在幾分鐘內(nèi)無法訪問蒲犬,Deployment
會立即啟動一個新的 pod 。
將 pod 移入/移出 Deployment
的作用域 P97
由 Deployment
創(chuàng)建的 pod 并不是綁定到 Deployment
稀火。在任何時刻暖哨, Deployment
管理與標(biāo)簽選擇器匹配的 pod 。通過更改 pod 的標(biāo)簽凰狞,可以將它從 Deployment
的作用域中添加或刪除篇裁。 P97
盡管一個 pod 沒有綁定到一個 Deployment
擁有的 ReplicaSet
,但該 pod 在 metadata.ownerReferences
中存儲它屬于哪一個 ReplicaSet
赡若。 P98
給 Deployment
管理的 pod 加標(biāo)簽 P98
kubectl label pod kubia-9495d9bf5-5mmhb type=special
: 給 pod 添加其他標(biāo)簽不會影響 Deployment
的管理范圍达布,它只關(guān)心該 pod 是否具有標(biāo)簽選擇器中引用的所有標(biāo)簽。 P98
更改已托管的 pod 的標(biāo)簽 P98
kubectl label pod kubia-9495d9bf5-5mmhb app=foo --overwrite
: 更改其中一個 pod 的標(biāo)簽將使其不再與 Deployment
的標(biāo)簽選擇器相匹配逾冬,并不再由 Deployment
管理黍聂,只剩下兩個匹配的 pod 。因此身腻, Deployment
會啟動一個新的 pod 产还,將數(shù)目恢復(fù)為三。 P98
更改 Deployment
的標(biāo)簽選擇器 P100
更改 Deployment
的標(biāo)簽選擇器會讓所有的 pod 脫離 Deployment
的管理嘀趟,導(dǎo)致它創(chuàng)建三個新的 pod 脐区。你永遠(yuǎn)不會修改控制器的標(biāo)簽選擇器,但會時不時地更改它的 pod 模版她按。 P100
修改 pod 模版 P100
Deployment
的 pod 模版可以隨時修改牛隅,可以使用 kubectl edit deployment kubia
編輯 Deployment
。更改后會重新創(chuàng)建一個新的 ReplocaSet
酌泰,并使原有的 ReplocaSet
的副本數(shù)變?yōu)?0 媒佣。因此,使用 kubectl get pods
將發(fā)現(xiàn)有 6 個 pod 陵刹,pod 的前綴是對應(yīng)的 ReplocaSet
的名稱默伍。
NAME READY STATUS RESTARTS AGE
kubia-9495d9bf5-kxcw5 1/1 Terminating 0 78m
kubia-9495d9bf5-w98f6 1/1 Terminating 0 102m
kubia-9495d9bf5-xn67d 1/1 Terminating 0 29m
kubia-bc974964b-bp4l2 1/1 Running 0 22s
kubia-bc974964b-r29j2 1/1 Running 0 39s
kubia-bc974964b-xl677 1/1 Running 0 14s
若通過 kubectl edit replicaset kubia-bc974964b
直接修改 Deployment
擁有的 ReplicaSet
實(shí)例。這樣效果和直接修改 Deployment
類似衰琐,也會創(chuàng)建一個新的 ReplicaSet
也糊,并使原有的 ReplocaSet
的副本數(shù)變?yōu)?0 。這樣修改不會將新的 pod 模版同步回原有的 Deployment
碘耳,但刪除 Deployment
時仍然會刪除所有相關(guān)的 ReplocaSet
及其管理的 pod 显设。
水平縮放 pod P101
kubectl scale deployment kubia --replicas=10
: 可以修改 Deployment
需要保持的 pod 實(shí)例的數(shù)量(02. 開始使用 Kubernetes 和 Docker中介紹過使用該命令進(jìn)行伸縮)。 P101
也可以通過 kubectl edit deployment kubia
修改 spec.replicas
的數(shù)量辛辨,從而更改需要保持的 pod 實(shí)例的數(shù)量捕捂。 P102
刪除一個 Deployment
當(dāng)通過 kubectl delete deployment kubia
刪除 Deployment
時瑟枫,對應(yīng)的 ReplicaSet
和 pod 都會被刪除。
而通過 kubectl delete replicaset kubia-bc974964b
刪除 ReplicaSet
時指攒,對應(yīng)的 pod 會被刪除慷妙,但由于 Deployment
會重新創(chuàng)建一個 Replicaset
,所以又會自動創(chuàng)建對應(yīng)數(shù)量的 pod 允悦。
當(dāng)通過 kubectl delete deployment kubia --cascade=false
刪除 Deployment
時膝擂,會保留對應(yīng)的 ReplicaSet
和 pod ,這樣ReplicaSet
不再受管理隙弛,但是 pod 仍然受 ReplicaSet
管理架馋。當(dāng)重新創(chuàng)建符合要求的 Deployment
時, ReplicaSet
又會受到管理全闷。
同樣地叉寂,通過 kubectl delete replicaset kubia-bc974964b --cascade=false
刪除 ReplicaSet
時,也會保留對應(yīng)的 pod 总珠。這樣 pod 不再受管理屏鳍。當(dāng)創(chuàng)建符合要求的 ReplicaSet
時,這些 pod 又會受到管理局服。
使用 ReplicaSet
P104
注:書中原本上一節(jié)講得是 ReplicationController
钓瞭,但我直接使用 Deployment
進(jìn)行實(shí)踐,并依照現(xiàn)在的結(jié)果進(jìn)行了修改淫奔。目前推薦使用 Deployment
山涡,并且 ReplicaSet
是受 Deployment
管理的,所以不再詳細(xì)實(shí)踐本節(jié)內(nèi)容搏讶。
使用更富有表達(dá)力的標(biāo)簽選擇器 P106
基于 kubia-deployment.yaml
創(chuàng)建一個新的描述文件 kubia-deployment-matchexpressions.yaml
佳鳖,并將 spec.selector.matchLabels
屬性替換為 spec.selector.matchExpressions
: P107
...
spec:
...
# 指定 Deployment 操作對象
selector:
# 需要匹配滿足以下要求的標(biāo)簽
matchExpressions:
# 標(biāo)簽名為 app 的值在 ["kubia"] 中
- app: app
operator: In
values:
- kubia
...
matchExpressions
運(yùn)行給選擇器添加額外的表達(dá)式霍殴。每個表達(dá)式都必須包含一個 key 媒惕、一個 operator ,并且可能還有一個 values 的列表(取決于 operator )来庭。共有四個有效的運(yùn)算符: P107
-
In
: 標(biāo)簽的值必須與其中一個指定的 values 匹配 -
NotIn
: 標(biāo)簽的值與任何指定的 values 都不匹配 -
Exists
: pod 必須包含一個指定名稱的標(biāo)簽(不關(guān)心值)妒蔚。使用此運(yùn)算符時,不應(yīng)指定 values 字段 -
DoesNotExist
: pod 不得包含指定名稱的標(biāo)簽月弛。使用此運(yùn)算符時肴盏,不應(yīng)指定 values 字段
如果指定了多個表達(dá)式,則所有這些表達(dá)式都必須為 true 才能使選擇器與 pod 匹配帽衙。如果同時指定 matchLabels
和 matchExpressions
菜皂,則所有標(biāo)簽都必須匹配,且所有表達(dá)式都必須為 true 才能使選擇器與 pod 匹配厉萝。 P107
使用 DaemonSet
在每個節(jié)點(diǎn)上運(yùn)行一個 pod P107
DaemonSet
可以讓 pod 在集群中的每個節(jié)點(diǎn)上運(yùn)行恍飘,并且每個節(jié)點(diǎn)正好有一個運(yùn)行的 pod 實(shí)例榨崩。 P107
使用 DaemonSet
在每個節(jié)點(diǎn)上運(yùn)行一個 pod P108
DaemonSet
沒有副本數(shù)的概念,它確保創(chuàng)建足夠的 pod 章母,并在每一個節(jié)點(diǎn)上部署一個 pod 母蛛。如果節(jié)點(diǎn)下線, DaemonSet
不會重新創(chuàng)建 pod 乳怎;但新節(jié)點(diǎn)添加到集群中彩郊,它會立刻部署一個新的 pod 實(shí)例到該節(jié)點(diǎn)。 P108
使用 DaemonSet
只在特定的節(jié)點(diǎn)上運(yùn)行 pod P109
DaemonSet
將 pod 部署到集群的所有節(jié)點(diǎn)上蚪缀,除非通過 pod 模版中的 spec.nodeSelector
屬性指定這些 pod 只在部分節(jié)點(diǎn)上運(yùn)行秫逝。 P109
注意:節(jié)點(diǎn)可以被設(shè)置為不可調(diào)度,防止 pod 被部署到節(jié)點(diǎn)上询枚。但 DaemonSet
會將 pod 部署到這些節(jié)點(diǎn)上筷登,因?yàn)闊o法調(diào)度但屬性只會被調(diào)度器使用,而 DaemonSet
的目的是運(yùn)行系統(tǒng)服務(wù)哩盲,即使在不可調(diào)度的節(jié)點(diǎn)上前方,系統(tǒng)服務(wù)通常也需要運(yùn)行。 P109
用一個例子來解釋 DaemonSet
P109
假設(shè)有一個名為 ssd-monitor
的守護(hù)進(jìn)程廉油,它需要在包含 SSD 的所有節(jié)點(diǎn)上運(yùn)行惠险。包含 SSD 的節(jié)點(diǎn)已被添加了 disk=ssd
標(biāo)簽,所以我們需要創(chuàng)建一個 DaemonSet
抒线,它只在擁有上述標(biāo)簽的節(jié)點(diǎn)上運(yùn)行守護(hù)進(jìn)程班巩。 P109
創(chuàng)建一個 DaemonSet
描述文件 P110
為了模擬 ssd-monitor
的監(jiān)控程序,我們將使用以下 Dockerfile
創(chuàng)建一個每 5 秒中打印 SSD OK
的鏡像嘶炭。
FROM busybox
ENTRYPOINT while true; do echo 'SSD OK'; sleep 5; done
為了將 ssd-monitor
部署到符合要求的每個節(jié)點(diǎn)上抱慌,我們還需要使用以下 ssd-monitor-daemonset.yaml
描述文件進(jìn)行部署。
# 遵循 apps/v1 版本的 Kubernetes API
apiVersion: apps/v1
# 資源類型為 DaemonSet
kind: DaemonSet
metadata:
# DaemonSet 的名稱
name: ssd-monitor
spec:
# 指定 DaemonSet 操作對象
selector:
# 需要匹配以下指定的標(biāo)簽
matchLabels:
app: ssd-monitor
# 啟動 pod 使用的模版
template:
metadata:
# 指定標(biāo)簽為 app=ssd-monitor
labels:
app: ssd-monitor
spec:
# 指定選擇具有 disk=ssd 標(biāo)簽的節(jié)點(diǎn)部署
nodeSelector:
disk: ssd
containers:
# 容器的名稱
- name: main
# 創(chuàng)建容器所使用的鏡像
image: idealism/ssd-monitor
實(shí)踐 P110
-
kubectl create -f ssd-monitor-daemonset.yaml
: 按照指定的描述文件創(chuàng)建一個DaemonSet
-
kubectl get daemonsets
: 可以發(fā)現(xiàn)所有的值都是 0 眨猎,因?yàn)槟壳斑€沒有節(jié)點(diǎn)擁有disk=ssd
標(biāo)簽 -
kubectl get pods
: 可以發(fā)現(xiàn)目前還沒有 pod -
kubectl label node minikube-m03 disk=ssd
: 給節(jié)點(diǎn)minikube-m03
打上標(biāo)簽disk=ssd
-
kubectl get pods
: 可以發(fā)現(xiàn)剛剛啟動了一個 podNAME READY STATUS RESTARTS AGE ssd-monitor-bbqbp 0/1 ContainerCreating 0 2s
-
kubectl label node minikube-m03 disk=hdd --overwrite
: 將節(jié)點(diǎn)minikube-m03
的標(biāo)簽disk=ssd
修改為disk=hdd
-
kubectl get pods
: 可以發(fā)現(xiàn)剛剛啟動的 pod 正在終止NAME READY STATUS RESTARTS AGE ssd-monitor-bbqbp 1/1 Terminating 0 2m37s
運(yùn)行執(zhí)行單個任務(wù)的 pod P112
介紹 Job
資源 P112
Kubernetes 通過 Job
資源支持運(yùn)行一種 pod 抑进,該 pod 子啊內(nèi)部進(jìn)程成功結(jié)束時,不重啟容器睡陪。一旦任務(wù)完成寺渗, pod 就被認(rèn)為處于完成狀態(tài)。 P112
在節(jié)點(diǎn)發(fā)生故障時兰迫,該節(jié)點(diǎn)上由 Job
管理的 pod 將被重新安排到其他節(jié)點(diǎn)信殊。如果進(jìn)程本身異常退出(進(jìn)程返回錯誤退出碼時),可以將 Job
配置為重新啟動容器汁果。 P112
定義 Job
資源 P113
為了模擬耗時的任務(wù),我們將使用以下 Dockerfile
創(chuàng)建一個調(diào)用 sleep 120
命令的鏡像据德。
FROM busybox
ENTRYPOINT echo "$(date) Batch job starting"; sleep 120; echo "$(date) Finished succesfully"
為了管理部署 batch-job
鳄乏,我們還需要使用以下 batch-job.yaml
描述文件進(jìn)行部署府蔗。
# 遵循 batch/v1 版本的 Kubernetes API
apiVersion: batch/v1
# 資源類型為 Job
kind: Job
metadata:
# Job 的名稱
name: batch-job
spec:
# 啟動 pod 使用的模版
template:
metadata:
# 指定標(biāo)簽為 app=batch-job
labels:
app: batch-job
spec:
# Job 不能使用 Always 為默認(rèn)的重啟策略
restartPolicy: OnFailure
containers:
# 容器的名稱
- name: main
# 創(chuàng)建容器所使用的鏡像
image: idealism/batch-job
設(shè)置 Job
的重啟策略為 OnFailure
或 Never
可以防止容器在完成任務(wù)時重新啟動。 P114
Job
運(yùn)行一個 pod P114
-
kubectl create -f batch-job.yaml
: 根據(jù)描述文件創(chuàng)建指定的Job
-
kubectl get jobs
: 查看 job 汞窗,可以發(fā)現(xiàn)剛剛創(chuàng)建的Job
NAME COMPLETIONS DURATION AGE batch-job 0/1 5s 5s
-
kubectl get pods
: 查看 pod 姓赤,可以發(fā)現(xiàn)Job
創(chuàng)建的 pod 正在運(yùn)行NAME READY STATUS RESTARTS AGE batch-job-d59js 1/1 Running 0 10s
-
kubectl get pods
: 等兩分鐘后再查看 pod ,可以發(fā)現(xiàn)Job
創(chuàng)建的 pod 狀態(tài)已經(jīng)變?yōu)?Completed
仲吏,即任務(wù)已經(jīng)完成不铆。 pod 未被刪除,所以我們可以查看 pod 的日志NAME READY STATUS RESTARTS AGE batch-job-d59js 0/1 Completed 0 2m56s
-
kubectl logs pod batch-job-d59js
: 查看 pod 的日志Sun Jun 7 22:36:04 UTC 2020 Batch job starting Sun Jun 7 22:38:04 UTC 2020 Finished succesfully
-
kubectl get jobs
: 再次查看 job 裹唆,可以發(fā)現(xiàn)需要運(yùn)行的 1 個 pod 已經(jīng)完成NAME COMPLETIONS DURATION AGE batch-job 1/1 2m45s 6m25s
在 Job
中運(yùn)行多個 pod 實(shí)例 P114
在 Job
配置中設(shè)置 spec.completions
和 spec.parallelism
可以讓 Job
創(chuàng)建多個 pod 實(shí)例誓斥,并允許以并行的方式運(yùn)行它們。 P114
基于 batch-job.yaml
創(chuàng)建一個新的描述文件 multi-completion-parallel-batch-job.yaml
许帐,并添加 spec.completions
和 spec.parallelism
屬性劳坑,指定需要成功運(yùn)行完成 5 個 pod ,最多 2 個 pod 并行運(yùn)行 : P115
...
spec:
# 必須確保 5 個 pod 運(yùn)行完成
completions: 5
# 最多 2 個 pod 可以并行運(yùn)行
parallelism: 2
...
kubectl create -f multi-completion-parallel-batch-job.yaml
: 根據(jù)描述文件創(chuàng)建指定的Job
-
kubectl get pods
: 查看運(yùn)行的 pod 成畦,可以發(fā)現(xiàn)共有兩個 pod 正在運(yùn)行距芬。只要一個 pod 運(yùn)行完成,Job
將運(yùn)行下一個 pod 循帐,直至 5 個 pod 都成功完成NAME READY STATUS RESTARTS AGE multi-completion-parallel-batch-job-fpwv5 1/1 Running 0 37s multi-completion-parallel-batch-job-m4cqw 1/1 Running 0 37s
限制 Job
pod 完成任務(wù)的時間 P116
-
Pod.spec.activeDeadlineSeconds
: 可以指定一個 pod 最長存活時間框仔,超時則終止 pod 并標(biāo)記Job
失敗,可以用來限制 pod 完成任務(wù)的時間 -
Job.spec.backoffLimit
: 可以配置一個Job
在被標(biāo)記為失敗前最多嘗試的次數(shù)拄养,默認(rèn)為 6 次
安排 Job
定期運(yùn)行或在將來運(yùn)行一次 P116
創(chuàng)建一個 CronJob
P116
為了每 15 分鐘運(yùn)行一次前面的任務(wù)离斩,我們需要創(chuàng)建以下 cronjob.yaml
描述文件:
# 遵循 batch/v1beta1 版本的 Kubernetes API
apiVersion: batch/v1beta1
# 資源類型為 CronJob
kind: CronJob
metadata:
# Job 的名稱
name: batch-job-every-fifteen-minutes
spec:
# Cron 表達(dá)式表明當(dāng)前任務(wù)在每天每小時的 0, 15, 30, 45 分運(yùn)行
schedule: "0,15,30,45 * * * *"
# 指定最遲必須在預(yù)定時間后 15 秒內(nèi)開始運(yùn)行,否則就標(biāo)記為一次失敗的 `Job`
startingDeadlineSeconds: 15
# 創(chuàng)建 Job 使用的模版(可以發(fā)現(xiàn)和 batch-job.yaml 的 spec 部分基本一致)
jobTemplate:
spec:
# 啟動 pod 使用的模版
template:
metadata:
# 指定標(biāo)簽為 app=periodic-batch-job
labels:
app: periodic-batch-job
spec:
# Job 不能使用 Always 為默認(rèn)的重啟策略
restartPolicy: OnFailure
containers:
# 容器的名稱
- name: main
# 創(chuàng)建容器所使用的鏡像
image: idealism/batch-job
kubectl get cronjobs
: 可以查看所有的 CronJob
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
batch-job-every-fifteen-minutes 0,15,30,45 * * * * False 0 <none> 8s
CronJob
總是為計(jì)劃中配置的每個執(zhí)行創(chuàng)建一個 Job
瘪匿,但可能會有以下兩種問題:
- 同時創(chuàng)建兩個
Job
:保證任務(wù)是冪等的 - 沒有創(chuàng)建
Job
:保證下一個任務(wù)能運(yùn)行完成錯過的任何工作