開源工作流引擎如何支撐企業級 Serverless 架構?

Serverless 應用引擎(SAE)是一款底層基於 Kubernetes,實現了 Serverless 架構與微服務架構結合的雲產品。作爲一款不斷迭代的雲產品,在快速發展的過程中也遇到了許多挑戰。如何在蓬勃發展的雲原生時代中解決這些挑戰,並進行可靠快速的雲架構升級?SAE 團隊和 KubeVela 社區針對這些挑戰開展了緊密合作,並給出了雲原生下的開源可複製解決方案——KubeVela Workflow。

本文將詳細介紹 SAE 使用 KubeVela Workflow 進行架構升級的解決方案,並對多個實踐場景進行一一解讀。

Serverless 時代下的挑戰

Serverless 應用引擎(SAE)是面向業務應用架構、微服務架構的一站式應用託管平臺,是一款底層基於 Kubernetes,實現了 Serverless 架構與微服務架構結合的雲產品。

如上架構圖,SAE 的用戶可以將多種不同類型的業務應用託管在 SAE 之上。而在 SAE 底層,則會通過 JAVA 業務層處理相關的業務邏輯,以及與 Kubernetes 資源進行交互。在最底層,則依靠高可用,免運維,按需付費的彈性資源池。

在這個架構下,SAE 主要依託其 JAVA 業務層爲用戶提供功能。這樣的架構在幫助用戶一鍵式部署應用的同時,也帶來了不少挑戰。

在 Serverless 持續發展的當下,SAE 主要遇到了三大挑戰:

  1. SAE 內部的工程師在開發運維的過程中,存在着一些複雜且非標準化的運維流程。如何自動化這些複雜的操作,從而降低人力的消耗?
  2. 隨着業務發展,SAE 的應用發佈功能受到了大量用戶的青睞。用戶增長的同時也帶來了效率的挑戰,在面對大量用戶高併發的場景下,如何優化已有的發佈功能並提升效率?
  3. 在 Serverless 持續落地於企業的當下,各大廠商都在不斷將產品體系 Serverless 化。在這樣的浪潮下,SAE 應該如何在快速對接內部 Serverless 能力,在上線新功能的同時,降低開發成本?

縱觀上述三個挑戰,不難看出,SAE 需要某種編排引擎來升級發佈功能,對接內部能力以及自動化運維操作。

而這個編排引擎需要滿足以下條件來解決這些挑戰:

  1. 高可擴展。對於這個編排引擎來說,流程中的節點需要具備高可擴展性,只有這樣,才能將原本非標準化且複雜的操作節點化,從而和編排引擎的流程控制能力結合在一起,發揮出 1+1 > 2 的效果,從而降低人力的消耗。
  2. 輕量高效。這種編排引擎必須高效,且生產可用。這樣才能滿足 SAE 在大規模用戶場景下的高併發需求。
  3. 強對接和流程控制能力。這個編排引擎需要能夠快速業務的原子功能,把原本串聯上下游能力的膠水代碼轉換成編排引擎中的流程,從而降低開發成本。

基於上面這些挑戰和思考,SAE 和 KubeVela 社區進行了深度合作,並推出了 KubeVela Workflow 這個項目作爲編排引擎。

爲什麼要用Kubevela Workflow?

得益於雲原生蓬勃的生態發展,社區中已經有許多成熟的工作流項目,如 Tekton,Argo 等。在阿里雲內部,也有一些編排引擎的沉澱。那麼爲什麼要“新造一個輪子”,而不使用已有的技術呢?

因爲 KubeVela Workflow 在設計上有一個非常根本的區別:工作流中的步驟面向雲原生 IaC 體系設計,支持抽象封裝和複用,相當於你可以直接在步驟中調用自定義函數級別的原子能力,而不僅僅是下發容器。

在 KubeVela Workflow 中,每個步驟都有一個步驟類型,而每一種步驟類型,都會對應 WorkflowStepDefinition(工作流步驟定義)這個資源。你可以使用 CUE 語言(一種 IaC 語言,是 JSON 的超集) 來編寫這個步驟定義,或者直接使用社區中已經定義好的步驟類型。

CUE語言: https://cuelang.org/

你可以簡單地將步驟類型定義理解爲一個函數聲明,每定義一個新的步驟類型,就是在定義一個新的功能函數。函數需要一些輸入參數,步驟定義也是一樣的。在步驟定義中,你可以通過 parameter 字段聲明這個步驟定義需要的輸入參數和類型。當工作流開始運行時,工作流控制器會使用用戶傳入的實際參數值,執行對應步驟定義中的 CUE 代碼,就如同執行你的功能函數一樣。

