保持 pod 健康 P84
只要 pod 調度到某個節點,該節點上的 Kubelet 就會運行 pod 的容器,從此只要該 pod 存在,就會保持運行。如果容器的主進程奔潰, Kubelet 就會自動重啟容器;如果應用程序奔潰, Kubelet 就會自動重啟應用程序。 P84
應用程序也可能因為無限循環或死鎖等情況而停止響應。為確保應用在這種情況下可以重新啟動,必須從外部檢查應用程序的運行狀況,而不是依賴於應用的內部檢測。 P84
介紹存活探測器 P84
Kubernetes 可以通過存活探測器 (liveness probe) 檢查容器是否還在運行。可以為 pod 中的每個容器單獨指定存活探測器。 Kubernetes 將定期執行探測器,如果探測失敗,就會自動重啟容器。 P84
注意:Kubernetes 還支持就緒探測器 (readiness probe) ,兩者適用於兩種不同的場景。 P84
Kubernetes 有三種探測容器的機制: P84
HTTP GET
探測器:對容器的 IP 地址(指定的端口和路徑)執行HTTP GET
請求。如果探測器收到響應,並且響應狀態碼不代表錯誤(狀態碼為 2xx 或 3xx ),則認為探測成功。如果服務器返回錯誤響應狀態碼或者沒有響應,那么探測就被認為是失敗的,容器將被重啟。TCP Socket
探測器:嘗試與容器指定端口建立 TCP 連接。如果連接成功建立,則探測成功。否則,容器將被重啟。Exec
探測器:在容器內執行任意命令,並檢查命令的退出狀態碼。如果狀態碼是 0 ,則探測成功。所有其他狀態碼都被認為失敗,容器將被重啟。
創建基於 HTTP 的存活探測器 P85
為了讓 HTTP GET
探測器探測失敗,我們需要修改 kubia 源碼,使得其從第五次訪問之后開始一直返回 500 狀態碼 (Internal Server Error) 。 P85
然后我們可以通過以下描述文件 kubia-liveness-probe.yaml
創建一個包含 HTTP GET
存活探測器的 pod 。 P85
# 遵循 v1 版本的 Kubernetes API
apiVersion: v1
# 資源類型為 Pod
kind: Pod
metadata:
# pod 的名稱
name: kubia-liveness
spec:
containers:
# 創建容器所使用的鏡像
- image: idealism/kubia-unhealthy
# 容器的名稱
name: kubia
ports:
# 應用監聽的端口
- containerPort: 8080
protocol: TCP
# 開啟一個存活探測器
livenessProbe:
# 存活探測器的類型為 HTTP GET
httpGet:
# 探測器連接的網絡端口
port: 8080
# 探測器請求的路徑
path: /
使用存活探測器 P86
使用 kubectl create -f kubia-liveness-probe.yaml
創建完 pod 后,等待一段時間后,容器將會重啟。可以通過 kubectl get pod kubia-liveness
看到容器會重啟,並且無限循環下去: 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 詳情。可以發現在 Containers 和 Events 里面有終止的相關信息。 P86
...
Containers:
kubia:
...
State: Running # 容器目前正常運行
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 # 發現容器不健康
Normal Killing 48s (x2 over 2m38s) kubelet, minikube-m02 Container kubia failed liveness probe, will be restarted # 終止該容器
...
錯誤碼 137 是兩個數字的總和: 128 + x , x 是終止進程的信號編號。 P86
- x=9 表示是
SIGKILL
的信號編號,意味着這個進程被強行終止,這個信號不能被捕獲或忽略,並且在接收過程中不能執行任何清理在接收到該信號 - x=15 表示是
SIGTERM
的信號編號,意味着這個進程被終止,先進行詢問進程終止,讓其清理文件和關閉,可以被捕獲和解釋或忽略
底部列出的事件顯示了 Kubernetes 發現容器不健康,所以終止並重新創建。 P86
注意:當容器被強行終止時,會創建一個全新的容器,而不是重啟原來的容器。 P86
配置存活探測器的附加屬性 P87
可以使用 kubectl explain pod.spec.containers.livenessProbe
查看存活探測器能使用的自定義附加參數。
基於 kubia-liveness-probe.yaml
創建一個新的描述文件 kubia-liveness-probe-initial-delay.yaml
,並添加 pod.spec.containers.livenessProbe.initialDelaySeconds
屬性,值為 15 ,表示在第一次探測器等待 15 秒。
...
spec:
containers:
# 創建容器所使用的鏡像
- image: idealism/kubia-unhealthy
...
# 開啟一個存活探測器
livenessProbe:
...
# 第一次探測前等待 15 秒
initialDelaySeconds: 15
這樣可以在應用程序准備好之后再進行探測,以免應用程序啟動時間過長導致一直探測失敗而無限重啟。
創建有效的存活探測器 P88
- 存活探測器應該檢查什么:簡易的存活探測器可以僅檢查服務器是否響應,但為了更好地進行存活檢查,需要將探測器配置為請求特定的 URL 路徑(如
/health
),並讓應用從內部對內部運行的所有重要組件執行狀態檢查,以確保它們都沒有終止或停止響應。P88
- 確保
/health
不需要認證,否則探測會一直失敗,導致容器無限重啟 - 檢查應用的內部,檢查結果不能受任何外部因素的影響。例如數據庫連不上時,存活探測器不應該返回失敗,如果問題在數據庫,那么重啟容器不會解決問題。
- 確保
- 保持探測器輕量
P89
- 不應消耗太多計算資源
- 運行不應花太長時間。默認情況下,探測器執行的頻率相對較高,必須在一秒之內執行完畢
- 無須在探測器中實現重試:探測器的失敗閾值是可配置的,並且通常在容器被終止之前探測器必須失敗多次
P89
- 存活探測器小結:存活探測由 pod 上的 Kubelet 執行, Kubernetes 控制面板不會參與。因此節點奔潰時,控制面板會為所有隨節點停止運行的 pod 創建替代者,但不會為直接創建的 pod 創建替代者,因為這些 pod 只被節點上的 Kubelet 管理。為了避免這種情況發生,我們應該使用控制器或類似機制管理 pod 。
P89
了解 Deployment
P89
注:本節中提到的 pod 受 Deployment
管理等說法為簡化說法,實際上 pod 由受 Deployment
管理創建的 ReplicaSet
進行管理創建。
Deployment
是一種 Kubernetes 資源,可確保它的 pod 始終保持運行狀態。如果 pod 因為任何原因消失(例如節點從集群中消失或由於該 pod 已從節點中逐出),則 Deployment
會注意到缺少了 pod 並創建替代者。 P89
上圖的節點 1 有兩個節點, Pod A 是被直接創建的,而 Pod B 由 Deployment
管理。節點異常退出后, Deployment
會創建一個新的 Pod B2 來替換減少的 Pod B ,而 Pod A 由於沒有東西負責重建而完全丟失。 P89
Deployment
的操作 P90
Deployment
會持續監控正在運行的 pod 列表,並保證匹配標簽選擇器(03. pod: 運行於 Kubernetes 中的容器 中介紹過標簽選擇器及使用方式)的 pod 數目與期望相符。 P90
介紹控制器的協調流程 P91
Deployment
的工作是確保 pod 數量始終與其標簽選擇器匹配。 P91
了解 Deployment 的三部分 P91
- 標簽選擇器 (label selector) :用於確定
Deployment
作用域中有哪些 pod - 副本個數 (replica count) :指定應運行的 pod 數量
- pod 模版 (pod template) :用於創建新的 pod 副本
Deployment
的副本個數、標簽選擇器和 pod 模版都可以隨時修改,但只有副本數目但變更會影響現有的 pod 。 P92
更改控制器的標簽選擇器或 pod 模版的效果 P92
更改標簽選擇器和 pod 模版對現有的 pod 沒有影響。更改標簽選擇器會使現有的 pod 脫離 Deployment
的范圍,因此控制器會停止關注它們。更改模版僅影響由此 Deployment
創建的新 pod 。 P92
使用 Deployment
的好處 P92
- 確保 pod 持續運行:在現有 pod 丟失時啟動一個新 pod
- 集群節點發生故障時,為故障節點上運行的受
Deployment
管理的所有 pod 創建替代副本 - 輕松實現 pod 水平伸縮——手動和自動都可以
注意: pod 實例永遠不會重新安置到另一個節點。 Deployment
會創建一個全新的 pod 實例,它與正在替換的實例無關。 P92
創建一個 Deployment
P92
我們可以通過以下描述文件 kubia-deployment.yaml
創建一個 Deployment
,它確保符合標簽選擇器 app=kubia
的 pod 實例始終是三個。
# 遵循 v1 版本的 Kubernetes API
apiVersion: apps/v1
# 資源類型為 Deployment
kind: Deployment
metadata:
# Deployment 的名稱
name: kubia
spec:
# 指定與標簽選擇器匹配的 pod 數目為 3
replicas: 3
# 指定 Deployment 操作對象
selector:
# 需要匹配以下指定的標簽
matchLabels:
app: kubia
# 啟動 pod 使用的模版(可以發現模版內容與 kubia-manual.yaml 對應部分一致)
template:
metadata:
# 指定標簽為 app=kubia
labels:
app: kubia
spec:
containers:
# 容器的名稱
- name: kubia
# 創建容器所使用的鏡像
image: idealism/kubia
# 應用監聽的端口
ports:
- containerPort: 8080
protocol: TCP
模版中的 pod 標簽必須和 Deployment
的標簽選擇器匹配, API 服務器會校驗 Deployment
的定義,不會接受錯誤配置。 P93
若不指定選擇器,它會自動根據 pod 模版中的標簽自動配置,這樣可以讓描述文件更簡潔。 P93
使用 Deployment
P94
kubectl create -f kubia-deployment.yaml
會創建一個名為 kubia 的 Deployment
,它會根據 pod 模版啟動三個新 pod 。 P94
kubectl get pods
可以查看當前創建的所有 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 的響應 P94
kubectl delete pod kubia-9495d9bf5-5dwj7
會刪除一個 pod ,然后再次查看當前所有 pod ,可以發現會有 4 個 pod ,因為刪除的 pod 正在終止,並且正在創建一個新的 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
控制器如何創建新的 pod P95
控制器通過創建一個新的替代 pod 來響應 pod 的刪除操作。但它並沒有對刪除本身作出反應,而是針對由此產生對狀態—— pod 數量不足作出反應。 P95
應對節點故障 P96
接下來我們將關閉一個節點的網絡接口來模擬節點故障。 P96
minikube ssh --node='m02'
: 進入節點內部sudo ifconfig eth0 down
: 關閉該節點的網絡接口kubectl get nodes
: 發現節點minikube-m02
的狀態為未就緒 (NotReady
)kubectl get pods
: 可能仍然會看到與之前相同的三個 pod ,因為 Kubernetes 在重新調度 pod 之前會等待一段時間(如果節點因臨時網絡故障或 Kubelet 重啟而無法訪問)。如果節點在幾分鍾內無法訪問,Deployment
會立即啟動一個新的 pod 。
將 pod 移入/移出 Deployment
的作用域 P97
由 Deployment
創建的 pod 並不是綁定到 Deployment
。在任何時刻, Deployment
管理與標簽選擇器匹配的 pod 。通過更改 pod 的標簽,可以將它從 Deployment
的作用域中添加或刪除。 P97
盡管一個 pod 沒有綁定到一個 Deployment
擁有的 ReplicaSet
,但該 pod 在 metadata.ownerReferences
中存儲它屬於哪一個 ReplicaSet
。 P98
給 Deployment
管理的 pod 加標簽 P98
kubectl label pod kubia-9495d9bf5-5mmhb type=special
: 給 pod 添加其他標簽不會影響 Deployment
的管理范圍,它只關心該 pod 是否具有標簽選擇器中引用的所有標簽。 P98
更改已托管的 pod 的標簽 P98
kubectl label pod kubia-9495d9bf5-5mmhb app=foo --overwrite
: 更改其中一個 pod 的標簽將使其不再與 Deployment
的標簽選擇器相匹配,並不再由 Deployment
管理,只剩下兩個匹配的 pod 。因此, Deployment
會啟動一個新的 pod ,將數目恢復為三。 P98
更改 Deployment
的標簽選擇器 P100
更改 Deployment
的標簽選擇器會讓所有的 pod 脫離 Deployment
的管理,導致它創建三個新的 pod 。你永遠不會修改控制器的標簽選擇器,但會時不時地更改它的 pod 模版。 P100
修改 pod 模版 P100
Deployment
的 pod 模版可以隨時修改,可以使用 kubectl edit deployment kubia
編輯 Deployment
。更改后會重新創建一個新的 ReplocaSet
,並使原有的 ReplocaSet
的副本數變為 0 。因此,使用 kubectl get pods
將發現有 6 個 pod ,pod 的前綴是對應的 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
實例。這樣效果和直接修改 Deployment
類似,也會創建一個新的 ReplicaSet
,並使原有的 ReplocaSet
的副本數變為 0 。這樣修改不會將新的 pod 模版同步回原有的 Deployment
,但刪除 Deployment
時仍然會刪除所有相關的 ReplocaSet
及其管理的 pod 。
水平縮放 pod P101
kubectl scale deployment kubia --replicas=10
: 可以修改 Deployment
需要保持的 pod 實例的數量(02. 開始使用 Kubernetes 和 Docker中介紹過使用該命令進行伸縮)。 P101
也可以通過 kubectl edit deployment kubia
修改 spec.replicas
的數量,從而更改需要保持的 pod 實例的數量。 P102
刪除一個 Deployment
當通過 kubectl delete deployment kubia
刪除 Deployment
時,對應的 ReplicaSet
和 pod 都會被刪除。
而通過 kubectl delete replicaset kubia-bc974964b
刪除 ReplicaSet
時,對應的 pod 會被刪除,但由於 Deployment
會重新創建一個 Replicaset
,所以又會自動創建對應數量的 pod 。
當通過 kubectl delete deployment kubia --cascade=false
刪除 Deployment
時,會保留對應的 ReplicaSet
和 pod ,這樣ReplicaSet
不再受管理,但是 pod 仍然受 ReplicaSet
管理。當重新創建符合要求的 Deployment
時, ReplicaSet
又會受到管理。
同樣地,通過 kubectl delete replicaset kubia-bc974964b --cascade=false
刪除 ReplicaSet
時,也會保留對應的 pod 。這樣 pod 不再受管理。當創建符合要求的 ReplicaSet
時,這些 pod 又會受到管理。
使用 ReplicaSet
P104
注:書中原本上一節講得是 ReplicationController
,但我直接使用 Deployment
進行實踐,並依照現在的結果進行了修改。目前推薦使用 Deployment
,並且 ReplicaSet
是受 Deployment
管理的,所以不再詳細實踐本節內容。
使用更富有表達力的標簽選擇器 P106
基於 kubia-deployment.yaml
創建一個新的描述文件 kubia-deployment-matchexpressions.yaml
,並將 spec.selector.matchLabels
屬性替換為 spec.selector.matchExpressions
: P107
...
spec:
...
# 指定 Deployment 操作對象
selector:
# 需要匹配滿足以下要求的標簽
matchExpressions:
# 標簽名為 app 的值在 ["kubia"] 中
- app: app
operator: In
values:
- kubia
...
matchExpressions
運行給選擇器添加額外的表達式。每個表達式都必須包含一個 key 、一個 operator ,並且可能還有一個 values 的列表(取決於 operator )。共有四個有效的運算符: P107
In
: 標簽的值必須與其中一個指定的 values 匹配NotIn
: 標簽的值與任何指定的 values 都不匹配Exists
: pod 必須包含一個指定名稱的標簽(不關心值)。使用此運算符時,不應指定 values 字段DoesNotExist
: pod 不得包含指定名稱的標簽。使用此運算符時,不應指定 values 字段
如果指定了多個表達式,則所有這些表達式都必須為 true 才能使選擇器與 pod 匹配。如果同時指定 matchLabels
和 matchExpressions
,則所有標簽都必須匹配,且所有表達式都必須為 true 才能使選擇器與 pod 匹配。 P107
使用 DaemonSet
在每個節點上運行一個 pod P107
DaemonSet
可以讓 pod 在集群中的每個節點上運行,並且每個節點正好有一個運行的 pod 實例。 P107
使用 DaemonSet
在每個節點上運行一個 pod P108
DaemonSet
沒有副本數的概念,它確保創建足夠的 pod ,並在每一個節點上部署一個 pod 。如果節點下線, DaemonSet
不會重新創建 pod ;但新節點添加到集群中,它會立刻部署一個新的 pod 實例到該節點。 P108
使用 DaemonSet
只在特定的節點上運行 pod P109
DaemonSet
將 pod 部署到集群的所有節點上,除非通過 pod 模版中的 spec.nodeSelector
屬性指定這些 pod 只在部分節點上運行。 P109
注意:節點可以被設置為不可調度,防止 pod 被部署到節點上。但 DaemonSet
會將 pod 部署到這些節點上,因為無法調度但屬性只會被調度器使用,而 DaemonSet
的目的是運行系統服務,即使在不可調度的節點上,系統服務通常也需要運行。 P109
用一個例子來解釋 DaemonSet
P109
假設有一個名為 ssd-monitor
的守護進程,它需要在包含 SSD 的所有節點上運行。包含 SSD 的節點已被添加了 disk=ssd
標簽,所以我們需要創建一個 DaemonSet
,它只在擁有上述標簽的節點上運行守護進程。 P109
創建一個 DaemonSet
描述文件 P110
為了模擬 ssd-monitor
的監控程序,我們將使用以下 Dockerfile
創建一個每 5 秒中打印 SSD OK
的鏡像。
FROM busybox
ENTRYPOINT while true; do echo 'SSD OK'; sleep 5; done
為了將 ssd-monitor
部署到符合要求的每個節點上,我們還需要使用以下 ssd-monitor-daemonset.yaml
描述文件進行部署。
# 遵循 apps/v1 版本的 Kubernetes API
apiVersion: apps/v1
# 資源類型為 DaemonSet
kind: DaemonSet
metadata:
# DaemonSet 的名稱
name: ssd-monitor
spec:
# 指定 DaemonSet 操作對象
selector:
# 需要匹配以下指定的標簽
matchLabels:
app: ssd-monitor
# 啟動 pod 使用的模版
template:
metadata:
# 指定標簽為 app=ssd-monitor
labels:
app: ssd-monitor
spec:
# 指定選擇具有 disk=ssd 標簽的節點部署
nodeSelector:
disk: ssd
containers:
# 容器的名稱
- name: main
# 創建容器所使用的鏡像
image: idealism/ssd-monitor
實踐 P110
kubectl create -f ssd-monitor-daemonset.yaml
: 按照指定的描述文件創建一個DaemonSet
kubectl get daemonsets
: 可以發現所有的值都是 0 ,因為目前還沒有節點擁有disk=ssd
標簽kubectl get pods
: 可以發現目前還沒有 podkubectl label node minikube-m03 disk=ssd
: 給節點minikube-m03
打上標簽disk=ssd
kubectl get pods
: 可以發現剛剛啟動了一個 podNAME READY STATUS RESTARTS AGE ssd-monitor-bbqbp 0/1 ContainerCreating 0 2s
kubectl label node minikube-m03 disk=hdd --overwrite
: 將節點minikube-m03
的標簽disk=ssd
修改為disk=hdd
kubectl get pods
: 可以發現剛剛啟動的 pod 正在終止NAME READY STATUS RESTARTS AGE ssd-monitor-bbqbp 1/1 Terminating 0 2m37s
運行執行單個任務的 pod P112
介紹 Job
資源 P112
Kubernetes 通過 Job
資源支持運行一種 pod ,該 pod 子啊內部進程成功結束時,不重啟容器。一旦任務完成, pod 就被認為處於完成狀態。 P112
在節點發生故障時,該節點上由 Job
管理的 pod 將被重新安排到其他節點。如果進程本身異常退出(進程返回錯誤退出碼時),可以將 Job
配置為重新啟動容器。 P112
定義 Job
資源 P113
為了模擬耗時的任務,我們將使用以下 Dockerfile
創建一個調用 sleep 120
命令的鏡像。
FROM busybox
ENTRYPOINT echo "$(date) Batch job starting"; sleep 120; echo "$(date) Finished succesfully"
為了管理部署 batch-job
,我們還需要使用以下 batch-job.yaml
描述文件進行部署。
# 遵循 batch/v1 版本的 Kubernetes API
apiVersion: batch/v1
# 資源類型為 Job
kind: Job
metadata:
# Job 的名稱
name: batch-job
spec:
# 啟動 pod 使用的模版
template:
metadata:
# 指定標簽為 app=batch-job
labels:
app: batch-job
spec:
# Job 不能使用 Always 為默認的重啟策略
restartPolicy: OnFailure
containers:
# 容器的名稱
- name: main
# 創建容器所使用的鏡像
image: idealism/batch-job
設置 Job
的重啟策略為 OnFailure
或 Never
可以防止容器在完成任務時重新啟動。 P114
Job
運行一個 pod P114
kubectl create -f batch-job.yaml
: 根據描述文件創建指定的Job
kubectl get jobs
: 查看 job ,可以發現剛剛創建的Job
NAME COMPLETIONS DURATION AGE batch-job 0/1 5s 5s
kubectl get pods
: 查看 pod ,可以發現Job
創建的 pod 正在運行NAME READY STATUS RESTARTS AGE batch-job-d59js 1/1 Running 0 10s
kubectl get pods
: 等兩分鍾后再查看 pod ,可以發現Job
創建的 pod 狀態已經變為Completed
,即任務已經完成。 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 ,可以發現需要運行的 1 個 pod 已經完成NAME COMPLETIONS DURATION AGE batch-job 1/1 2m45s 6m25s
在 Job
中運行多個 pod 實例 P114
在 Job
配置中設置 spec.completions
和 spec.parallelism
可以讓 Job
創建多個 pod 實例,並允許以並行的方式運行它們。 P114
基於 batch-job.yaml
創建一個新的描述文件 multi-completion-parallel-batch-job.yaml
,並添加 spec.completions
和 spec.parallelism
屬性,指定需要成功運行完成 5 個 pod ,最多 2 個 pod 並行運行 : P115
...
spec:
# 必須確保 5 個 pod 運行完成
completions: 5
# 最多 2 個 pod 可以並行運行
parallelism: 2
...
-
kubectl create -f multi-completion-parallel-batch-job.yaml
: 根據描述文件創建指定的Job
-
kubectl get pods
: 查看運行的 pod ,可以發現共有兩個 pod 正在運行。只要一個 pod 運行完成,Job
將運行下一個 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 完成任務的時間 P116
Pod.spec.activeDeadlineSeconds
: 可以指定一個 pod 最長存活時間,超時則終止 pod 並標記Job
失敗,可以用來限制 pod 完成任務的時間Job.spec.backoffLimit
: 可以配置一個Job
在被標記為失敗前最多嘗試的次數,默認為 6 次
安排 Job
定期運行或在將來運行一次 P116
創建一個 CronJob
P116
為了每 15 分鍾運行一次前面的任務,我們需要創建以下 cronjob.yaml
描述文件:
# 遵循 batch/v1beta1 版本的 Kubernetes API
apiVersion: batch/v1beta1
# 資源類型為 CronJob
kind: CronJob
metadata:
# Job 的名稱
name: batch-job-every-fifteen-minutes
spec:
# Cron 表達式表明當前任務在每天每小時的 0, 15, 30, 45 分運行
schedule: "0,15,30,45 * * * *"
# 指定最遲必須在預定時間后 15 秒內開始運行,否則就標記為一次失敗的 `Job`
startingDeadlineSeconds: 15
# 創建 Job 使用的模版(可以發現和 batch-job.yaml 的 spec 部分基本一致)
jobTemplate:
spec:
# 啟動 pod 使用的模版
template:
metadata:
# 指定標簽為 app=periodic-batch-job
labels:
app: periodic-batch-job
spec:
# Job 不能使用 Always 為默認的重啟策略
restartPolicy: OnFailure
containers:
# 容器的名稱
- name: main
# 創建容器所使用的鏡像
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
總是為計划中配置的每個執行創建一個 Job
,但可能會有以下兩種問題:
- 同時創建兩個
Job
:保證任務是冪等的 - 沒有創建
Job
:保證下一個任務能運行完成錯過的任何工作
本文首發於公眾號:滿賦諸機(點擊查看原文) 開源在 GitHub :reading-notes/kubernetes-in-action