返回文章列表

Kubernetes Job 與 CronJob 資源管理

本文探討 Kubernetes 中的 Job 和 CronJob 資源,解析其 YAML 設定檔的關鍵欄位,並提供實際操作範例。涵蓋 Job 的生命週期管理、CronJob 的排程設定、以及多容器 Pod 的設計模式與應用場景。

容器技術 DevOps

Kubernetes 提供 Job 和 CronJob 兩種資源,分別用於執行一次性任務和定時任務。Job 資源確保任務執行完成,並可設定重試次數和完成後的清理策略。CronJob 則根據 cron 語法,定期觸發 Job 執行,適用於定時備份、日誌清理等場景。設定 CronJob 時,需注意排程語法、啟動期限和歷史記錄限制等引數,以確保任務穩定執行。此外,多容器 Pod 的設計模式,例如 Sidecar 和 Ambassador,能提升應用程式的彈性和可維護性,例如日誌收集和代理服務等場景,多容器 Pod 能簡化佈署和管理。

在Kubernetes中執行容器:探討Job與CronJob資源

在前面的章節中,我們探討了Kubernetes中的Pod資源。本章節將繼續探討Kubernetes中的另一個重要資源——Job與CronJob。這些資源對於執行批處理任務和定時任務至關重要。

管理Job資源

在Kubernetes中,Job資源用於執行一次性任務。當一個Job完成後,它所建立的Pod將根據組態被保留或刪除。為了演示如何使用Job資源,我們首先建立一個名為hello-world-job-6.yaml的檔案,並在其中定義一個簡單的Job。

hello-world-job-6.yaml

apiVersion: batch/v1
kind: Job
metadata:
  name: hello-world-job-6
spec:
  backoffLimit: 3
  ttlSecondsAfterFinished: 30
  template:
    metadata:
      name: hello-world-job-6
    spec:
      restartPolicy: OnFailure
      containers:
      - name: hello-world-container
        image: busybox
        command: ["/bin/sh", "-c"]
        args: ["echo 'Hello world'"]

在這個例子中,ttlSecondsAfterFinished欄位設定為30,意味著Job完成後30秒將被自動刪除。這個特性可以幫助我們自動清理完成的Job,避免叢集中積累過多的無用資源。

刪除Job

要刪除一個Job,可以使用kubectl delete jobs命令。例如:

$ kubectl delete jobs hello-world-job

如果希望在刪除Job的同時保留它建立的Pod,可以新增--cascade=false引數:

$ kubectl delete jobs hello-world-job --cascade=false

瞭解CronJob

CronJob是Kubernetes中的另一個重要資源,用於定時執行任務。它根據Unix的cron功能,但有一些不同。在Kubernetes中,CronJob用於建立Job資源,而這些Job資源又會建立Pod來執行具體的任務。

為什麼使用CronJob?

CronJob可以用於各種場景,例如:

  • 定期備份資料函式庫
  • 清理快取資料
  • 傳送佇列中的郵件
  • 執行定期的維護操作

這些場景與Unix系統中使用cron的場景相似,但Kubernetes的CronJob提供了額外的好處,例如可以使用已有的Kubernetes叢集和容器映象。

建立第一個CronJob

要建立一個CronJob,需要定義一個YAML檔案,例如hello-world-cronjob.yaml

hello-world-cronjob.yaml

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: hello-world-cronjob
spec:
  schedule: "* * * * *"
  jobTemplate:
    spec:
      template:
        metadata:
          name: hello-world-cronjob
        spec:
          restartPolicy: OnFailure
          containers:
          - name: hello-world-container
            image: busybox
            imagePullPolicy: IfNotPresent
            command: ["/bin/sh", "-c"]
            args: ["echo 'Hello world'"]

在這個例子中,schedule欄位定義了CronJob的執行時間表,使用的是cron表示式。jobTemplate欄位則定義了要執行的Job資源。

理解cron表示式

cron表示式由五個部分組成,分別代表分鐘、小時、日期、月份和星期幾。例如:

  • "10 11 * * *" 表示每天11點10分執行任務
  • "10 11 * 12 *" 表示每年12月的每天11點10分執行任務
  • "10 11 * * 1" 表示每週一的11點10分執行任務