有了這樣一層步驟的抽象,就爲步驟增添了極大的可能性。

  • 如果你希望自定義步驟類型,就如同編寫一個新的功能函數一樣,你可以在步驟定義中直接通過 import 來引用官方代碼包,從而將其他原子能力沉澱到步驟中,包括 HTTP 調用,在多集羣中下發,刪除,列出資源,條件等待,等等。這也意味着,通過這樣一種可編程的步驟類型,你可以輕鬆對接任意系統。如,在 SAE 的場景下,在步驟定義中解決和內部其他原子能力(如 MSE,ACR,ALB,SLS 等等)的對接,再使用工作流的編排能力來控制流程:

  • 如果你只希望使用定義好的步驟,那麼,就如同調用一個封裝好的第三方功能函數一樣,你只需要關心你的輸入參數,並且使用對應的步驟類型就可以了。如,一個典型的構建鏡像場景。首先,指定步驟類型爲 build-push-image,接着,指定你的輸入參數:構建鏡像的代碼來源與分支,構建後鏡像名稱以及推送到鏡像倉庫需要使用的祕鑰信息。
apiVersion: core.oam.dev/v1alpha1
kind: WorkflowRun
metadata:
  name: build-push-image
  namespace: default
spec:
  workflowSpec:
   steps:
    - name: build-push
      type: build-push-image
      properties:
        context:
          git: github.com/FogDong/simple-web-demo
          branch: main
        image: fogdong/simple-web-demo:v1
        credentials:
          image:
            name: image-secret

在這樣一種架構下,步驟的抽象給步驟本身帶來了無限可能性。當你需要在流程中新增一個節點時,你不再需要將業務代碼進行“編譯-構建-打包”後用 Pod 來執行邏輯,只需要修改步驟定義中的配置代碼,再加上工作流引擎本身的編排控制能力,就能夠完成新功能的對接。

而這也是 SAE 中使用 KubeVela Workflow 的基石,在可擴展的基礎之上,才能充分藉助和發揮生態的力量,加速產品的升級。

使用案例

接下來,我們來深入 SAE 中使用 KubeVela Workflow 的場景,從案例中進行更深層的理解

案例 1:自動化運維操作

第一個場景,是 SAE 內部的運維工程師的一個自動化運維場景。

在 SAE 內部有這樣一個場景,我們會編寫並更新一些基礎鏡像,並且需要將這些鏡像預熱到多個不同 Region 的集羣中,通過鏡像預熱,來給使用這些基礎鏡像的用戶更好的體驗。

原本的操作流程非常複雜,不僅涉及到了使用 ACR 的鏡像構建,多個區域的鏡像推送,還需要製作鏡像緩存的模板,並且將這些鏡像緩存推送到不同 Region 的集羣當中。這裏的 Region 包括上海,美西,深圳,新加坡等等。這些操作是非標準化,且非常耗時的。因爲當一個運維需要在本地推送這些鏡像到國外的集羣當中時,很有可能因爲網絡帶寬的問題而失敗。因此,他需要將精力分散到這些原本可以自動化的操作上。

而這也是一個非常適合 KubeVela Workflow 的場景:這些操作裏面的每一個步驟,都可以通過可編程的方式轉換成工作流裏的步驟,從而可以在編排這些步驟的同時,達到可複用的效果。同時,KubeVela Workflow 也提供了一個可視化的 Dashboard,運維人員只需要配置一次流水線模板,之後就可以通過觸發執行,或者在每次觸發執行時傳入特定的運行時參數,來完成流程的自動化。

在這裏,簡化版的步驟如下:

  1. 使用 HTTP 請求步驟類型,通過請求 ACR 的服務來構建鏡像,並通過參數傳遞將鏡像 ID 傳遞給下一個步驟。在該步驟定義中,需要等待 ACR 的服務構建完畢後,才結束當前步驟的執行。
  2. 如果第一步構建失敗了,則進行該鏡像的錯誤處理。
  3. 如果第一步構建成功了,則使用 HTTP 請求步驟來調用鏡像緩存構建的服務,並同時將服務的日誌作爲當前的步驟來源。這裏可以直接在 UI 中查看步驟的日誌以排查問題,
  4. 使用一個步驟組,在裏面分別使用下發資源類型的步驟來進行上海集羣和美西集羣的鏡像預熱:這裏會使用 KubeVela Workflow 的多集羣管控能力,直接在多集羣中下發 ImagePullJob 工作負載,進行鏡像預熱。

