Higress & Kruise Rollout: 漸進式交付爲應用發佈保駕護航

作者:揚少

前言

在業務高速發展過程中,如何最大化保障功能迭代過程中業務流量無損一直是開發者比較關心的問題。通常在應用發佈新功能階段,我們會採用灰度發佈的思想對新版本進行小流量驗證,在符合預期之後再進行全量發佈,這就是"漸進性交付"。該詞最早起源於大型、複雜的工業化項目,它試圖將複雜的項目進行分階段拆解,通過持續進行小型閉環迭代降低交付成本和時間。隨着雲原生架構不斷髮展,漸進性交付被廣泛應用在互聯網業務應用中,開發者通過GitOps、CI/CD方式集成漸進式交付框架,讓新功能交付以流水線的方式分批執行,利用A/B 測試、金絲雀發佈等技術精細化控制每一批次的流量策略,充分保障應用發佈的穩定性。

什麼是Higress

Higress 是一款標準化、高集成、易擴展、熱更新的雲原生網關。

Higress 源自阿里巴巴內部電商、交易等核心生產場景的實踐沉澱,遵循 Ingress/Gateway API 標準,將流量網關、微服務網關、安全網關三合一,並在此基礎上擴展了服務管理插件、安全類插件和自定義插件,高度集成 K8s 和微服務生態,包括 Nacos 註冊和配置、Sentinel 限流降級等能力,並支持規則變更毫秒級生效等熱更新能力。

1.png

更多關於 Higress 的介紹,可以參閱Higress官網 [ 1]

什麼是Kruise Rollout

Kruise Rollout 是阿里雲開源的雲原生應用自動化管理套件 OpenKruise 在漸進式交付領域的新嘗試,支持配合流量和實例灰度的金絲雀發佈、藍綠髮布、A/B Testing 發佈,以及發佈過程能夠基於 Prometheus Metrics 指標自動化分批與暫停,並提供旁路的無感對接、兼容已有的多種工作負載(Deployment、CloneSet、DaemonSet)。

這裏,熟悉 Kubernetes 的小夥伴可以會疑惑,官方的 Deployment 工作負載不是有控制發佈的策略嗎?我們爲什麼還需要 Kruise Rollout 呢?

首先,Kubernetes 官方的 Deployment 中定義發佈策略嚴格上不符合漸進性交付的思想,它實際是滾動發佈。雖然 Deployment 對於升級而言提供了 maxUnavailable 和 maxSurge 兩個參數,但是本質上來講 Deployment 它只支持流式的一次性發布,用戶並不能控制分批以及精細化的流量策略。比如用戶無法嚴格控制新老版本之間的流量比例,只能根據實際 Pod 數量佔比以及調用端的負載均衡策略;用戶無法做 A/B testing 策略,例如限制公司內部員工可以訪問新版本。當新版本出現問題,只能重新執行一遍滾動發佈切回老版本,這樣不僅回滾速度慢,而且頻繁線上變更本身就具有極高的不穩定因素。

再者,Kubernetes 只提供了應用交付的 Deployment 控制器,以及針對流量的 Ingress、Service 抽象,但是如何將上述實現組合成開箱即用的漸進式交付方案,Kubernetes 並沒有出標準的定義。

出於以上問題和考量,阿里雲開始發起對漸進式領域的探索,結合多年來容器化、雲原生的技術沉澱,推出了無侵入、可擴展、高易用的漸進式交付框架 Kruise Rollout。

Higress & Kruise Rollout工作機制

簡單介紹一下 Higress 和 Kruise Rollout 在一次應用發佈過程中的工作機制。

2.png

這裏,假設集羣中有一個 Deployment 應用A,通過 Higress 網關對外暴露提供服務。應用A由於業務發展,需要發佈新功能。

1.用戶首先在集羣中添加漸進性交付策略(Rollout CRD資源),描述目標工作負載的交付策略,比如批次,每一批次的流量控制,以及關聯的 Service 資源和 Ingress 資源。

2.應用A發佈新版本,用戶修改集羣上中目標Deployment的Pod模板中容器鏡像爲新版本。

3.Kruise Rollout通過hook方式參與到Deployment滾動發佈流程,修改Deployment的Pause來暫停滾動發佈過程。

4.執行第一次批次發佈,根據Rollout CRD資源描述的交付策略,控制新版本的Pod數量,同時爲正式Ingress資源生成對應的灰度Ingress資源,並配置灰度流量策略,比如流量權重比或者根據請求內容Header進行流量分發。Higress監聽到Ingress資源變化,實時動態修改路由規則,滿足灰度規則的流量被分發到新版本。

5.通過Prometheus等監控手段觀察應用流量的指標信息,驗證新版本是否符合預期。