可以使用線上工具,如crontab.cronhub.io和crontab.guru,來生成和驗證cron表示式。

第四章:深入理解Pod與排程任務管理

在Kubernetes中,Pod是基本的工作單元,但實際操作中,我們很少直接建立Pod。相反,我們會使用更高階的物件(如控制器)來管理和建立Pod。這種做法提供了更強大的管理和擴充套件功能。

控制器與Pod管理

控制器是Kubernetes中的特殊物件,它們根據自身的邏輯來操作其他Kubernetes資源。Job物件本身就是一種控制器,因為它透過提供平行執行Pod的能力來操控Pod。

使用控制器的好處

在實際應用中,應盡量使用中間物件(如Job或CronJob)來建立和管理Pod,因為它們提供了額外的進階管理功能。

CronJob的執行期限控制

有時,CronJob可能會因為某些原因無法執行。如果Job超過了設定的截止日期,Kubernetes會將其視為失敗。.spec.startingDeadlineSeconds欄位用於設定Job的啟動截止日期(以秒為單位)。一旦錯過了截止日期,CronJob將跳過該次Job執行,但未來的執行仍然會按照排程進行。

管理Job的歷史記錄限制

CronJob完成後,無論成功與否,Kubernetes叢集都會保留一份歷史記錄。你可以透過組態CronJob層級的.spec.successfulJobsHistoryLimit.spec.failedJobsHistoryLimit欄位來決定保留多少成功或失敗的Job記錄。

建立CronJob

建立CronJob非常簡單,只需準備好YAML設定檔,然後使用kubectl apply -f命令即可。

範例:hello-world-cronjob.yaml

apiVersion: batch/v1
kind: CronJob
metadata:
  name: hello-world-cronjob
spec:
  schedule: "*/1 * * * *"
  successfulJobsHistoryLimit: 5
  startingDeadlineSeconds: 30
  jobTemplate:
    spec:
      template:
        metadata:
          name: hello-world-cronjob
        spec:
          restartPolicy: OnFailure
          containers:
          - name: hello-world-container
            image: busybox
            imagePullPolicy: IfNotPresent
            command: ["/bin/sh", "-c"]
            args: ["echo 'Hello world'"]

內容解密:

  • schedule: "*/1 * * * *":每分鐘執行一次CronJob。
  • successfulJobsHistoryLimit: 5:保留最近5次成功的Job記錄。
  • startingDeadlineSeconds: 30:設定Job啟動的截止日期為30秒。
  • restartPolicy: OnFailure:當容器失敗時重啟。
  • image: busybox:使用busybox映像來執行簡單的命令。
  • commandargs:執行/bin/sh -c "echo 'Hello world'"命令。

驗證CronJob運作

建立CronJob後,可以使用kubectl get cronjobskubectl get jobskubectl get pods來檢查其運作狀態。

刪除CronJob

刪除CronJob同樣簡單,使用kubectl delete -f命令即可刪除指定的CronJob資源。

使用多容器 Pod 與設計模式

在 Kubernetes 中執行複雜的應用程式需要將多個容器執行在同一個 Pod 中。Kubernetes 的強大之處在於能夠建立由多個容器組成的 Pod。本章將重點介紹在同一個 Pod 中託管多個容器的不同方面,以及如何讓這些容器彼此通訊。

到目前為止,我們只建立了執行單個容器的 Pod,這些是最簡單的 Pod 形式,用於管理最簡單的應用程式。我們還學習瞭如何使用 kubectl 命令列工具對這些 Pod 執行簡單的建立、讀取、更新和刪除(CRUD)操作。

除了掌握 CRUD 操作的基本知識外,我們還學習瞭如何存取 Kubernetes 叢集中執行的 Pod。雖然單容器 Pod 更為常見,但在某些情況下,在單個 Pod 中使用多個容器是有益的。例如,使用專門的容器來處理日誌收集,或者使用另一個專門的容器來實作服務之間的代理通訊。

