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

Deployment 是什麼?為什麼不直接用 Pod?

Pod 自己掛了不會自動補,刪了就沒了。Deployment 是 Pod 的「保母」:跑幾份、版本是什麼、掛了怎麼辦,全部交給 K8s 照顧。

#Kubernetes #Deployment #入門 #ReplicaSet
章節目錄 · 10

直接建 Pod 有什麼問題?親身體驗一下

kubectl run lonely-nginx --image=nginx:1.27
kubectl get pods   # Running,看起來很好

kubectl delete pod lonely-nginx
kubectl get pods # 空的。沒了。沒人幫你補。

如果這是生產環境,使用者現在正看著錯誤頁面。你要嘛半夜爬起來手動補,要嘛等到上班才發現。

這就是「一個人做事」的脆弱。一個人倒了事情就停了。

我們需要的是:告訴 K8s「我要三個 nginx Pod,你幫我維持。少了一個你就自動補」。這個東西就是 Deployment。

Deployment YAML 跟 Pod YAML 差在哪?

# pod.yaml(你已經很熟了)
apiVersion: v1
kind: Pod
metadata:
  name: my-nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.27
    ports:
    - containerPort: 80
# deployment.yaml(多了三樣東西)
apiVersion: apps/v1                    # 不同!
kind: Deployment                       # 不同!
metadata:
  name: nginx-deploy
spec:
  replicas: 3                          # 新!要幾個副本
  selector:                            # 新!怎麼找 Pod
    matchLabels:
      app: nginx
  template:                            # 新!Pod 的模板
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.27
        ports:
        - containerPort: 80

差異對照:

欄位PodDeployment
apiVersionv1apps/v1
kindPodDeployment
容器定義位置spec.containersspec.template.spec.containers
多了什麼沒有replicas + selector + template

三個新欄位的意義

1. replicas: 3 — 要維持幾個 Pod

寫 3 就維持 3 個、寫 5 就維持 5 個。Deployment 最核心的設定。

2. selector.matchLabels — 怎麼找到自己的 Pod

Deployment 不認 Pod 名字,它認 labelmatchLabels: app=nginx 意思是:「所有 label 有 app=nginx 的 Pod,那些就是我管的」。

3. template — Pod 的模板

長得跟 Pod YAML 幾乎一樣(但不寫 apiVersionkind,因為 Deployment 已經知道這是 Pod 模板)。

⚠️ selectortemplate.metadata.labels 必須一致!如果 selector 寫 app: nginx、template labels 寫 app: web,Deployment 找不到自己的 Pod、會以為 Pod 不夠然後一直建,永遠停不下來。

三層關係:Deployment → ReplicaSet → Pod

┌─────────────────────────────────────┐
│           Deployment                │  ← 你管這個
│  ┌───────────────────────────────┐  │
│  │         ReplicaSet            │  │  ← 自動建立,你不用管
│  │  ┌───────┐ ┌───────┐ ┌─────┐ │  │
│  │  │ Pod 1 │ │ Pod 2 │ │Pod 3│ │  │  ← 自動維持數量
│  │  └───────┘ └───────┘ └─────┘ │  │
│  └───────────────────────────────┘  │
└─────────────────────────────────────┘

分工

  • Deployment:管理「版本」(換 Image 時怎麼滾動更新、怎麼 rollback)
  • ReplicaSet:管理「數量」(少了一個馬上補)
  • Pod:實際在跑的容器
你只跟 Deployment 互動,ReplicaSet K8s 自動幫你管。

部署 + 驗證三層

kubectl apply -f deployment.yaml
# deployment.apps/nginx-deploy created

# 驗證三層
kubectl get deployments
# nginx-deploy READY 3/3 AVAILABLE 3

kubectl get replicasets
# nginx-deploy-7d8c5f6b9 DESIRED 3 CURRENT 3 READY 3

kubectl get pods
# nginx-deploy-7d8c5f6b9-abc12 Running
# nginx-deploy-7d8c5f6b9-xyz45 Running
# nginx-deploy-7d8c5f6b9-def67 Running

# 一行看三層
kubectl get deploy,rs,pods

Pod 名字格式:--

重點實驗:刪 Pod 看自動補回

# 隨便挑一個 Pod 名字
kubectl delete pod nginx-deploy-7d8c5f6b9-abc12

# 馬上看
kubectl get pods
# 還是 3 個!但有一個 AGE 是幾秒鐘 ← K8s 自動補了一個新的

ReplicaSet 持續監控:發現從 3 變 2 → 不符合 replicas: 3 → 自動建一個新的補上。整個過程你什麼都不用做

對比剛才的 lonely-nginx

  • 直接 kubectl run 的 Pod:刪掉就沒了
  • 透過 Deployment 的 Pod:刪掉自動補回
  • 想真的不要了?刪 Deployment:kubectl delete deployment nginx-deploy

擴縮容一行搞定

# 雙十一流量暴增,3 → 5
kubectl scale deployment nginx-deploy --replicas=5
kubectl get pods   # 5 個

# 流量過了,5 → 2
kubectl scale deployment nginx-deploy --replicas=2
kubectl get pods # 多的被砍掉,剩 2 個

跟 Docker Compose 對比:

動作Docker ComposeK8s
擴到 5 個docker compose up --scale web=5kubectl scale deploy xxx --replicas=5
自動補 Pod做不到(除非 Swarm)Deployment 自動補
跨機器分散做不到(除非 Swarm)Scheduler 自動分配 Node

從一個人到一個團隊

Pod = 一個人做事
  └─ 生病就停工,沒人頂

Deployment = 一個團隊做事
└─ 有人倒了馬上有人頂上
└─ 半夜 Pod 掛了 → K8s 自動補
└─ 你睡得安穩,明天看監控才知道發生過

重點整理

  • 不要直接建 Pod,要透過 Deployment 管理 Pod
  • Deployment YAML 比 Pod 多三樣:replicas / selector / template
  • 三層關係:Deployment → ReplicaSet → Pod(ReplicaSet 你不用管)
  • selector 跟 template labels 必須一致
  • 刪 Pod 自動補回 = 自我修復
  • kubectl scale 一行擴縮容
  • kubectl delete deployment 才是真的刪掉

下一步

維持 3 個 Pod 會了,但實際工作中會用更頻繁的是擴縮容跟更新。下一篇講Deployment 擴縮容:從 3 個到 100 個一行搞定,順便看 K8s 在多節點叢集怎麼自動分散 Pod。