a.如果符合預期,觸發下一次批次發佈,重複執行步驟4

b.如果不符合預期,觸發回滾,新發布的Pod下線,灰度已下線的部分老版本的Pod,Ingress資源自動下線灰度規則,Higress實時修改路由規則,確保流量只訪問老版本服務。

整個 Rollout 過程,自動整合Deployment、Service、Ingress一起工作,並向用戶屏蔽底層資源變化。這是與現有工作負載能力的一種協同,它儘量複用工作負載的能力,又做到了非 Rollout 過程的零入侵。

實戰:金絲雀發佈

01:什麼是金絲雀發佈

金絲雀發佈的思想是將少量的請求引流到新版本上,因此部署新版本服務只需極小數的機器。驗證新版本符合預期後,逐步調整流量權重比例,使得流量慢慢從老版本遷移至新版本,期間可以根據設置的流量比例,對新版本服務進行擴容,同時對老版本服務進行縮容,使得底層資源得到最大化利用。

如圖,某服務當前版本爲v1,現在新版本v2要上線。爲確保流量在服務升級過程中平穩無損,採用金絲雀發佈方案,逐步將流量從老版本遷移至新版本。

3.png

02:基於Higress & Kruise Rollout實踐金絲雀發佈

假設集羣中有一個服務demo,通過Higress網關對外提供服務。

如何安裝Higress,請參閱Higress快速開始 [ 2]

如何安裝Kruise Rollout,請參閱安裝Kruise Rollout [ 3]

apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo
spec:
  replicas: 5
  selector:
    matchLabels:
      app: demo
  template:
    metadata:
      labels:
        app: demo
    spec:
      containers:
      - name: main
        image: registry.cn-hangzhou.aliyuncs.com/mse-ingress/version:v1
        imagePullPolicy: Always
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: demo
spec:
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP
    name: http
  selector:
    app: demo
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: demo
  annotations:
    kubernetes.io/ingress.class: nginx
spec:
  rules:
  - http:
      paths:
      - backend:
          service:
            name: demo
            port:
              number: 80
        path: /version
        pathType: Exact

現在,服務demo需要發佈新版本。在修改應用鏡像之前,我們需要爲服務demo定義金絲雀發佈策略,以達到漸進式發佈的效果。

apiVersion: rollouts.kruise.io/v1alpha1
kind: Rollout
metadata:
  name: rollouts-demo
spec:
  objectRef:
    workloadRef:
      apiVersion: apps/v1
      kind: Deployment
      name: demo
  strategy:
    canary:
      steps:
      - weight: 10
        pause: {}
        replicas: 1
      - weight: 30
        pause: {}
        replicas: 2
      trafficRoutings:
      - service: demo
        type: nginx
        ingress:
          name: demo
  • 其中workloadRef 旁路式的選擇需要 Rollout 的 Workload,此處爲Deployment,支持其他Workload(如CloneSet、DaemonSet)。

  • 其中canary.Steps 定義了整個 Rollout 過程一共分爲3批,其中第一批只灰度一個新版本 Pod,並且 routing 10% 流量到新版本 Pod,並且需要人工確認是否繼續發佈;第二批只灰度兩個新版本Pod,並且routing 30%流量到新版本Pod,並且需要人工確認是否繼續發佈;最後一批,無需定義,即全量發佈。

  • 其中trafficRoutings指向了需要感知流量規則的資源,kruise rollout會自動更新相關資源,實時反射目標流量規則。

修改服務A的Deployment中鏡像爲registry.cn-hangzhou.aliyuncs.com/mse-ingress/version:v2,觀察相關資源變化。

查看rollout資源狀態,發現當前執行完第一批發布,並且出於暫停狀態,需要人工確認才能繼續下一批次發佈。

4.png

查看pod狀態,發現新版本pod只有一個,Deployment資源沒有全部滾動發佈。

5.png

查看Ingress的解析IP (即Higress網關對外的公網IP地址)。

6.png

測試流量,發現有10%流量訪問新版本。

7.png

繼續第二批次發佈,查看當前Pod狀態,發現新版本Pod有兩個。

如何安裝kubectl-kruise,請參閱**安裝kubectl-kruise [ 4] **。

8.png

測試流量,觀察流量分配比。

9.png

發佈最後一批,完成全量發佈。

10.png

測試流量,發現流量全部轉發至新版本。至此,我們通過小流量的方式逐步將流量從老版本遷移至新版本。

11.png

實戰:A/B Testing

01:什麼是A/B Testing