在本章中,我們將進一步探討如何管理包含多個容器的 Pod。幸運的是,之前學到的知識同樣適用於多容器 Pod。在原始 Pod 管理方面,無論 Pod 包含多少個容器,更新和刪除 Pod 的操作都是相同的。

除了這些基本操作外,我們還將介紹如何存取多容器 Pod 中的特定容器,以及如何存取其日誌。當一個 Pod 包含多個容器時,您需要使用特定的命令和引數來存取它。

多容器 Pod 的設計模式

我們還將探討一些重要的設計模式,例如 Ambassador、Sidecar 和 Adapter 容器。您需要學習這些架構以有效地管理多容器 Pod。您還將學習如何處理 Kubernetes 中的卷。Docker 也提供了卷,但在 Kubernetes 中,它們用於在同一個 Pod 中啟動的容器之間分享資料,這將是本章的重要內容。

在本章中,我們將涵蓋以下主要主題:

  • 瞭解多容器 Pod 是什麼
  • 在同一個 Pod 中的容器之間分享卷
  • Ambassador 設計模式
  • Sidecar 設計模式
  • Adapter 設計模式
  • Sidecar 與 Kubernetes 原生 Sidecar 的比較

技術需求

本章需要以下先決條件:

  • 一個可用的 kubectl 命令列工具。
  • 一個本地或根據雲的 Kubernetes 叢集來進行實踐。

瞭解多容器 Pod 是什麼

多容器 Pod 是在 Kubernetes 中將緊密耦合的應用程式封裝在一起的一種方式。這允許多個容器分享資源並輕鬆地相互通訊,這對於像 Sidecar 和服務網格這樣的場景來說是理想的。在本文中,我們將透過討論一些具體的多容器 Pod 示例來瞭解用於管理多個容器的 Pod 的核心概念。

需要多容器 Pod 的具體場景

當您的容器需要緊密連結時,您應該將它們分組到一個 Pod 中。更廣泛地說,一個 Pod 必須對應於在您的 Kubernetes 叢集中執行的應用程式或程式。如果您的應用程式需要多個容器才能正常執行,那麼這些容器應該透過單個 Pod 啟動和管理。

當容器應該一起工作時,您應該將它們分組到一個單獨的 Pod 中。請記住,Pod 不能跨越多個計算節點。因此,如果您建立了一個包含多個容器的 Pod,那麼所有這些容器都將在同一個計算節點上建立。

為了了解何時以及如何在多容器 Pod 中使用,讓我們考慮兩個簡單的應用程式示例:

  • 日誌轉發器:在這個示例中,假設您已經佈署了一個像 NGINX 這樣的 Web 伺服器,它將日誌儲存在一個專門的目錄中。您可能希望收集並轉發這些日誌。為此,您可以在與 NGINX 伺服器相同的 Pod 中佈署像 Splunk 轉發器這樣的容器。
apiVersion: v1
kind: Pod
metadata:
  name: nginx-with-log-forwarder
spec:
  containers:
  - name: nginx
    image: nginx:latest
    volumeMounts:
    - name: logs
      mountPath: /var/log/nginx
  - name: log-forwarder
    image: splunk/splunk-forwarder:latest
    volumeMounts:
    - name: logs
      mountPath: /var/log/nginx
  volumes:
  - name: logs
    emptyDir: {}

內容解密:

此 YAML 組態檔案定義了一個名為 nginx-with-log-forwarder 的 Pod,其中包含兩個容器:nginxlog-forwarder。兩個容器都掛載了一個名為 logs 的卷,用於分享日誌資料。

  1. nginx 容器使用 nginx:latest 映象,並將 /var/log/nginx 目錄掛載到 logs 捲上,用於儲存 NGINX 日誌。
  2. log-forwarder 容器使用 splunk/splunk-forwarder:latest 映象,同樣將 /var/log/nginx 目錄掛載到 logs 捲上,用於讀取 NGINX 日誌並將其轉發到指定的目標。
  3. emptyDir: {} 定義了一個臨時卷,該卷在 Pod 被刪除時會被清空,適合用於臨時資料分享。 透過這種方式,兩個容器可以在同一個 Pod 中協同工作,實作日誌收集和轉發的功能。

