Kruise Rollout: 讓所有應用負載都能使用漸進式交付

阿里巴巴雲原生發表於2022-04-26

*作者:趙明山(立衡)*


## 前言


OpenKruise **[1]**  是阿里雲開源的雲原生應用自動化管理套件,也是當前託管在 Cloud Native Computing Foundation (CNCF) 下的 Sandbox 專案。它來自阿里巴巴多年來容器化、雲原生的技術沉澱,是阿里內部生產環境大規模應用的基於 Kubernetes 之上的標準擴充套件元件,也是緊貼上游社群標準、適應網際網路規模化場景的技術理念與最佳實踐。在原有的工作負載、sidecar 管理等領域外,Kruise 目前正在漸進式交付領域進行嘗試。


## 什麼是漸進式交付?


**“漸進式交付”** 一詞最早起源於大型、複雜的工業化專案,它試圖將複雜的專案進行分階段拆解,透過持續進行小型閉環迭代降低交付成本和時間。隨著 Kubernetes 及雲原生理念被普及之後,尤其是在持續部署流水線出現後,漸進式交付為網際網路應用提供了基礎設施和實現方法。


在產品的迭代過程中,可以將漸進式交付的具體行為附著在流水線中,將整條交付流水線看作產品迭代的一個過程和一次漸進式交付週期。**漸進式交付在實踐中是以 A/B 測試、金絲雀/灰度釋出等技術手段落地的**。以 **淘寶商品推薦** 為例,其每次釋出重大功能,都會經歷一次典型的漸進式交付過程,**從而透過漸進式交付提高交付的穩定性和效率**:


![1.png](~tplv-k3u1fbpfcp-zoom-1.image "1.png")


## 為什麼要 Kruise Rollout


Kubernetes 只提供了應用交付的 Deployment 控制器,以及針對流量的 Ingress、Service 抽象,但是如何將上述實現組合成開箱即用的漸進式交付方案,Kubernetes 並沒有出標準的定義。Argo-rollout 與 Flagger 是社群目前比較流行的漸進式交付方案,但是它們在一些能力和理念上跟我們的設想不太一樣。**首先,它們僅支援 Deployment, 不支援 Statefulset、Daemonset,更不用說自定義的 operator 了;其次,它們不是“非侵入式的漸進式釋出方式”** ,例如:Argo-rollout 不能支援社群 K8S Native Deployment、Flagger 對業務建立的 Deployment 進行了複製導致 Name 改變而與 Gitops 或自建 Paas 存在一些相容性的問題。


另外,百花齊放是雲原生的一大特點。阿里雲容器團隊負責整個容器平臺雲原生架構的演進,在應用漸進式交付領域也有強烈的需求,因此在參考社群方案以及考慮阿里內部場景的基礎上,我們在設計 Rollout 過程中有以下幾個目標:


1.  **無侵入性:對原生的 Workload 控制器以及使用者定義的 Application Yaml 定義不進行任何修改,保證原生資源的乾淨、一致**


2.  **可擴充套件性:透過可擴充套件的方式,支援 K8S Native Workload、自定義 Workload 以及 Nginx、Isito 等多種 Traffic 排程方式**


3.  **易用性:對使用者而言開箱即用,能夠非常方便的與社群 Gitops 或自建 Paas 結合使用**


## Kruise Rollout:旁路的漸進式交付能力


Kruise Rollout **[2]** 是 Kruise 針對漸進式交付抽象的定義模型,完整的 Rollout 定義:滿足配合應用流量和實際部署例項的金絲雀釋出、藍綠髮布、A/B Testing 釋出,以及釋出過程能夠基於 Prometheus Metrics 指標自動化分批與暫停,並能提供旁路的無感對接、相容已有的多種工作負載(Deployment、CloneSet、DaemonSet),架構如下:


![2.png](~tplv-k3u1fbpfcp-zoom-1.image "2.png")


### 流量排程(金絲雀、A/B Test、藍綠)與分批發布


金絲雀與分批發布是漸進式交付實踐中最常用的釋出方式,如下所示:


1.  workloadRef 旁路式的選擇需要 Rollout 的 Workload(Deployment、CloneSet、DaemonSet)。

1.  canary.Steps 定義了整個 Rollout 過程一共分為五批,其中第一批只灰度一個新版本 Pod,並且 routing 5% 流量到新版本 Pod,並且需要人工確認是否繼續釋出。

1.  第二批發布 40% 新版本 Pod,以及 Routing 40% 流量到新版本 Pod,且釋出完成後 sleep 10m,自動釋出後面批次。

1.  trafficRoutings 定義了業務 Ingress 控制器為 Nginx,此處設計為可擴充套件實現,除 Nginx 之外還可以支援 Istio、Alb 等其它流量控制器。


```

apiVersion: rollouts.kruise.io/v1alpha1

kind: Rollout

spec:

  strategy:

    objectRef:

      workloadRef:

        apiVersion: apps/v1

        # Deployment, CloneSet, AdDaemonSet etc.

        kind: Deployment 

        name: echoserver

    canary:

      steps:

        # routing 5% traffics to the new version

      - weight: 5

        # Manual confirmation, release the back steps

        pause: {}

        # optional, The first step of released replicas. If not set, the default is to use 'weight', as shown above is 5%.

        replicas: 1

      - weight: 40

        # sleep 600s, release the back steps

        pause: {duration: 600}

      - weight: 60

        pause: {duration: 600}

      - weight: 80

        pause: {duration: 600}

        # 最後一批無需配置

      trafficRoutings:

        # echoserver service name

      - service: echoserver

        # nginx ingress

        type: nginx

        # echoserver ingress name

        ingress:

          name: echoserver

```


