Kruise Rollout: 讓所有應用負載都能使用漸進式交付
*作者:趙明山(立衡)*
## 前言
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/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Kruise Rollout:靈活可插拔的漸進式釋出框架UI框架
- 使用 React.js 的漸進式 Web 應用程式(1)ReactJSWeb
- 使用 React.js 的漸進式 Web 應用程式(2)ReactJSWeb
- 漸進式Web應用程式的深入概述Web
- 使用 React.js 的漸進式 Web 應用程式:第 2 部分 – 頁面載入效能ReactJSWeb
- 使用 React.js 的漸進式 Web 應用程式:第 2 部分 - 頁面載入效能ReactJSWeb
- 漸進式Web應用程式(PWA)的深入概述Web
- 漸進式Web應用(PWA)入門教程(下)Web
- 漸進式web應用開發---promise式資料庫(五)WebPromise資料庫
- 使用 Flux,Helm v3,Linkerd 和 Flagger 漸進式交付 KubernetesUX
- 使用 flux2+kustomize+helm+github 進行多叢集 GitOps 雲原生漸進式交付UXGithub
- Kruise Rollout v0.2.0 版本釋出:支援 Gateway API、StatefulSet 分批發布等能力UIGatewayAPI
- 使用 React.js 的漸進式 Web 應用程式:第 1 部分 - 介紹ReactJSWeb
- 漸進式載入 - 基礎講解
- SAP Spartacus - Progressive Web Applications,漸進式 Web 應用程式WebAPP
- 使用Rancher建立負載均衡的容器應用負載
- 使用SQIP工具和交叉點觀察器進行漸進式影像載入
- 使用SQIP工具和交叉點觀察器進行漸進式影象載入
- 漸進式web應用開發-- 使用後臺同步保證離線功能(六)Web
- 在30天內學習漸進式Web應用開發Web
- 使用nginx進行負載均衡Nginx負載
- F5:讓跨雲應用順暢交付
- 漸進式web應用開發---使用indexedDB實現ajax本地資料儲存(四)WebIndex
- Locust 進行分散式負載測試分散式負載
- 漸進式web應用開發--擁抱離線優先(三)Web
- 漸進式web應用開發---service worker 原理及介紹(一)Web
- 2.8 使用資料庫服務管理應用負載資料庫負載
- 使用 haproxy 進行 TCP 負載均衡TCP負載
- 使用 Flux+Flagger+Istio+Kubernetes 實戰 GitOps 雲原生漸進式(金絲雀)交付UXGit
- vuex 漸進式教程Vue
- Blazor WebAssembly 漸進式 Web 應用程式 (PWA) 離線處理資料BlazorWeb
- 漸進式圖片載入:提升前端使用者體驗的藝術前端
- vuex 漸進式教程(一)Vue
- 圖片漸進式載入最佳化實踐指南
- 離散漸進模型(轉載)模型
- 您需要漸進式 Web 應用程式做專案開發的 7 個理由Web
- [譯] 將網站轉換為漸進式 Web 應用程式之簡易教程網站Web
- 基於Vue JS, Webpack 以及Material Design的漸進式web應用 [Part 1]VueJSWebMaterial Design