直接建 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
差異對照:
| 欄位 | Pod | Deployment |
|---|---|---|
apiVersion | v1 | apps/v1 |
kind | Pod | Deployment |
| 容器定義位置 | spec.containers | spec.template.spec.containers |
| 多了什麼 | 沒有 | replicas + selector + template |
三個新欄位的意義
1. replicas: 3 — 要維持幾個 Pod
寫 3 就維持 3 個、寫 5 就維持 5 個。Deployment 最核心的設定。
2. selector.matchLabels — 怎麼找到自己的 Pod
Deployment 不認 Pod 名字,它認 label。matchLabels: app=nginx 意思是:「所有 label 有 app=nginx 的 Pod,那些就是我管的」。
3. template — Pod 的模板
長得跟 Pod YAML 幾乎一樣(但不寫 apiVersion 跟 kind,因為 Deployment 已經知道這是 Pod 模板)。
⚠️selector和template.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:實際在跑的容器
部署 + 驗證三層
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 Compose | K8s |
|---|---|---|
| 擴到 5 個 | docker compose up --scale web=5 | kubectl 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。