正如您在前幾章中了解到的,透過 Deployment、StatefulSet 或 DaemonSet 所建立的 Pod 會持續運行。 當運行在 Pod 的容器裡其中之一程序終止時,Kubelet 會重新啟動該容器。 Pod 永遠不會自行停止,只有當您刪除Pod物件時才會停止。雖然這非常適合運行 Web server、資料庫、系統服務和類似的工作負載,但它不適合只需要執行單個任務的有限工作負載。

有限的工作負載不會持續運行,而是讓任務運行完成。在k8s中,您可以使用Job資源運行此類工作負載。 但是,Job 始終會立刻運行其Pod,因此您不能使用它來安排任務。為此,您需要將Job包裝在CronJob物件中。 CronJob物件允許您安排任務在將來的特定時間或定期執行。

在開始之前,建立kiada命名空間,切換到Chapter17/目錄,並利用以下指令apply SETUP/目錄中的所有yaml:

$ kubectl create ns kiada
$ kubectl config set-context --current --namespace kiada
$ kubectl apply -f SETUP -R

如果您發現每個quiz Pod中的其中一個容器未能就緒,請不要驚慌。這是意料之中的,因為在這些 Pod 中運行的MongoDB資料庫尚未初始化。您將建立一個Job資源來執行此操作。

17.1 使用Job資源運行任務

在透過Job資源建立第一個 Pod 之前,讓我們思考一下kiada命名空間中的Pod 。它們都應該持續運行。當其中一個 pod 中的容器終止時,它會自動重新啟動。 當 Pod 被刪除時,它會由建立原始Pod的controller重新建立。 例如,如果您刪除其中一個kiada Pod,Deployment controller會很快重新建立它,因為kiada Deployment中的replicas字段指定三個Pod應該始終存在。

現在考慮用一個Pod來初始化MongoDB資料庫。您不希望這個Pod持續運行;希望這個Pod執行一項任務然後退出。 儘管您希望Pod的容器在失敗時重新啟動,但您不希望它們在成功結束後重新啟動。您也不希望在刪除完成結束的Pod後,重新建立新的Pod。

還記得在第15章中建立了這樣的一個Pod → quiz-data-importer Pod。它設定了OnFailure的重啟策略,以確保容器只有在失敗時才會重啟。 當容器成功終止時,Pod 結束,您可以刪除它。 由於您是直接建立此Pod,並不是透過Deployment、StatefulSet、DaemonSet建立的,因此不會重新創建它。那麼,這種方法有什麼問題,為什麼要改為利用Job建立Pod?

要回答這個問題,請考慮如果有人不小心過早刪除了Pod或者運行Pod的節點發生故障時會發生什麼情況。 在這些情況下,k8s不會自動重新建立Pod。你必須自己做。而且您自己必須從建立到完成觀察此Pod。 對於在幾秒鐘內完成任務的Pod來說,這可能沒問題,但您可能不希望一直盯著Pod看幾個小時。所以,最好建立一個Job物件,讓k8s完成剩下的工作。

Job資源類似於Deployment,因為它會建立一個或多個Pod,但Job不會確保這些Pod無限期運行,它只會確保其中一定數量的Pod成功完成。

如下圖所示,最簡單的Job執行單個Pod直到完成,而更複雜的Job會運行多個 Pod,依序或同時併發。 當Pod中的所有容器都成功終止時,Pod被認為已完成。當所有Pod都完成時,Job本身也算完成了。

Untitled

如您所料,Job資源定義了Pod template和必須成功完成的Pod數量。它還定義了Pod可以並行運行的數量。

<aside> 📝 不同於包含Pod template的Deployments和其他資源,您無法在建立Job物件後修改物件中的template。

</aside>

定義Job資源

在本節中,您將使用第15章中的quiz-data-importer Pod並將它轉換 Job。此Pod將數據匯入Quiz MongoDB資料庫。 您可能還記得,在運行此Pod之前,您必須透過在其中一個quiz Pod中發出指令來初始化MongoDB副本集。 您也可以在此Job中使用init容器執行此操作。Job和Job建立的Pod如下圖。

Untitled

以下為Job清單,job.quiz-init.yaml。

<aside> 📝 此manifest還包含一個ConfigMap,其中存儲了測驗問題,但此ConfigMap未顯示在清單中。

</aside>