昨天我們認識了 ReplicaSet,看到它如何自動維持 Pod 的副本數量,帶來高可用性和水平擴展的好處。我們也實際體驗了當 Pod 被刪除時,ReplicaSet 會立刻建立新的 Pod 來替補,看到 ReplicaSet 的自我修復機制。
透過 ReplicaSet,我們解決了單一 Pod 的脆弱性問題,也學會了用更靈活的 selector 來管理 Pod。但在文章最後我提到了一個重要限制:ReplicaSet 雖然能維持副本數量,但對於應用程式的版本更新、滾動部署、版本回滾等進階需求就力不從心了。
想像一下這些實際情境:
如果只用 ReplicaSet,我們可能需要手動刪除舊 Pod、建立新 Pod,過程中服務很可能會中斷。這就是 Deployment 登場的時機——它建構在 ReplicaSet 之上,提供了完整的應用程式生命週期管理。
假設我們有一個 Web 應用程式正在運行,背後由 ReplicaSet 管理多個副本。
當有新版本要上線時,我們當然希望「不中斷服務」的情況下完成更新。這時候最佳解法不是一次性更新所有 Pod,而是逐一替換 Pod,如下圖所示——這就是 Rolling Update (滾動更新)。
而如果新版本出現 bug,我們也能快速撤銷更新,回到前一個版本,這就是 Roll Back (回滾)。
Deployment
的厲害之處不只是「會更新」而已,它的核心價值在於:掌管多個 ReplicaSet,每個 ReplicaSet 再去掌管 Pod。
換句話說,Deployment 提供「版本維度」的抽象,而 ReplicaSet 專注於「數量維度」的控制。透過這樣的層次結構,Deployment 可以在更新時建立新的 ReplicaSet,逐步將流量從舊版本轉移到新版本,達到無縫更新的效果。這樣一層一層的關係就像下圖:
Deployment 的 YAML 與 ReplicaSet 幾乎一模一樣,只需要把 kind
改為 Deployment
即可。
完整的 YAML:
# deployment-def.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deployment
labels:
app: myapp
type: front-end
spec:
replicas: 3
selector:
matchLabels:
type: front-end
template:
metadata:
labels:
app: my-app
type: front-end
spec:
containers:
- name: nginx-container
image: nginx
建立後我們用 kubectl get all
查看結果,可以看到資源的命名階層關係:
這樣就驗證了三者的關聯性。
接下來實際體驗 Deployment 的滾動更新和回滾功能。為了方便觀察,我把 replica (副本) 數設為 1。左邊是指令操作,右邊用 watch
即時監控:
整個流程如下:
nginx:1.91
(故意給錯誤 tag)
kubectl rollout undo
指令
nginx:1.9.1
👉 新 Pod 沒有 Ready 之前,舊 Pod 不會被刪除,這確保了服務的連續性,這就是 Rolling Update 的精髓。
透過今天的實戰,我們可以看到 Deployment
為 Kubernetes 帶來的不只是高可用性,而是 完整的版本管理能力。
明天我們要進一步探討 Kubernetes 的另一個關鍵能力:Namespace。
有了 Deployment 之後,當我們的叢集裡有越來越多服務時,如何分門別類、避免命名衝突、甚至做到多租戶隔離?那就是 Namespace 要解決的問題。