### 基於 Metrics 指標自動化分批與暫停


Rollout 過程中能夠自動的分析業務 Prometheus Metrics 指標,然後與 steps 結合起來,來決定 Rollout 是否需要繼續或者暫停。如下所示,在釋出完每個批次之後分析過去五分鐘業務的 http 狀態碼,如果 http 200 的比例小於 99.5 將暫停此 Rollout 過程。


```

apiVersion: rollouts.kruise.io/v1alpha1

kind: Rollout

spec:

  strategy:

    objectRef:

      ...

    canary:

      steps:

      - weight: 5

        ...

      # metrics分析  

      analysis:

        templates:

        - templateName: success-rate

          startingStep: 2 # delay starting analysis run until setWeight: 40%

          args:

          - name: service-name

            value: guestbook-svc.default.svc.cluster.local


# metrics analysis模版

apiVersion: rollouts.kruise.io/v1alpha1

kind: AnalysisTemplate

metadata:

  name: success-rate

spec:

  args:

  - name: service-name

  metrics:

  - name: success-rate

    interval: 5m

    # NOTE: prometheus queries return results in the form of a vector.

    # So it is common to access the index 0 of the returned array to obtain the value

    successCondition: result[0] >= 0.95

    failureLimit: 3

    provider:

      prometheus:

        address:

        query: |

          sum(irate(

            istio_requests_total{reporter="source",destination_service=~"{{args.service-name}}",response_code!~"5.*"}[5m]

          )) / 

          sum(irate(

            istio_requests_total{reporter="source",destination_service=~"{{args.service-name}}"}[5m]

          ))

```


## 金絲雀釋出實踐


1.  假設使用者有基於 Kubernetes 部署 echoServer 服務如下,並且透過 nginx ingress 對外服務:


![3.png](~tplv-k3u1fbpfcp-zoom-1.image "3.png")


2.  定義 Kruise Rollout 金絲雀釋出(1 個新版本 Pod,以及 5% 流量),並 apply -f 到 Kubernetes 叢集


```

apiVersion: rollouts.kruise.io/v1alpha1

kind: Rollout

metadata:

  name: rollouts-demo

spec:

  objectRef:

    ...

  strategy:

    canary:

      steps:

      - weight: 5

        pause: {}

        replicas: 1

      trafficRoutings:

        ...

```


3.  升級 echoserver 映象版本(Version 1.10.2 -> 1.10.3),並 kubectl -f 到 Kuberernetes 叢集中


```

apiVersion: apps/v1

kind: Deployment

metadata:

  name: echoserver

...

spec:

  ...

  containers:

  - name: echoserver

    image: cilium/echoserver:1.10.3

```


Kruise Rollout 監聽到上述行為後,將會自動開始金絲雀釋出過程。如下所示,自動生成 canary Deployment、service 以及 Ingress,並且配置 5% 流量到新版本 Pods:


![4.png](~tplv-k3u1fbpfcp-zoom-1.image "4.png")


4.  金絲雀一段時間後,業務研發同學確認新版本無異常後,可以透過命令 **kubectl-kruise rollout approve rollout/rollouts-demo -n default** 釋出剩餘所有的 Pods。Rollout 會精確的控制後續過程,當釋出完成後,會回收所有的 canary 資源,恢復到使用者部署的狀態。


![5.png](~tplv-k3u1fbpfcp-zoom-1.image "5.png")


5.  如果在金絲雀過程中發現新版本異常,可以將業務映象調整為之前版本(1.10.2),然後 kubectl apply -f 到 Kubernetes 叢集當中。Kruise Rollout 監聽到該行為,會回收所有的 canary 資源,達到快速回滾的效果。


```

apiVersion: apps/v1

kind: Deployment

metadata:

  name: echoserver

...

spec:

  ...

  containers:

  - name: echoserver

    image: cilium/echoserver:1.10.2

```


![6.png](~tplv-k3u1fbpfcp-zoom-1.image "6.png")


## 總結


隨著 Kubernetes 上面部署的應用日益增多,如何做到業務快速迭代與應用穩定性之間的平衡,是平臺建設方必須要解決的問題。Kruise Rollout 是 OpenKruise 在漸進式交付領域的新探索,旨在解決應用交付領域的流量排程以及分批部署問題。Kruise Rollout 目前已經正式釋出 v0.1.0 版本,並且與社群 OAM KubeVela 專案進行了整合,vela 使用者可以透過 Addons 快速部署與使用 Rollout 能力。此外,也希望社群使用者能夠加入進來,我們一起在應用交付領域做更多的擴充套件。


-   Github:[**]()

-   Official:[** ]()

-   Slack: Channel in Kubernetes Slack

-   釘釘交流群:


![7.jpeg](~tplv-k3u1fbpfcp-zoom-1.image "7.jpeg")


## 相關連結


[1] OpenKruise:


[**]()


[2] Kruise Rollout:


[*/blob/master/docs/getting_started/introduction.md*](/blob/master/docs/getting_started/introduction.md)


**??戳**[**此處**]() **,檢視 OpenKruise 專案官方主頁與文件!**


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69953029/viewspace-2888911/,如需轉載,請註明出處,否則將追究法律責任。

相關文章