一、更新運行在 Pod 內的應用程序
1. 修改 Pod 模板
將導致應用程序在一定時間內不可用

2. 修改 Service 的 Pod 選擇器
需要同時運行兩倍的 Pod

3. 滾動升級
應用程序需支持兩個版本同時對外提供服務

舊版本 ReplicationController 縮容,同時新版本擴容
通過新舊 ReplicationController 副本數的改變,逐漸將所有 Pod 替換成新版本,結束后刪除原有的 ReplicationController
二、使用 Deployment
用於部署應用程序,並以聲明的方式升級應用
創建 Deployment 時自動創建 ReplicaSet,Pod 由 ReplicaSet 創建和管理
1. 創建 Deployment
定義類似於 ReplicationController。但能指定部署策略:在修改 Deployment 資源時如何執行更新
apiVersion: apps/v1
kind: Deployment
metadata:
name: kubia
spec:
replicas: 3
selector:
matchLabels:
app: kubia
template:
metadata:
name: kubia
labels:
app: kubia
spec:
containers:
- image: luksa/kubia:v1
name: nodejs
# --record:記錄歷史版本號
$ kubectl create -f kubia-deployment-v1.yaml --record
# 查看部署狀態
$ kubectl rollout status deployment kubia
deployment "kubia" successfully rolled out
# 查看部署的資源
$ kubectl get all
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/kubia 3/3 3 3 3m34s
NAME DESIRED CURRENT READY AGE
replicaset.apps/kubia-59d857b444 3 3 3 3m34s
NAME READY STATUS RESTARTS AGE
pod/kubia-59d857b444-4c7v8 1/1 Running 0 3m34s
pod/kubia-59d857b444-7r76k 1/1 Running 0 3m34s
pod/kubia-59d857b444-lrjtp 1/1 Running 0 3m34s
- ReplicaSet 創建的 Pod 名稱是由 ReplicaSet 名稱加上運行時生成的隨機字符串組成的
- Deployment 創建的 ReplicaSet 包含 Pod 模板的哈希值
2. 升級 Deployment
只需修改 Deployment 資源中定義的 Pod 模板,K8s 會自動將系統狀態收斂到定義的狀態
升級策略:
- RollingUpdate:滾動更新。默認策略
- 漸進刪除舊 Pod,同時創建新 Pod
- Pod 數量會浮動,其上下限可配置
- Recreate:一次性刪除所有舊 Pod,之后創建新 Pod
- 適用:系統不支持多個版本同時對外提供服務。但會出現短暫不可用
演示 RollingUpdate
# 1. 減慢滾動升級速度
# kubectl patch 常用於修改單個或少量資源屬性,無需編輯器編輯
$ kubectl patch deployment kubia -p '{"spec": {"minReadySeconds": 10}}'
# 因為 Pod 模板沒變,故不會觸發滾動升級
# 2. 觸發滾動升級
# 指定新的鏡像(可設置任何包含容器的資源)
$ kubectl set image deployment kubia nodejs=luksa/kubia:v2
# 3. 查看滾動升級
$ while true; do curl 10.109.157.15; done
# 可以看到剛開始請求 v1,后來慢慢全部切換到 v2
升級過程由 Deployment 控制器完成。流程為:創建新的 ReplicaSet 然后擴容,同時之前的 ReplicaSet 會縮容至 0。舊的 ReplicaSet 仍被保留
若 Deployment 的 Pod 模板引用了 ConfigMap/Secret,更改 ConfigMap/Secret 資源本身不會觸發升級操作
若想觸發更新可創建新的 ConfigMap/Secret 並修改模板引用
3. 回滾 Deployment
使用新鏡像
# v3 版本請求 5 次后會出錯
$ kubectl set image deployment kubia nodejs=luksa/kubia:v3
# 查看整個升級過程
$ kubectl rollout status deployment kubia
# 模擬應用出錯
$ while true; do curl 10.109.157.15; done
回滾
# 回滾到先前版本
$ kubectl rollout undo deployment kubia
# 顯示升級的版本(歷史版本號會被保存到 ReplicaSet 中)
$ kubectl rollout history deployment kubia
deployment.apps/kubia
REVISION CHANGE-CAUSE # 若不指定 --record,CHANGE-CAUSE 會為空
1 kubectl create --filename=kubia-deployment-v1.yaml --record=true
3 kubectl create --filename=kubia-deployment-v1.yaml --record=true
4 kubectl create --filename=kubia-deployment-v1.yaml --record=true
# 回滾到指定版本
$ kubectl rollout undo deployment kubia --to-revision=1
undo 也可以在滾動升級過程中運行:停止升級並刪除已創建 pod
可通過指定 Deployment 的 revisionHistoryLimit 來限制歷史版本數量,默認 10
4. 控制滾動升級速率
spec:
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
type: RollingUpdate
- maxSurge:決定 Deployment 配置中期望的副本數之外,最多允許超出的 Pod 實例數量。默認值為 25%(四舍五入)
- maxUnavailable:決定在滾動升級期間,相對於期望副本數能夠允許多少 Pod 實例處於不可用狀態。默認值為 25%(四舍五入)
本例中,replicas=3,因此 Pod 數最多可達到 4 且必須有 2 個 Pod 可用

