概述
本文核心問題是:如何升級應用。
對於Pod的更新有兩種策略:
- 一是刪除全部舊Pod之後再建立新Pod。好處是,同一時間只會有一個版本的應用存在;缺點是,應用有一段時間不可用。
- 二是先建立新Pod,再刪除舊Pod。可以一次性建立全部,再刪除全部,也可以逐漸建立刪除。好處是應用一直可用,缺點是要同時支援兩個版本。
藍綠部署
對於應用的版本v1和版本v2:
- 在執行v1前,流量一直都在v2上
- 部署v1,然後測試通過後,將流量切換到v2,v2就成為了新的生產環境
- 一旦v2出現問題,可以在切回v1
金絲雀部署(也稱灰度部署)
金絲雀部署一種增量釋出,先是在小範圍內釋出,然後觀察測試,如無問題逐漸釋出全部。
kubectl rolling-update
因為kubectl rolling-update的方式已經過時,所以只是做一下簡介。
假設現在有一個名為test-v1,Pod選擇器為app=order
的ReplicationController要升級為test-v2,則執行下面命令可升級:
k rolling-update test-v1 test-v2 --image=test:v2
執行此命令後:
- 立刻建立一個名為test-v2的ReplicationController,他的Pod模板映象正是test:v2,並新增一個標籤
deployment=xxxx
。 - test-v1以及
app=order
選中的Pod都會被加上一個標籤:deployment=yyyy
。如此做法是防止Pod的管理混亂。 - 先將test-v2的Pod擴充套件為1,使用更新後的模板建立新Pod;再將test-v1縮小1,如此迴圈。
- 因為在滾動過程中Service的標籤選擇器一直是
app=order
,所以新老版本都會接收到流量。
過時的原因是:伸縮的請求時由kubectl發起的,如果因為任何原因丟失了網路連線,升級將處於中間狀態。另一個原因是:期望只修改Pod定義中的映象tag,就能時Kubernetes執行升級工作
使用Deployment宣告式的升級
Deployment是一種更高階的資源,用於部署程式並以宣告的方式升級應用,而不是通過ReplicationController或ReplicaSet進行部署。
在使用Deployment時,Pod是由Deployment的ReplicaSet建立的。
準備映象
將之前的文章(Kubernetes學習筆記(四):服務)裡的拿過來做一下微小的改動,生成兩個映象。改動內容就是在輸出內容加上版本號。
fmt.Fprintf(w,"this is v1, hostname: %v\n",hostname)
docker push registry.cn-hangzhou.aliyuncs.com/orzi/goweb:v1
fmt.Fprintf(w,"this is v2, hostname: %v\n",hostname)
docker push registry.cn-hangzhou.aliyuncs.com/orzi/goweb:v2
建立Deployment
Deployment與ReplicaSet的配置相似,都含有標籤選擇器、副本數量和Pod模板。此外Deployment還會包含一個部署策略。
定義Service
定義了一個NodePort型別的Service
# goweb-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: goweb
spec:
type: NodePort
selector:
app: goweb
ports:
- port: 80
targetPort: 8000
nodePort: 31234
定義Deployment
# goweb-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: goweb
spec:
replicas: 3
selector:
matchLabels:
app: goweb
template:
metadata:
labels:
app: goweb
spec:
containers:
- name: goweb
image: registry.cn-hangzhou.aliyuncs.com/orzi/goweb:v1
執行檢視
可以看到名為goweb-fdfcfdcc6
的RS,有個label是pod-template-hash=fdfcfdcc6
,顧名思義,fdfcfdcc6就是pod模板的hash值。
建立Deployment時指定 --record 記錄歷史版本號,非常有用
-> [root@kube0.vm] [~] k create -f goweb-svc.yaml
service/goweb created
-> [root@kube0.vm] [~] k create -f goweb-deployment.yaml --record
deployment.apps/goweb created
-> [root@kube0.vm] [~] k get all -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/goweb-fdfcfdcc6-4wklw 1/1 Running 0 9s 10.244.2.37 kube2.vm <none> <none>
pod/goweb-fdfcfdcc6-bw8c4 1/1 Running 0 9s 10.244.2.36 kube2.vm <none> <none>
pod/goweb-fdfcfdcc6-xjcwf 1/1 Running 0 9s 10.244.1.33 kube1.vm <none> <none>
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/goweb NodePort 10.100.193.94 <none> 80:31234/TCP 28s app=goweb
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 54s <none>
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
deployment.apps/goweb 3/3 3 3 9s goweb registry.cn-hangzhou.aliyuncs.com/orzi/goweb:v1 app=goweb
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
replicaset.apps/goweb-fdfcfdcc6 3 3 3 9s goweb registry.cn-hangzhou.aliyuncs.com/orzi/goweb:v1 app=goweb,pod-template-hash=fdfcfdcc6
升級Deployment
只要修改Deployment的Pod模板定義,Kubernetes會自動的將實際狀態收斂為修改後的狀態。對於升級,只需要修改Pod中映象的tag。
升級策略由deployment.spec.strategy.type
定義,值是Recreate或RollingUpdate,預設RollingUpdate。
kubectl patch及minReadySeconds
使用kubectl patch定義deployment.spec.minReadySeconds
來減慢滾動升級時間,以便觀察升級過程
-> [root@kube0.vm] [~] k patch deployment goweb -p '{"spec":{"minReadySeconds":5}}'
deployment.apps/goweb patched
迴圈請求服務
在執行升級前新開視窗,執行下面的命令檢視輸出
-> [root@kube0.vm] [~] while true; do curl http://192.168.199.231:31234/ ; sleep 1; done
this is v1, hostname: goweb-fdfcfdcc6-pw7b4
this is v1, hostname: goweb-fdfcfdcc6-pw7b4
this is v1, hostname: goweb-fdfcfdcc6-x8n7h
this is v1, hostname: goweb-fdfcfdcc6-pw7b4
this is v1, hostname: goweb-fdfcfdcc6-x8n7h
this is v1, hostname: goweb-fdfcfdcc6-j4mz8
this is v1, hostname: goweb-fdfcfdcc6-j4mz8
# 以上是升級之前的輸出、以下是開始升級後的
this is v1, hostname: goweb-fdfcfdcc6-x8n7h
this is v1, hostname: goweb-fdfcfdcc6-pw7b4
this is v1, hostname: goweb-fdfcfdcc6-pw7b4
this is v1, hostname: goweb-fdfcfdcc6-j4mz8
this is v2, hostname: goweb-65cc575865-25988
this is v2, hostname: goweb-65cc575865-25988
this is v1, hostname: goweb-fdfcfdcc6-x8n7h
this is v1, hostname: goweb-fdfcfdcc6-j4mz8
this is v2, hostname: goweb-65cc575865-bfd98
this is v2, hostname: goweb-65cc575865-bfd98
this is v2, hostname: goweb-65cc575865-25988
this is v2, hostname: goweb-65cc575865-25988
this is v2, hostname: goweb-65cc575865-25988
# 這之後就是升級完成了
kubectl set
使用 kubectl set image 更新任何包含容器資源的映象。
-> [root@kube0.vm] [~] k set image deployment goweb goweb=registry.cn-hangzhou.aliyuncs.com/orzi/goweb:v2
deployment.apps/goweb image updated
kubectl rollout
檢視升級狀態資訊。執行完kubectl set image,立刻執行下面的命令。手速得快,不然趕不上熱乎的。
-> [root@kube0.vm] [~] k rollout status deployment goweb
Waiting for deployment "goweb" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment "goweb" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment "goweb" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment "goweb" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "goweb" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "goweb" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "goweb" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "goweb" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "goweb" rollout to finish: 1 old replicas are pending termination...
deployment "goweb" successfully rolled out
修改Deployment或其他資源的方式
方法 | 作用 |
---|---|
kubectl edit | 使用編輯器開啟資源配置 |
kubectl patch | 在命令列以merge的方式修改配置 |
kubectl apply | 通過yaml或者json檔案,修改新改動的值。如果指定的物件不存在則建立。 |
kubectl replace | 使用yaml或者json檔案替換一個必須已存在的物件配置。 |
kubectl set image | 修改映象 |
回滾
使用kubectl rollout undo 回滾到上一個版本
-> [root@kube0.vm] [~] k rollout undo deployment goweb
deployment.apps/goweb rolled back
使用 kubectl rollout history 檢視版本記錄
-> [root@kube0.vm] [~] k rollout history deployment goweb
deployment.apps/goweb
REVISION CHANGE-CAUSE
6 kubectl create --filename=goweb-deployment.yaml --record=true
7 kubectl create --filename=goweb-deployment.yaml --record=true
回滾到特定版本
-> [root@kube0.vm] [~] k rollout undo deployment goweb --to-revision=5
error: unable to find specified revision 5 in history
-> [root@kube0.vm] [~] k rollout undo deployment goweb --to-revision=7
deployment.apps/goweb skipped rollback (current template already matches revision 7)
-> [root@kube0.vm] [~] k rollout undo deployment goweb --to-revision=6
deployment.apps/goweb rolled back
通過deployment.spec.revisionHistoryLimit
指定歷史版本個數,預設為2。也就是當前和上一個版本。
控制滾動升級速率
deployment.spec.strategy.rollingUpdate
下有兩個欄位,用來控制升級速率
- maxSurge:超出期望副本數的Pod例項的比例或個數。預設25%,轉換成絕對值後四捨五入,也可以直接指定為絕對值。
- maxUnavailable:滾動升級時,最多允許有多少例項不可用,預設25%,轉換成絕對值後四捨五入,也可以直接指定為絕對值。
暫停、恢復升級
- 使用
kubectl rollout pause
暫停升級 - 使用
kubectl rollout resume
取消暫停
阻止出錯版本的滾動升級
- minReadySeconds:指定新建立的Pod至少要執行多久才視為可用。
- 配置就緒探針
- 為滾動升級配置progressDeadlineSeconds
小結
- kubectl rolling-update 過時的原因:伸縮的請求時由kubectl發起的,如果因為任何原因丟失了網路連線,升級將處於中間狀態
- Deployment是一種更高階的資源,用於部署程式並以宣告的方式升級應用,而不是通過ReplicationController或ReplicaSet進行部署。
- 建立Deployment時指定 --record 記錄歷史版本號
- Deployment下的ReplicaSet命名是
DeploymentName+Pod模板Hash
,而ReplicaSet下的Pod是在此基礎拼接個隨機字串。 - 升級策略由
deployment.spec.strategy.type
定義,值是Recreate或RollingUpdate,預設RollingUpdate。 - 定義
deployment.spec.minReadySeconds
來減慢滾動升級時間 - maxSurge與maxUnavailable控制滾動升級速率
- 命令:patch、set、rollout
- kubectl rollout:status、undo、pause、resume、history。