多容器 Pod 的應用與設計模式

在 Kubernetes 環境中,多容器 Pod 是一種常見的佈署模式,用於將多個緊密耦合的容器組合在一起執行在同一節點上。這種設計模式可以滿足多種應用場景,包括日誌轉發、代理伺服器等。

多容器 Pod 的典型應用場景

  1. 日誌轉發工具:在 Kubernetes 中,通常會使用 Splunk、Fluentd 或 Filebeat 等代理工具來收集容器日誌並將其轉發到集中式的日誌儲存位置,如 Elasticsearch 叢集。這種情況下,日誌轉發容器與應用容器通常會被佈署在同一個 Pod 中,以確保它們執行在同一節點上。

  2. 代理伺服器:例如,將 NGINX 反向代理容器與主應用容器佈署在同一個 Pod 中,可以高效地處理流量路由和安全規則。此外,在服務網格(Service Mesh)架構中,可以使用 Envoy 等專用代理容器來實作負載平衡和服務發現等功能。

使用多容器 Pod 的設計模式

當多個容器之間存在緊密耦合關係時,將它們佈署在同一個 Pod 中是一種合理的選擇。這種設計模式可以確保相關的容器始終執行在同一節點上,並且可以分享本地資源。

建立多容器 Pod

在 Kubernetes 中,建立多容器 Pod 需要使用宣告式語法,即透過 YAML 清單檔案來定義 Pod 及其包含的容器。以下是一個示例 YAML 檔案(multi-container-pod.yaml):

apiVersion: v1
kind: Pod
metadata:
  name: multi-container-pod
spec:
  restartPolicy: Never
  containers:
  - name: nginx-container
    image: nginx:latest
  - name: debian-container
    image: debian
    command: ["/bin/sh"]
    args: ["-c", "while true; do date; echo debian-container; sleep 5; done"]

內容解密:

  1. apiVersionkind:定義了 Kubernetes 物件的版本和型別,這裡建立的是一個 Pod。
  2. metadata.name:指定了 Pod 的名稱為 multi-container-pod
  3. spec.restartPolicy:設定為 Never,表示 Pod 中的容器不會自動重啟。
  4. containers:定義了兩個容器,分別是 nginx-containerdebian-container
    • nginx-container 使用 nginx:latest 映象執行。
    • debian-container 使用 debian 雞像執行,並執行一個無限迴圈命令,每 5 秒輸出日期和字串。

要建立這個 Pod,可以使用以下命令:

$ kubectl apply -f multi-container-pod.yaml
pod/multi-container-pod created

驗證多容器 Pod 的狀態

建立 Pod 後,可以使用 kubectl get pods 命令檢查其狀態:

$ kubectl get pods
NAME                 READY   STATUS    RESTARTS   AGE
multi-container-pod  2/2     Running   0          2m7s

輸出中的 2/2 表示 Pod 中的兩個容器都已成功啟動並執行。

檢視容器日誌

可以使用 kubectl logs 命令檢視特定容器的日誌:

$ kubectl logs multi-container-pod -c debian-container
Mon Jan 8 01:33:23 UTC 2024
debian-container
Mon Jan 8 01:33:28 UTC 2024
debian-container
...<removed for brevity>...

$ kubectl logs multi-container-pod -c nginx-container
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
...<removed for brevity>...
2024/01/08 01:33:20 [notice] 1#1: start worker process 39
2024/01/08 01:33:20 [notice] 1#1: start worker process 40

內容解密:

  • kubectl logs 命令用於取得容器的日誌輸出。
  • -c 引數指定要檢視日誌的容器名稱。

多容器 Pod 的特點

  1. 排程:Pod 中的所有容器會被排程到同一個節點上執行。
  2. 生命週期:Pod 中的容器分享相同的生命週期,終止 Pod 時,所有容器都會被終止。
  3. 高用性:高用性通常透過在多個節點上複製多個 Pod 來實作。

總之,多容器 Pod 提供了一種靈活的佈署模式,用於管理緊密耦合的容器應用。透過合理設計和組態,可以滿足多種複雜的應用場景需求。