K8s · 工作負載 · 第 16 課 · · 9min read

K8s 自我修復原理:Labels 和 Selector 在做什麼?

為什麼 delete pod 之後 K8s 自動補一個?因為 Deployment 用 selector 一直在數「我管的 label 有幾個 Pod」,少一個就補一個。這篇用 label 拆穿 K8s 的魔法。

#Kubernetes #自我修復 #Labels #Selector
章節目錄 · 12

Deployment 怎麼知道哪些 Pod 屬於自己?

Deployment 你已經會用了。但有沒有想過:

  • 你刪一個 Pod,Deployment 是怎麼發現少一個的?
  • 同一個叢集跑 nginx 跟 httpd 兩個 Deployment,K8s 怎麼分得出哪些 Pod 屬於誰?
  • Pod 名字有 hash 不固定,Deployment 用什麼追蹤 Pod?
答案不是 Pod 名字,而是 Labels(標籤)+ Selector(選擇器)。這是 K8s 整個資源關聯的核心機制。

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 不夠」一直建新的
  • 永遠停不下來
寫 Deployment YAML 時務必檢查這兩處 label 一致。

自我修復的真正原理

1. Deployment 設 replicas: 3
   ↓
2. ReplicaSet 用 selector「app=nginx」找 Pod
   ↓
3. 你 kubectl delete pod my-nginx-xxx
   ↓
4. ReplicaSet 重新查:app=nginx 的 Pod 只剩 2 個
   ↓
5. 期望 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 killReplicaSet 補新 Pod
Node 當機上面所有 Pod 被自動排到別台 Node
你誤刪 Pod馬上補回來
容器 crash 退出restartPolicy 重啟
不需要你寫腳本、不需要你半夜爬起來,這就是 K8s 比 Docker 強的核心。

重點整理

  • 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 飄忽問題。

📅 下一篇:ClusterIP Service 入門:Pod 之間怎麼互相找到?
Pod IP 會變、Pod 還會搬家——Service 給你一個永不變的虛擬 IP,正式進入 K8s 網路世界。
📚 完整系列總覽:K8s 系列教學首頁(共 40 課,按學習路徑順序排)