在 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
重點解析:
- Annotations 與 Labels 的區別:Annotations 用於儲存額外的資訊,而 Labels 用於物件的識別和選擇。
- 使用場景:Annotations 可以包含組態資訊、建立者的姓名等,而 Labels 用於建立 Kubernetes 物件之間的關聯。
- 操作方式:可以使用 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'
內容解密:
kubectl describe Pod:用於檢視Pod的詳細資訊,包括註解。kubectl get po -o yaml:以YAML格式輸出Pod的詳細組態。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'"]
內容解密:
apiVersion: batch/v1:指定Job的API版本。kind: Job:定義資源型別為Job。restartPolicy: OnFailure:設定失敗重啟策略,若Pod或容器失敗,將會重啟。containers:定義容器相關組態,包括映象、命令和引數。
建立Job後,可以使用以下命令檢視其狀態:
$ kubectl apply -f hello-world-job.yaml
$ kubectl get jobs
輸出結果將顯示Job的完成狀態和執行時間。
內容解密:
kubectl apply -f hello-world-job.yaml:根據YAML檔案建立Job。kubectl get jobs:檢視Job的狀態,包括完成數和執行時間。
在 Kubernetes 中執行容器的工作管理
瞭解 Job 物件的 restartPolicy
在 Kubernetes 中,Job 物件用於執行一次性任務,而 restartPolicy 引數則控制著任務失敗時的重啟策略。該引數可設為兩個選項:Never 和 OnFailure。
- 當設定為
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'"]
程式碼解析:
backoffLimit: 3表示 Job 在失敗後最多重試 3 次。restartPolicy: OnFailure表示當容器失敗時重啟。- 使用
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"]
程式碼解析:
completions: 10表示 Job 需要成功執行 10 次。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"]
程式碼解析:
parallelism: 5表示最多允許 5 個 Pod 同時執行。- 省略了
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'"]
程式碼解析:
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'"]
程式碼解析:
ttlSecondsAfterFinished: 100表示 Job 完成後將保留 100 秒,然後自動刪除。