上面這個流程中,如果不使用 KubeVela Workflow,你可能需要寫一段業務代碼,來串聯多個服務和集羣。以最後一步,往多集羣中下發 ImagePullJob 工作負載爲例:你不僅需要管理多集羣的配置,還需要 Watch 工作負載(CRD)的狀態,直到工作負載的狀態變成 Ready,才繼續下一步。而這個流程其實對應了一個簡單的 Kubernetes Operator 的 Reconcile 邏輯:先是創建或者更新一個資源,如果這個資源的狀態符合了預期,則結束此次 Reconcile,如果不符合,則繼續等待。

難道我們運維操作中每新增一種資源的管理,就需要實現一個 Operator 嗎?有沒有什麼輕便的方法,可以將我們從複雜的 Operator 開發中解放出來呢?

正是因爲 KubeVela Workflow 中步驟的可編程性,能夠完全覆蓋 SAE 場景中的這些運維操作和資源管理,才能夠幫助工程師們降低人力的消耗。類似上面的邏輯,對應到 KubeVela Workflow 的步驟定義中則非常簡單,不管是什麼類似的資源(或者是一個 HTTP 接口的請求),都可以用類似的步驟模板覆蓋:

template: {
  // 第一步:從指定集羣中讀取資源
  read: op.#Read & {
    value: {
      apiVersion: parameter.apiVersion
      kind: parameter.kind
      metadata: {
        name: parameter.name
        namespace: parameter.namespace
      }
    }
    cluster: parameter.cluster
  }
  // 第二步:直到資源狀態 Ready,才結束等待,否則步驟會一直等待
  wait: op.#ConditionalWait & {
    continue: read.value.status != _|_ && read.value.status.phase == "Ready"
  }
  // 第三步(可選):如果資源 Ready 了,那麼...
  // 其他邏輯...

  // 定義好的參數,用戶在使用該步驟類型時需要傳入
  parameter: {
    apiVersion: string
    kind: string
    name: string
    namespace: *context.namespace | string
    cluster: *"" | string
   }
}

對應到當前這個場景就是:

  1. 第一步:讀取指定集羣(如:上海集羣)中的 ImagePullJob 狀態。
  2. 第二步:如果 ImagePullJob Ready,鏡像已經預熱完畢,則當前步驟成功,執行下一個步驟。
  3. 第三步:當 ImagePullJob Ready 後,清理集羣中的 ImagePullJob。

通過這樣自定義的方式,不過後續在運維場景下新增了多少 Region 的集羣或是新類型的資源,都可以先將集羣的 KubeConfig 納管到 KubeVela Workflow 的管控中後,再使用已經定義好的步驟類型,通過傳入不同的集羣名或者資源類型,來達到一個簡便版的 Kubernetes Operator Reconcile 的過程,從而極大地降低開發成本。

案例 2:優化已有的發佈流程

在自動化內部的運維操作之外,升級原本 SAE 的產品架構,從而提升產品的價值和用戶的發佈效率,也是 SAE 選擇 KubeVela Workflow 的重要原因。

原有架構

在 SAE 的發佈場景中,一次發佈會對應一系列的任務,如:初始化環境,構建鏡像,分批發布等等。這一系列任務對應下圖中的 SAE Tasks。

在 SAE 原本的架構中,這些任務會被有序地扔給 JAVA Executor 來進行實際的業務邏輯,比如,往 Kubernetes 中下發資源,以及與 MySQL 數據庫進行當前任務的狀態同步,等等。

在當前的任務完成後,JAVA Executor 會從 SAE 原本的編排引擎中獲取下一個任務,同時,這個編排引擎也會不斷地將新任務放到最開始的任務列表中。

而這個老架構中最大的問題就在於輪詢調用, JAVA Executor 會每隔一秒從 SAE 的任務列表中進行獲取,查看是否有新任務;同時,JAVA Executor 下發了 Kubernetes 資源後,也會每隔一秒嘗試從集羣中獲取資源的狀態。

SAE 原有的業務架構並不是 Kubernetes 生態中的控制器模式,而是輪詢的業務模式,如果將編排引擎層升級爲事件監聽的控制器模式,就能更好地對接整個 Kubernetes 生態,同時提升效率。

但是在原本的架構中,業務的邏輯耦合較深。如果使用的是傳統的以容器爲基礎下發的雲原生工作流的話,SAE 就需要將原本的業務邏輯打包成鏡像,維護並更新一大堆鏡像製品,這並不是一條可持續發展的道路。我們希望升級後的工作流引擎,能夠輕量地對接 SAE 的任務編排,業務執行層以及 Kubernetes 集羣。

新架構

在藉助了 KubeVela Workflow 的高可擴展性後,SAE 的工程師既不需要將原有的能力重新打包成鏡像,也不需要進行大規模的修改。

