1. 程式人生 > >Kubernetes學習筆記(八):Deployment--宣告式的升級應用

Kubernetes學習筆記(八):Deployment--宣告式的升級應用

## 概述 本文核心問題是:如何升級應用。 對於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 ``` 執行此命令後: 1. 立刻建立一個名為test-v2的ReplicationController,他的Pod模板映象正是test:v2,並新增一個標籤`deployment=xxxx`。 2. test-v1以及`app=order`選中的Pod都會被加上一個標籤:`deployment=yyyy`。如此做法是防止Pod的管理混亂。 3. 先將test-v2的Pod擴充套件為1,使用更新後的模板建立新Pod;再將test-v1縮小1,如此迴圈。 4. 因為在滾動過程中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 記錄歷史版本號,非常有用 ``` -> [[email protected]] [~] k create -f goweb-svc.yaml service/goweb created -> [[email protected]] [~] k create -f goweb-deployment.yaml --record deployment.apps/goweb created -> [[email protected]] [~] 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 pod/goweb-fdfcfdcc6-bw8c4 1/1 Running 0 9s 10.244.2.36 kube2.vm pod/goweb-fdfcfdcc6-xjcwf 1/1 Running 0 9s 10.244.1.33 kube1.vm NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR service/goweb NodePort 10.100.193.94 80:31234/TCP 28s app=goweb service/kubernetes ClusterIP 10.96.0.1 443/TCP 54s 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`來減慢滾動升級時間,以便觀察升級過程 ``` -> [[email protected]] [~] k patch deployment goweb -p '{"spec":{"minReadySeconds":5}}' deployment.apps/goweb patched ``` #### 迴圈請求服務 在執行升級前新開視窗,執行下面的命令檢視輸出 ``` -> [[email protected]] [~] 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 更新任何包含容器資源的映象。 ``` -> [[email protected]] [~] k set image deployment goweb goweb=registry.cn-hangzhou.aliyuncs.com/orzi/goweb:v2 deployment.apps/goweb image updated ``` #### kubectl rollout 檢視升級狀態資訊。執行完kubectl set image,立刻執行下面的命令。手速得快,不然趕不上熱乎的。 ``` -> [[email protected]] [~] 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 回滾到上一個版本 ``` -> [[email protected]] [~] k rollout undo deployment goweb deployment.apps/goweb rolled back ``` 使用 kubectl rollout history 檢視版本記錄 ``` -> [[email protected]] [~] 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 ``` 回滾到特定版本 ``` -> [[email protected]] [~] k rollout undo deployment goweb --to-revision=5 error: unable to find specified revision 5 in history -> [[email protected]] [~] k rollout undo deployment goweb --to-revision=7 deployment.apps/goweb skipped rollback (current template already matches revision 7) -> [[email protected]] [~] 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、his