在 Kubernetes 環境中,有效管理 Pod 和 Job 是確保應用程式穩定執行和資源最佳化的關鍵。本文將會逐步說明如何使用標籤和註解來組織和管理 Pod,並探討 Job 的生命週期管理,包含如何設定重啟策略、控制平行度、設定完成次數以及自動清理等技巧。這些技術將有助於提升 Kubernetes 叢集的維運效率和資源利用率。

在 Kubernetes 中管理 Pod 的標籤與註解

新增標籤

在本文中,我們將學習如何新增和移除 Pod 的標籤與註解,同時也會學習如何修改已經存在於叢集中的 Pod 的標籤。

首先,讓我們使用之前根據 NGINX 映像的 Pod 為例。我們將使用一個名為 tier 的標籤重新建立它,該標籤的值為 frontend。以下是用於此操作的 kubectl 命令:

$ kubectl run nginx-pod --image nginx --labels "tier=frontend"

正如你所看到的,可以使用 --labels 引數來分配標籤。你也可以透過使用 --labels 引數和逗號分隔的值來新增多個標籤,如下所示:

$ kubectl run nginx-pod --image nginx --labels="app=myapp,env=dev,tier=frontend"

在這裡,nginx Pod 將被建立並具有兩個標籤。

--labels 旗標有一個簡短版本,稱為 -l。你可以使用它來使命令更短且更易讀。標籤也可以附加到 YAML Pod 定義中。下面是相同的 Pod,持有我們之前建立的兩個標籤,但這次是使用宣告式語法建立的:

# labelled_pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  labels:
    environment: prod
    tier: frontend
spec:
  containers:
  - name: nginx-container
    image: nginx:latest

假設該檔案已建立在 ~/labelled_pod.yaml。以下 kubectl 命令將以與之前相同的方式建立 Pod:

$ kubectl apply -f ~/labelled_pod.yaml

這次,執行我們之前使用的命令應該至少傳回一個 Pod——也就是我們剛才建立的:

$ kubectl get pod -l environment=prod
NAME        READY   STATUS    RESTARTS   AGE
nginx-pod   1/1     Running   0          31m

現在,讓我們學習如何列出附加到我們的 Pod 的標籤。

列出附加到 Pod 的標籤

沒有專門的命令用於列出附加到 Pod 的標籤,但是可以使 kubectl get pods 的輸出變得更加詳細。透過使用 --show-labels 引數,命令的輸出將包括附加到 Pod 的標籤:

$ kubectl get pods --show-labels
NAME        READY   STATUS    RESTARTS   AGE   LABELS
nginx-pod   1/1     Running   0          56s   environment=prod,tier=frontend

這個命令不會根據標籤執行任何查詢;相反,它將標籤本身顯示為輸出的一部分。

新增或更新執行中 Pod 的標籤

既然我們已經學會瞭如何建立帶有標籤的 Pod,那麼接下來我們將學習如何新增標籤到執行中的 Pod。你可以使用 kubectl label 命令隨時新增、建立或修改資源的標籤。在這裡,我們將為我們的 nginx Pod 新增另一個名為 stack 且值為 blue 的標籤:

$ kubectl label pod nginx-pod stack=blue
pod/nginx-pod labeled

這個命令只有在 Pod 沒有名為 stack 的標籤時才有效。當命令執行時,它只能新增一個新的標籤,而不能更新它。執行以下命令以檢視變更是否已套用:

$ kubectl get pods nginx-pod --show-labels
NAME        READY   STATUS    RESTARTS   AGE   LABELS
nginx-pod   1/1     Running   0          38m   environment=prod,stack=blue,tier=frontend

要更新現有的標籤,你必須在前面的命令中附加 --overwrite 引數。讓我們更新 stack=blue 標籤,使其變為 stack=green;請注意覆寫引數:

$ kubectl label pod nginx-pod stack=green --overwrite
pod/nginx-pod labeled

這裡,標籤應該被更新。stack 標籤現在應該等於 green。再次執行以下命令以顯示 Pod 及其標籤:

$ kubectl get pods nginx-pod --show-labels
NAME        READY   STATUS    RESTARTS   AGE   LABELS
nginx-pod   1/1     Running   0          41m   environment=prod,stack=green,tier=frontend