5. 暫停滾動升級
只升級部分,方便用戶驗證新版本 Pod
kubectl set image deployment kubia nodejs=luksa/kubia:v4
kubectl rollout pause deployment kubia
# 這樣會創建一個(數量不可控)新的 Pod
# 若部署被暫停,在恢復部署之前,撤銷命令不會撤銷它
恢復滾動升級
kubectl rollout resume deployment kubia
暫停功能還可用於阻止更新 Deployment 后的自動升級行為。可更改多次,完成更改后再升級
6. 滾動升級前檢查
minReadySeconds 屬性主要是避免部署出錯版本的應用,而不是單單減緩部署的速度。它指定新創建的 Pod 至少要成功運行多久之后,才能將其視為可用。在 Pod 可用前,滾動升級的過程不會繼續
當容器的所有就緒探針都返回成功時,Pod 被標記為就緒狀態。Pod 就緒后等待 minReadySeconds 后才可用,才繼續滾動升級
apiVersion: apps/v1
kind: Deployment
metadata:
name: kubia
spec:
# 更新可以不用加 replicas
selector:
matchLabels:
app: kubia
minReadySeconds: 10
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0 # 挨個替換
type: RollingUpdate
template:
metadata:
name: kubia
labels:
app: kubia
spec:
containers:
- image: luksa/kubia:v3
name: nodejs
readinessProbe:
periodSeconds: 1 # 1s 執行一次就緒探針
httpGet: # 探針發送的請求
path: /
port: 8080
kubectl apply -f kubia-deployment-v3.yaml

默認 10min(spec.progressDeadlineSeconds)內不能完成滾動升級就視為失敗,滾動升級會自動取消
可通過 rollout undo 取消滾動升級
修改資源的不同方式
| 方法 | 作用 | 例子 |
|---|---|---|
| kubectl edit | 使用默認編輯器打開資源配置 | kubectl edit pod test |
| kubectl patch | 修改單個資源屬性 | kubectl patch pod test -p '{"spec": {"replicas": 4}}' |
| kubectl apply | 通過 YAML/JSON 文件修改或創建資源 | kubectl apply -f test.yaml |
| kubectl replace | 通過 YAML/JSON 文件修改資源(資源需存在) | kubectl replace -f test.yaml |
| kubectl set image | 修改包含容器資源的鏡像 | kubectl set image pod test nodejs=kubia:v2 |
鏡像拉取策略
- 若更改后的鏡像推到相同的 tag,會導致鏡像不被重新拉取。可設置容器的 imagePullPolicy 為 Always
- 若容器使用 latest 的 tag,則 imagePullPolicy 默認為 Always,否則為 IfNotPresent
命令
kubectl delete pod --all
kubectl set selector ...
# 提高日志級別,輸出所有 kubectl 發起的 API 服務器請求
kubectl ... --v 6