相比於基於權重方式的金絲雀發佈,A/B測試基於用戶請求的元信息將流量路由到新版本,這是一種基於請求內容匹配的灰度發佈策略。只有匹配特定規則的請求才會被引流到新版本,常見的做法包括基於Http Header和Cookie。基於Http Header方式的例子,例如User-Agent的值爲Android的請求 (來自安卓系統的請求)可以訪問新版本,其他系統仍然訪問舊版本。基於Cookie方式的例子,Cookie中通常包含具有業務語義的用戶信息,例如普通用戶可以訪問新版本,VIP用戶仍然訪問舊版本。

如圖,某服務當前版本爲v1,現在新版本v2要上線。希望安卓用戶可以嚐鮮新功能,其他系統用戶保持不變。

12.png

通過在監控平臺觀察舊版本與新版本的成功率、RT對比,當新版本整體服務預期後,即可將所有請求切換到新版本v2,最後爲了節省資源,可以逐步下線到舊版本v1。

13.png

02:基於Higress & Kruise Rollout實踐A/B Testing

我們仍然利用上面的例子,服務A初始鏡像爲v1。現在,服務demo需要發佈新版本。在修改應用鏡像之前,我們需要爲服務demo定義A/B Testing 策略,以達到漸進式發佈的效果。

apiVersion: rollouts.kruise.io/v1alpha1
kind: Rollout
metadata:
  name: rollouts-header
spec:
  objectRef:
    workloadRef:
      apiVersion: apps/v1
      kind: Deployment
      name: demo
  strategy:
    canary:
      steps:
      - matches:
        - headers:
          - name: user-agent
            value: android
        pause: {}
        replicas: 1
      trafficRoutings:
      - service: demo
        ingress:
          classType: nginx
          name: demo

其中canary.Steps 定義了整個 Rollout 過程一共分爲2批,其中第一批只灰度一個新版本 Pod,並且將帶有HTTP Header user-agent: android (即安卓用戶)的流量routing 到新版本 Pod,並且需要人工確認是否繼續發佈;最後一批,無需定義,即全量發佈。

修改服務A的Deployment中鏡像爲registry.cn-hangzhou.aliyuncs.com/mse-ingress/version:v2,觀察相關資源變化。

查看rollout資源狀態,發現當前執行完第一批發布,並且出於暫停狀態,需要人工確認才能繼續下一批次發佈。

14.png

查看pod狀態,發現新版本pod只有一個,Deployment資源沒有全部滾動發佈。

15.png

測試來自安卓的流量是否路由到新版本,非安卓的流量是否路由到老版本。

16.png

發佈最後一批,完成全量發佈。並測試所有流量是否路由到新版本。

17.png

總結

相比於傳統人工手動方式,Higress & Kruise Rollouts提供了無侵入、自動化運維方式讓應用發佈絲滑般順暢。開發者無需關注發佈過程中如何調整Deployment、Ingress、Service等資源,只需聲明並管理髮布策略Rollouts資源即可,原生Deployment的滾動發佈會自動實現爲漸進式交付,讓應用發佈可批次、可灰度、可回滾,助力業務快速迭代發展同時,也提高了應用發佈的穩定性和效率問題。

01:Higress 社區

Higress項目處於開源初期,我們在兼容好現有 Ingress 標準的基礎上,會重點發力下一代的Ingress 標準 Gateway API,利用 Gateway API 帶來的契機打通南北向與東西向的全域流量調度,幫助用戶使用一套架構架構同時管理外部與內部流量,降低部署運維成本、提升開發及運維效率。歡迎更多的用戶參與到Higress社區,貢獻一份文檔、提交一段代碼,您就有可能成爲 Higress  的第一批 Contributor 甚至 Committer。目前,我們建立了1個釘羣和1個微信羣,加入我們,聯繫羣主或羣管,共建雲原生網關吧。

18.png

02:OpenKruise 社區

OpenKruise是阿里巴巴從容器化轉向雲原生化過程中,在雲原生應用管理方面的最佳實踐經驗,除本文涉及的Kruise Rollout外,OpenKruise還提供了諸多雲原生應用管理相關的能力,如:增強的工作負載、Sidecar容器管理、彈性拓撲管理等。目前OpenKruise上面託管着阿里集羣上百萬的Pod,包含:有狀態、無狀態、通用類型的Sidecar Aagent。

最後,歡迎感興趣的同學加入下面的社區釘釘羣,我們大家一起討論雲原生應用管理相關的需求與技術。

19.png

相關鏈接

[1] Higress官網:

https://higress.io/zh-cn/

[2] Higress快速開始:

https://higress.io/zh-cn/docs/user/quickstart.html

[3] 安裝Kruise Rollout:

https://github.com/openkruise/rollouts/blob/master/docs/getting_started/installation.md

[4] 安裝kubectl-kruise:

https://github.com/openkruise/kruise-tools/blob/master/README.md

點擊此處進入Higress官網

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章