刪除執行中 Pod 的標籤

就像我們新增和更新了執行中 Pod 的標籤一樣,我們也可以刪除它們。該命令有點棘手。在這裡,我們將刪除名為 stack 的標籤,可以透過在標籤名稱後面新增減號(`-)來實作:

$ kubectl label pod nginx-pod stack-
pod/nginx-pod unlabeled

在命令末尾新增減號可能有點奇怪,但再次執行 kubectl get pods --show-labels 應該會顯示 stack 標籤現在已經消失:

$ kubectl get pods nginx-pod --show-labels

新增註解

Kubernetes 註解是你可以附加到各種 Kubernetes 物件(如 Pod、Deployments 和 Services)的鍵值對。它們允許你在不改變這些物件核心功能的情況下新增額外資訊。與用於識別和選擇的標籤不同,註解旨在儲存可以用於人類可讀性或外部工具的其他資料。註解可以包括諸如組態資訊或建立者的姓名等詳細資訊。

讓我們學習如何為 Pod 新增註解:

# annotated_pod.yaml
apiVersion: v1
kind: Pod
metadata:
  annotations:
    tier: webserver
  name: nginx-pod
  labels:
    environment: prod
    tier: frontend
spec:
  containers:
  - name: nginx-container
    image: nginx:latest

重點解析:

  1. Annotations 與 Labels 的區別:Annotations 用於儲存額外的資訊,而 Labels 用於物件的識別和選擇。
  2. 使用場景:Annotations 可以包含組態資訊、建立者的姓名等,而 Labels 用於建立 Kubernetes 物件之間的關聯。
  3. 操作方式:可以使用 YAML 定義檔案或 kubectl annotate 命令來新增或更新 Annotations。

重點提示:

  • 使用 Labels 時應謹慎,因為它們會影響 Kubernetes 物件之間的關聯。
  • 新增或更新 Labels 可能會破壞現有的關聯,因此建議在建立 Pod 時就定義好 Labels,以保持 Kubernetes 組態的不變性。
  • 在可能的情況下,摧毀並重新建立資源,而不是更新已經執行的組態。

在Kubernetes中執行容器化任務

使用註解增強Pod管理

在Kubernetes中,除了基本的Pod組態外,還可以透過註解(Annotations)為Pod新增額外的後設資料。例如,為Pod新增tier: webserver註解,以標識該Pod執行的是HTTP伺服器。

containers:
- name: nginx-container
  image: nginx:latest

此處增加了tier: webserver註解,有助於識別該Pod的用途。值得注意的是,註解的鍵名可以使用DNS名稱作為字首,這是Kubernetes元件(如kube-scheduler)標識自身的方式。

要檢視Pod的註解,可以使用以下命令:

$ kubectl describe Pod nginx-pod
$ kubectl get po -o yaml
$ kubectl get pod nginx-pod -o json | jq '.metadata.annotations'

內容解密:

  1. kubectl describe Pod:用於檢視Pod的詳細資訊,包括註解。
  2. kubectl get po -o yaml:以YAML格式輸出Pod的詳細組態。
  3. kubectl get pod nginx-pod -o json | jq '.metadata.annotations':使用jq工具解析JSON輸出,提取.metadata.annotations欄位。

啟動第一個Job

在Kubernetes中,Job是一種用於執行一次性任務的資源物件。它透過建立一個或多個Pod來完成特定的計算任務。

為什麼需要Job?

雖然可以直接建立Pod來執行命令,但Job提供了更進階的管理功能,例如:

  • 多次執行Pod
  • 平行執行多個Pod
  • 在Pod失敗時重試
  • 在指定時間後終止Pod

建立Job

以下是一個簡單的Job示例,使用busybox映象執行echo 'Hello world'命令:

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

內容解密:

  1. apiVersion: batch/v1:指定Job的API版本。
  2. kind: Job:定義資源型別為Job。
  3. restartPolicy: OnFailure:設定失敗重啟策略,若Pod或容器失敗,將會重啟。
  4. containers:定義容器相關組態,包括映象、命令和引數。

建立Job後,可以使用以下命令檢視其狀態:

$ kubectl apply -f hello-world-job.yaml
$ kubectl get jobs

輸出結果將顯示Job的完成狀態和執行時間。

內容解密:

  1. kubectl apply -f hello-world-job.yaml:根據YAML檔案建立Job。
  2. kubectl get jobs:檢視Job的狀態,包括完成數和執行時間。

在 Kubernetes 中執行容器的工作管理

瞭解 Job 物件的 restartPolicy

在 Kubernetes 中,Job 物件用於執行一次性任務,而 restartPolicy 引數則控制著任務失敗時的重啟策略。該引數可設為兩個選項:NeverOnFailure

  • 當設定為 Never 時,即使任務失敗,Kubernetes 也不會重啟 Pod。這在除錯失敗的任務時非常有用,因為它可以防止 Pod 被反覆重建,從而簡化除錯過程。
  • 當設定為 OnFailure 時,如果任務失敗,Kubernetes 將嘗試重啟 Pod。重啟的間隔時間會每次加倍,從 10 秒開始,直到 6 分鐘後放棄。

檢視 Job 日誌

要確認 Job 是否成功執行,可以檢視其日誌:

$ kubectl logs jobs/hello-world-job
Hello world

或者,先取得 Job 建立的 Pod 名稱,然後檢視該 Pod 的日誌:

$ kubectl logs pods/hello-world-job-2qh4d
Hello world

瞭解 Job 的 backoffLimit

預設情況下,Kubernetes Job 會在失敗後 6 分鐘內嘗試重啟 Pod 六次。您可以透過 backoffLimit 選項修改此限制。

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

程式碼解析:

  1. backoffLimit: 3 表示 Job 在失敗後最多重試 3 次。
  2. restartPolicy: OnFailure 表示當容器失敗時重啟。
  3. 使用 busybox 映象執行簡單的 echo 'Hello world' 命令。

使用 completions 重複執行任務

您可以使用 completions 選項指定 Job 需要執行的次數。以下範例將建立 10 個 Pod,依序執行。

# hello-world-job-3.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: hello-world-job-3
spec:
  backoffLimit: 3
  completions: 10
  template:
    metadata:
      name: hello-world-job-3
    spec:
      restartPolicy: OnFailure
      containers:
      - name: hello-world-container
        image: busybox
        command: ["/bin/sh", "-c"]
        args: ["echo 'Hello world'; sleep 3"]

程式碼解析:

  1. completions: 10 表示 Job 需要成功執行 10 次。
  2. args: ["echo 'Hello world'; sleep 3"] 使每個任務在完成前暫停 3 秒,以便觀察 Pod 的建立過程。

平行執行任務

使用 parallelism 選項可以讓 Job 平行執行多個 Pod,從而提高效率。

# hello-world-job-4.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: hello-world-job-4
spec:
  backoffLimit: 3
  parallelism: 5
  template:
    metadata:
      name: hello-world-job-4
    spec:
      restartPolicy: OnFailure
      containers:
      - name: hello-world-container
        image: busybox
        command: ["/bin/sh", "-c"]
        args: ["echo 'Hello world'; sleep 3"]

程式碼解析:

  1. parallelism: 5 表示最多允許 5 個 Pod 同時執行。
  2. 省略了 completions,Job 將持續執行直到成功。

自動終止 Job

使用 activeDeadlineSeconds 可以設定 Job 的最長執行時間,超過此時間 Job 將被終止。

# hello-world-job-5.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: hello-world-job-5
spec:
  backoffLimit: 3
  activeDeadlineSeconds: 60
  template:
    metadata:
      name: hello-world-job-5
    spec:
      restartPolicy: OnFailure
      containers:
      - name: hello-world-container
        image: busybox
        command: ["/bin/sh", "-c"]
        args: ["echo 'Hello world'"]

程式碼解析:

  1. activeDeadlineSeconds: 60 表示 Job 將在 60 秒後自動終止。

自動清理已完成的 Job

預設情況下,已完成的 Job 不會自動刪除。使用 ttlSecondsAfterFinished 可以設定 Job 完成後保留的時間,超過此時間 Job 將被自動刪除。

# hello-world-job-6.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: hello-world-job-6
spec:
  ttlSecondsAfterFinished: 100
  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'"]

程式碼解析:

  1. ttlSecondsAfterFinished: 100 表示 Job 完成後將保留 100 秒,然後自動刪除。