Deployment 怎麼知道哪些 Pod 屬於自己?
Deployment 你已經會用了。但有沒有想過:
- 你刪一個 Pod,Deployment 是怎麼發現少一個的?
- 同一個叢集跑 nginx 跟 httpd 兩個 Deployment,K8s 怎麼分得出哪些 Pod 屬於誰?
- Pod 名字有 hash 不固定,Deployment 用什麼追蹤 Pod?
Labels = Pod 上的便利貼
每個 Pod 都可以貼任意數量的 label:
metadata:
name: my-nginx
labels:
app: nginx # 應用名稱
tier: frontend # 層級
env: prod # 環境
version: v1 # 版本
Label 是 key-value pair。愛貼幾個就貼幾個,K8s 不會限制。
Selector = 告訴 K8s「我要找哪些 Pod」
Deployment 用 selector 找自己的 Pod:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deploy
spec:
replicas: 3
selector:
matchLabels:
app: nginx # 找 app=nginx 的 Pod
template:
metadata:
labels:
app: nginx # template 建出來的 Pod 會有這個 label
spec:
containers:
- name: nginx
image: nginx:1.27
ReplicaSet 持續監控:「目前有幾個 app=nginx 的 Pod?少一個就建一個。」
⚠️ selector 跟 template labels 必須一致
這是 Deployment 最常踩的坑。
spec:
selector:
matchLabels:
app: nginx # 我要找 app=nginx
template:
metadata:
labels:
app: web # ❌ 但建出的 Pod label 是 app=web
結果:
- ReplicaSet 找不到自己建的 Pod(label 不符)
- 以為「Pod 不夠」一直建新的
- 永遠停不下來
自我修復的真正原理
1. Deployment 設 replicas: 3
↓
ReplicaSet 用 selector「app=nginx」找 Pod
↓
你 kubectl delete pod my-nginx-xxx
↓
ReplicaSet 重新查:app=nginx 的 Pod 只剩 2 個
↓
期望 3 但實際 2 → 用 template 建一個新的
Deployment 從來不認 Pod 名字、只認 label。只要 label 對得上,新 Pod 就被「認領」。
實作:手動驗證 label 機制
kubectl create deployment nginx-deploy --image=nginx:1.27 --replicas=3
# 看 Pod label
kubectl get pods --show-labels
# NAME ... LABELS
# nginx-deploy-xxx-aaa ... app=nginx-deploy,pod-template-hash=xxx
# nginx-deploy-xxx-bbb ... app=nginx-deploy,pod-template-hash=xxx
# nginx-deploy-xxx-ccc ... app=nginx-deploy,pod-template-hash=xxx
K8s 自動加了:
app=nginx-deploy(你的 selector)pod-template-hash=xxx(給 ReplicaSet 區分版本用,滾動更新會看到不同 hash)
用 label 篩選 Pod
# 篩 app=nginx-deploy
kubectl get pods -l app=nginx-deploy
# 多個條件用逗號(AND)
kubectl get pods -l app=nginx-deploy,tier=frontend
# 反向選擇
kubectl get pods -l app!=nginx-deploy
實用場景:
# 一次刪除所有 app=test 的 Pod
kubectl delete pods -l app=test
# 看所有 prod 環境的 Pod
kubectl get pods --all-namespaces -l env=prod
「孤兒 Pod」實驗
如果你直接修改 Pod 的 label 把它跟 Deployment 切斷會怎樣?
# 看一下 Deployment 跟 Pod
kubectl get pods -l app=nginx-deploy
# 3 個 Pod
# 改其中一個 Pod 的 label,把 app 改成別的
kubectl label pod nginx-deploy-xxx-aaa app=orphan --overwrite
# 馬上看
kubectl get pods -l app=nginx-deploy
# 只剩 2 個!
kubectl get pods
# 但總共有 4 個 Pod!
# nginx-deploy-xxx-aaa(label app=orphan) ← 孤兒,不歸 Deployment 管
# nginx-deploy-xxx-bbb(label app=nginx-deploy)
# nginx-deploy-xxx-ccc(label app=nginx-deploy)
# nginx-deploy-xxx-NEW(label app=nginx-deploy) ← Deployment 補的新 Pod
Deployment 看到 app=nginx-deploy 的 Pod 變 2 個,立刻補一個新的。原本那個 Pod 還活著、但 label 不符 → 變孤兒,Deployment 不再管它(你要自己 kubectl delete pod 殺掉)。
這個實驗很清楚地展示了 K8s 的關聯都是 label 驅動的。
Service 也是用 label 找 Pod
不只 Deployment,後面學的 Service 也一樣:
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
spec:
selector:
app: nginx # ← 把流量送到所有 app=nginx 的 Pod
ports:
- port: 80
label = K8s 整個世界的關聯機制。掌握 label 就掌握 K8s。
自我修復的場景
實際工作中 K8s 自我修復救過很多次:
| 情境 | K8s 怎麼救 |
|---|---|
| Pod OOM 被 kernel kill | ReplicaSet 補新 Pod |
| Node 當機 | 上面所有 Pod 被自動排到別台 Node |
| 你誤刪 Pod | 馬上補回來 |
| 容器 crash 退出 | restartPolicy 重啟 |
重點整理
- K8s 用 label + selector 關聯資源(不認名字)
- Deployment 的
selector.matchLabels必須跟template.metadata.labels一致 - ReplicaSet 持續監控 label 對得上的 Pod 數量,少了就補
kubectl get pods -l key=value用 label 篩選- 改 Pod label 會讓它脫離 Deployment 變孤兒
- Service 也用 label 找 Pod
- 自我修復不是黑魔法,就是 ReplicaSet 持續比對 label 跟期望數量
下一步
Deployment + Pod 的故事告一段落。但外面怎麼連到 Pod?Pod IP 隨時會變、Pod 還會被 K8s 搬到別的 Node。下一篇進入 Service 的世界:ClusterIP:固定 IP 解決 Pod IP 飄忽問題。