新的流程如上圖:SAE 產品側創建了發佈單之後,業務側會將模型寫入數據庫,進行模型轉換,生成一條 KubeVele Workflow,這裏對應到右側的 YAML。

同時,SAE 原本的 JAVA Executor 將原本的業務能力提供成微服務 API。KubeVela Workflow 在執行時,每個步驟都是 IaC 化的,底層實現是 CUE 語言。這些步驟有的會去調用 SAE 的業務微服務 API,有的則會直接與底層 Kubernetes 資源進行交付。而步驟間也可以進行數據傳遞。如果調用出錯了,可以通過步驟的條件判斷,來進行錯誤處理。

這樣一種優化,不僅可擴展,充分複用 K8S 生態,工作流流程和原子能力均可擴展,並且面向終態。這種可擴展和流程控制的相結合,能夠覆蓋原本的業務功能,並且減少開發量。同時,狀態的更新從分支級延遲降低到毫秒級,敏捷且原生,不僅具備了 YAML 級的描述能力,還能將開發效率從 1d 提升到 1h。

案例 3:快速上線新功能

除了自動化運維和升級原本的架構,KubeVela Workflow 還能提供什麼?

步驟的可複用性和與其他生態的易對接性,在升級之外,給 SAE 帶來了額外的驚喜:從編寫業務代碼變爲編排不同步驟,從而快速上線產品的新功能!

SAE 沉澱了大量的 JAVA 基礎,並且支持了豐富的功能,如:支持 JAVA 微服務的單批發布,分批發布,以及金絲雀發佈等等。但隨着客戶增多,一些客戶提出了新的需求,他們希望能有多語言南北流量的灰度發佈能力。

在雲原生蓬勃的生態下,灰度發佈這塊也有許多成熟的開源產品,比如 Kruise Rollout。SAE 的工程師調研後發現,可以使用 Kruise Rollout 來完成灰度發佈的能力,同時,配合上阿里雲的內部的 ingress controller,ALB,來進行不同流量的切分。

這樣一種方案就沉澱成了上面這張架構圖,SAE 下發一條 KubeVela Workflow,Workflow 中的步驟將同時對接阿里雲的 ALB,開源的 Kruise Rollout 以及 SAE 自己的業務組件,並在步驟中完成對批次的管理,從而完成功能的快速上線。

事實上,使用了 KubeVela Workflow 後,上線這個功能就不再需要編寫新的業務代碼,只需要編寫一個更新灰度批次的步驟類型。

由於步驟類型的可編程性,我們可以輕鬆在定義中使用不同的更新策略來更新 Rollout 對象的發佈批次以及對應下發集羣。並且,在工作流中,每個步驟的步驟類型都是可複用的。這也意味着,當你開發新步驟類型時,你也在爲下一次,下下次的新功能上線打下了基礎。這種複用,可以讓你迅速地沉澱功能,極大減少了開發成本。

有了這種高效的編排能力,我們就能進行快速變更,在通用變更的基礎上,如果某客戶需要開啓功能,可以迅速進行自定義變更。

總結

在 SAE 進行了 KubeVela 架構升級後,不僅提升了發佈效率,同時,也降低了開發成本。可以在底層依賴 Serverless 基礎設施的優勢之上,充分發揮產品在應用託管上的優勢。

並且,KubeVela Workflow 在 SAE 中的架構升級方案,也是一個可複製的開源解決方案。社區已經內置提供了 50+ 的步驟類型,包括構建、推送鏡像,鏡像掃描,多集羣部署,使用 Terraform 管理基礎設施,條件等待,消息通知等,能夠幫你輕鬆打通 CICD 的全鏈路。

你還可以參考以下文檔來獲取更多使用場景:

打通 CI/CD:構建鏡像,推送鏡像以及部署資源

https://github.com/kubevela/workflow#try-kubevela-workflow

編排多個 KubeVela Applications

https://github.com/kubevela/workflow/blob/main/examples/multiple-apps.md

一鍵式初始化環境:通過 Terraform 拉起集羣,納入多集羣管控,以及在新集羣中下發資源

https://github.com/kubevela/workflow/blob/main/examples/initialize-env.md

調用指定服務,並通過數據傳遞將返回結果發送通知

https://github.com/kubevela/workflow/blob/main/examples/request-and-notify.md

使用不同的運行時參數來控制資源的部署

https://github.com/kubevela/workflow/blob/main/examples/run-with-template.md

最後

您可以通過如下材料瞭解更多關於 KubeVela 以及 OAM 項目的細節:

作者:董天欣(霧霧)

原文鏈接

本文爲阿里雲原創內容,未經允許不得轉載。

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