Deployment 是一種無狀態的水平擴展控制器,主要功能也是確保Pod能正常運作, 它建構在Pod和ReplicaSets之上, 可以為Pod和ReplicaSets提供聲明式更新, 大部分的功能都可以透過調用ReplicaSet Controller來實現。它能根據資源狀況分配Pod到各節點,並提供滾動更新與回滾的功能。
圖片參考書:【Kubernetes 進階實踐】
由於它建構在ReplicaSet之上, 所以spec中的字段包含ReplicaSet Controller的replicas
, selector
, template
, minReadySeconds
, 他也是利用這些字段內容完成了下一層的ReplicaSet創建。
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy-example
spec:
replicas: 3
selector:
matchLabels:
app: deploy-demo
template:
metadata:
labels:
app: deploy-demo
spec:
containers:
- name: deploy-hello
image: nginx:latest
ports:
- name: http
containerPort: 80
minReadySeconds: 5
-> % kubectl apply -f deploy-demo.yaml --record
deployment.apps/deploy-example created
-> % kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
deploy-example 3/3 3 3 117s
UP-TO-DATE
表示達到期望狀態的數量AVAILABLE
表示處於可用狀態的數量
-> % kubectl get replicasets -l app=deploy-demo -L app
NAME DESIRED CURRENT READY AGE APP
deploy-example-5b9b49dd7d 3 3 3 6m55s deploy-demo
由此可知 deployment大部分都和ReplicaSet相同, 最大的不同在於 deployment支援滾動更新, 這也是為什麼deployment是被實踐最多的Controller。
Deployment 支援兩種自動更新方案:
1. Recreate: 全面停止、刪除舊的Pod之後以新版本重建。
這也是ReplicaSet的更新方式, 他會導致新舊版本更新期間服務中斷, 優點是服務不會有中間狀態, 不是新版本就是舊版本。
2. RollingUpdate: 逐步替換舊有的Pod直到全部更新為新版本為止。
Deployment更新策略 `default` 為滾動更新, 在刪除舊版本的同時也在創建新版本, 優點是服務不中斷, 缺點是在更新期間執行的請求不保證會是新版本。
Deployment的滾動更新會將新舊版本拆成兩個ReplicaSet Controller 同時分別執行, V1少一個Pod的同時, V2就多一個Pod, 會一直執行到V2版本的Pod符合期望值為止。
圖片參考書:【Kubernetes 進階實踐】
Deployment 支援自訂義滾動更新的節奏, 包含暫停(pause)和繼續(resume), 可以在一個新的pod建立成功之後就先暫停更新, 讓環境中同時存在新舊版本, 用戶再針對新版本進行檢測, 沒問題就繼續更新, 有問題也可以執行回滾, 這就是金絲雀發布的概念。
礦井中的金絲雀
17世紀, 美國礦場的工人發現金絲雀對於瓦斯十分敏感, 空氣中哪怕只有微量的瓦斯氣體, 金絲雀也會停止歌唱;當瓦斯含量超過一定濃度時, 人類可能尚未察覺, 金絲雀卻早已中毒身亡。在當時採礦設備相對簡陋的情況下, 工人在下礦場之前都會帶上一隻金絲雀當作瓦斯檢測工具, 以便在危險情況下緊急撤離。
圖片參考書:【Kubernetes 進階實踐】
先添加, 再刪除, 保持可用的Pod數量超過期望值, 這就是金絲雀的概念。
因為各種原因導致滾動更新無法正常執行,例如image拉不到或是金絲雀
死掉的狀況, 就要執行回滾。
先apply一個deployment, image: nginx:latest
, 修改YAML:image: nginx:v1.0.0
再apply一次
之後查看歷史版本會有兩筆:
-> % kubectl rollout history deployments deploy-example
deployment.apps/deploy-example
REVISION CHANGE-CAUSE
1 kubectl apply --filename=deploy-demo.yaml --record=true
2 kubectl apply --filename=deploy-demo.yaml --record=true
先看一下目前的deployment內容:
Rollback to the previous deployment
kubectl rollout undo deployment/abc
Rollback to daemonset revision 3
kubectl rollout undo daemonset/abc --to-revision=3
Rollback to the previous deployment with dry-run
kubectl rollout undo --dry-run=true deployment/abc
這邊試試看第1種, 回滾到上一版
-> % kubectl rollout undo deployment/deploy-example
deployment.apps/deploy-example rolled back
deployment內容
再看一次歷史版本也會異動
-> % kubectl rollout history deployments deploy-example
deployment.apps/deploy-example
REVISION CHANGE-CAUSE
2 kubectl apply --filename=deploy-demo.yaml --record=true
3 kubectl apply --filename=deploy-demo.yaml --record=true
回滾也會被當作一次滾動更新寫到歷史紀錄中, 但是被回滾的紀錄會被刪除掉, 所以仍舊是2筆記錄。
如果修改YAML:image: nginx:v1.2.0
再apply一次, 因為是一般的滾動更新,
再查看歷史版本紀錄的時候, 就會看到3筆喔!
pause
狀態, 要先把PodTamplate改回到前一版然後resume
, 否則會因為狀態一直處於暫停而無法進行回滾。和ReplicaSet一樣, 只差在對象不同, 這邊就跳過了。