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

蝦敏四把刀發表於2020-05-26

概述

本文核心問題是:如何升級應用。
對於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 記錄歷史版本號,非常有用

-> [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。

相關文章