1. 程式人生 > >Kubernetes技術分析之灰度升級

Kubernetes技術分析之灰度升級

【編者的話】Docker的流行激活了一直不溫不火的PaaS,隨著而來的是各類Micro-PaaS的出現,Kubernetes是其中最具代表性的一員,它是Google多年大規模容器管理技術的開源版本。本系列文章將逐一分析Kubernetes,本文介紹 Kubernetes對灰度升級的支援。 

Kubernetes灰度升級

灰度升級(又稱灰度釋出、灰度更新)是指在黑與白之間,能夠平滑過渡的一種釋出方式。ABtest就是一種灰度釋出方式,讓一部使用者繼續用A,一部分使用者開始用B,如果使用者對B沒有什麼反對意見,那麼逐步擴大範圍,把所有使用者都遷移到B上面來。灰度釋出可以保證整體系統的穩定,在初始灰度的時候就可以發現、調整問題,以保證其影響度。


Kubenetes中支援灰度升級,現在我們先通過一個例子演示應用從V1版本灰度升級到V2版本,建立V1版本的Replication Controller ,配置檔案my-web-v1-rc.yaml
apiVersion: v1
kind: ReplicationController
metadata:
name: my-web-v1
spec:
selector:
app: my-web
version: v1
template:
metadata:
  labels:
    app: my-web
    version: v1
spec:
  containers:
  - name: my-web
    image: my-web:v1
    ports:
    - containerPort: 80
      protocol: TCP 


通過配置檔案建立Replication Controller
$ kubectl create -f my-web-v1-rc.yaml 
replicationcontrollers/my-web-v1

$ kubectl get rc my-web-v1
CONTROLLER   CONTAINER(S)   IMAGE(S)    SELECTOR                REPLICAS
my-web-v1    my-web         my-web:v1   app=my-web,version=v1   1 

然後擴容Replication Controller到副本數目4:

$ kubectl scale rc my-web-v1 --replicas=4
scaled

$ kubectl get pods -l app=my-web
NAME              READY     STATUS    RESTARTS   AGE
my-web-v1-2r7ag   1/1       Running   0          6s
my-web-v1-mv9wg   0/1       Running   0          6s
my-web-v1-qvi4r   1/1       Running   0          6s
my-web-v1-v1w9e   1/1       Running   0          13s

現在需要升級V1版本到V2版本,V2版本的Replication Controller配置檔案my-web-v2-rc.yaml:
apiVersion: v1
kind: ReplicationController
metadata:
name: my-web-v2
spec:
selector:
app: my-web
version: v2
template:
metadata:
  labels:
    app: my-web
    version: v2
spec:
  containers:
  - name: my-web
    image: my-web:v2
    ports:
    - containerPort: 80
      protocol: TCP

開始灰度升級:
$ kubectl rolling-update my-web-v1 -f my-web-v2-rc.yaml --update-period=10s
Creating my-web-v2
At beginning of loop: my-web-v1 replicas: 3, my-web-v2 replicas: 1
Updating my-web-v1 replicas: 3, my-web-v2 replicas: 1
At end of loop: my-web-v1 replicas: 3, my-web-v2 replicas: 1
At beginning of loop: my-web-v1 replicas: 2, my-web-v2 replicas: 2
Updating my-web-v1 replicas: 2, my-web-v2 replicas: 2
At end of loop: my-web-v1 replicas: 2, my-web-v2 replicas: 2
At beginning of loop: my-web-v1 replicas: 1, my-web-v2 replicas: 3
Updating my-web-v1 replicas: 1, my-web-v2 replicas: 3
At end of loop: my-web-v1 replicas: 1, my-web-v2 replicas: 3
At beginning of loop: my-web-v1 replicas: 0, my-web-v2 replicas: 4
Updating my-web-v1 replicas: 0, my-web-v2 replicas: 4
At end of loop: my-web-v1 replicas: 0, my-web-v2 replicas: 4
Update succeeded. Deleting my-web-v1
my-web-v2

升級開始後,首先根據提供的配置檔案建立新的Replication Controller(V2版本),然後每隔10s(通過--update-period設定)逐步增加新的Replication Controller(V1版本)的副本數,逐步減少舊的Replication Controller的副本數,升級完成後後刪除舊的Replication Controller,保留新的Replication Controller,即實現灰度升級。
Updating my-web-v1 replicas: 3, my-web-v2 replicas: 1
Updating my-web-v1 replicas: 2, my-web-v2 replicas: 2
Updating my-web-v1 replicas: 1, my-web-v2 replicas: 3
Updating my-web-v1 replicas: 0, my-web-v2 replicas: 4

升級期間通過查詢Pod,V2版本的Pod目前相應增加逐漸替換V1版本的Pod,當然這是通過調整Replication Controller的副本數目來控制:
$ kubectl get rc,pods -l app=my-web
CONTROLLER   CONTAINER(S)   IMAGE(S)    SELECTOR                REPLICAS
my-web-v1    my-web         my-web:v1   app=my-web,version=v1   2
my-web-v2    my-web         my-web:v2   app=my-web,version=v2   2
NAME              READY     STATUS    RESTARTS   AGE
my-web-v1-2r7ag   1/1       Running   0          1m
my-web-v1-mv9wg   1/1       Running   0          1m
my-web-v2-bg8ur   1/1       Running   0          18s
my-web-v2-qr33c   1/1       Running   0          41s

待升級完成,即V2的Pod完全替換V1的Pod,同時V1的Replication Controller也被V2的Replication Controller替換:
$ kubectl get rc,pods -l app=my-web
CONTROLLER   CONTAINER(S)   IMAGE(S)    SELECTOR                REPLICAS
my-web-v2    my-web         my-web:v2   app=my-web,version=v2   4
NAME              READY     STATUS    RESTARTS   AGE
my-web-v2-785ok   1/1       Running   0          35s
my-web-v2-bg8ur   1/1       Running   0          1m
my-web-v2-qr33c   1/1       Running   0          1m
my-web-v2-y2es3   1/1       Running   0          57s

如果在升級過程中,發生錯誤中途退出的時候,可以選擇繼續升級,繼續升級的話Kubernetes能夠智慧地判斷出升級中斷之前的階段。然後緊接著繼續執行升級。

另外也可以進行回退,命令如下。
$ kubectl rolling-update my-web-v1 my-web-v2 --rollback --image=my-web:v2
Found existing update in progress (my-web-v2), resuming.
Found desired replicas.Continuing update with existing controller my-web-v1.
At beginning of loop: my-web-v2 replicas: 1, my-web-v1 replicas: 3
Updating my-web-v2 replicas: 1, my-web-v1 replicas: 3
At end of loop: my-web-v2 replicas: 1, my-web-v1 replicas: 3
At beginning of loop: my-web-v2 replicas: 0, my-web-v1 replicas: 4
Updating my-web-v2 replicas: 0, my-web-v1 replicas: 4
At end of loop: my-web-v2 replicas: 0, my-web-v1 replicas: 4
Update succeeded. Deleting my-web-v2
my-web-v2

回退的方式實際上就是升級的逆操作,逐步增加舊的Replication Controller(V1版本)的副本數,逐步減少新的Replication Controller(V2版本)的副本數。

參考


==========================================================
作者簡介
吳龍輝,現任網宿科技高階運營工程師,致力於雲端計算PaaS的研究和實踐,活躍於CloudFoundry,Docker,Kubernetes等開源社群,貢獻程式碼和撰寫技術文件。