OpenFunction:新一代開源函式計算平臺

語言: CN / TW / HK

作者:

方闐 | OpenFunction Maintainer

霍秉傑 | OpenFunction 發起人

1

概述

無伺服器計算,即通常所說的 Serverless,已經成為當前雲端計算領域的熱門話題與趨勢技術。無伺服器計算是一種契合於當下雲原生生態的開發、執行模式。無伺服器並非不依賴伺服器,而是對開發者而言伺服器被抽象為更精確的算力單元。加州大學伯克利分校在論文 A Berkeley View on Serverless Computing 中提出的關於 Serverless 的觀點——Serverless computing = FaaS + BaaS 被廣泛接受,而 FaaS (函式即服務) 是 Serverless 的核心。

自 AWS Lambda 面世後,各大雲端計算巨頭廠商紛紛投入 Serverless 戰場,爭相推出各自的 Serverless 或 FaaS 平臺。另一方面,開發者不希望被特定廠商繫結的意願也讓開源的 Serverless 專案有了一席之地。如今 OpenFaaS(faas 倉庫 20.3k)、Kubeless(6.7k)、Fission(6.4k)、OpenWhisk(5.4k)、Knative(serving 倉庫 3.9k) 社群已經擁有大量的擁簇與開發者。

那麼為什麼 KubeSphere 社群要做一個自己的 FaaS 專案而不是直接整合現有的主流 Serverless 或 FaaS 框架?或者說現在的 Serverless 市場為什麼還需要 OpenFunction ?

2

Serverless 新願景

根據 CNCF 的雲原生報告可以看出,Kubernetes 在容器編排技術領域擁有絕對的優勢,甚至可以將 Kubernetes 作為雲原生的代名詞。雲原生是目前備受矚目的技術潮流,該領域的創新非常活躍,陸續湧現出了眾多優秀的開源專案(比如 Serverless 領域的 KEDA、Knative 等),並且還將繼續引領技術趨勢。在 Kubernetes 宣佈 1.20 版本將棄用 Docker、不再將其作為預設的容器執行時之後,儘管 Docker 仍然佔據著容器執行時領域最大的份額,但對於雲原生開發者來說,不得不開始著手順應這方面的變化。

與此同時,人們生活方式的變化不斷催生新的業務模式,5G、大資料、邊緣計算、AI 推理、圖資料庫等服務應運而生。這些應用場景不但擴大了 Serverless 的潛在市場,結合雲原生的技術潮流也孵化出很多新的技術,如 Dapr、WebAssembly 等。如何突破現有專案的侷限引入更新更強力的技術,如何抹平執行時之間的差異降低應用的開發成本,逐漸成為了開發者的新煩惱。

3

OpenFunction 專案背景

OpenFunction開源專案連結:

https://github.com/OpenFunction/OpenFunction

OpenFunction 是 KubeSphere 社群發起的開源 FaaS 專案,目前的核心開發人員均來自 KubeSphere 團隊。KubeSphere 社群一直陸續收到社群使用者對 Serverless 或 FaaS 功能的需求,也注意到了社群開發者參與 Serverless 開發的興趣:

KubeSphere 是否有計劃整合 Knative ?我願意參與開發!

KubeSphere 有 FaaS 方面的計劃嗎?是否可以整合 OpenFaaS ?

可否提供日誌告警的功能?這個需求本質上是可自動伸縮的非同步資料處理。

和雲原生一樣,Serverless 是個不容錯失的賽道。僅僅整合現有的 Serverless 或 FaaS 專案還不足以體現 Serverless 這個領域的重要性,於是 KubeSphere 社群從 2020 年下半年開始對 Serverless 領域進行深度調研。經過一段時間的調研後,我們發現:

現有開源 FaaS 專案絕大多數啟動較早,大部分都在 Knative 出現前就已經存在了;

Knative 是一個非常傑出的 Serverless 平臺,但是 Knative Serving 僅僅能執行應用,不能執行函式,還不能稱之為 FaaS 平臺;

Knative Eventing 也是非常優秀的事件管理框架,但是設計有些過於複雜,使用者用起來有一定門檻;

OpenFaaS 是比較流行的 FaaS 專案,但是技術棧有點老舊,依賴於 Prometheus 和 Alertmanager 進行 Autoscaling,在雲原生領域並非最專業和敏捷的做法;

近年來雲原生 Serverless 相關領域陸續湧現出了很多優秀的開源專案如 KEDA、 Dapr、 Cloud Native Buildpacks(CNB)、 Tekton、 Shipwright 等,為建立新一代開源 FaaS 平臺打下了基礎。

綜上所述,我們調研的結論就是: 現有開源 Serverless 或 FaaS 平臺 不能滿足 構建 現代雲原生 FaaS 平臺的要求,而云原生 Serverless 領域的最新進展卻為構建新一代 FaaS 平臺提供了可能。 於是 KubeSphere 社群決定發起 OpenFunction 專案,其目標是構建新一代開源函式計算平臺。

4

開源專案與社群發展

截至 2021 年 8 月, OpenFunction 陸續釋出了 4 個版本,在最新的 v0.3.1 版裡 builder 和 serving 部分已經趨於穩定,並且釋出了 OpenFunction 自己的事件驅動框架 OpenFunction Events。KubeSphere 社群將持續在 OpenFunction 進行投入,最新路線圖詳見 OpenFunction Roadmap (https://github.com/OpenFunction/OpenFunction/blob/main/docs/roadmap.md)。

目前青雲全象低程式碼平臺已經採用 OpenFunction 實現靈活的低程式碼平臺外掛機制;也有來自 Nebula 的社群使用者用 OpenFunction 實現了語音助手;有社群開發者為 OpenFunction 社群貢獻了 NodeJS 版的 Function Framework 和 Builder。隨著專案逐漸成熟,會有越來越多的社群使用者使用 OpenFunction,我們也期待有更多的社群開發者參與進來。

5

OpenFunction FaaS 框架設計詳解

OpenFunction 是一個開源的函式即服務(FaaS)框架,和大多數同類產品一樣,旨在讓使用者專注於他們的業務邏輯,而不必擔心底層執行環境和基礎設施。如下圖所示函式生命週期中幾個重要的部分分別是: 函式框架(Functions framework)、函式構建 (Build)、函式服務 (Serving)和事件驅動框架 (Events Framework),下面我們將分別詳細闡述這幾個重要部分的設計及架構。

OpenFunction 函式生命週期示意圖

函式框架(Functions framework)

在 FaaS 框架中,怎樣將一段函式程式碼轉換為可執行的應用是一個重要的環節。我們知道函式計算之所以降低了開發成本,正是因為函式框架(Functions framework)代替開發者完成了很多與業務無關的工作。不僅如此,函式框架還為開發者提供了應用執行環境中的上下文和語義明確的函式開發擴充套件庫(可以理解為 SDK)。

這部分的設計並不複雜,實現的難點在於如何做到上述的 語義明確功能強大

我們調研了幾種主流的 FaaS 框架(平臺),發現大部分的專案選擇了封裝函式入參的做法,其意圖在於抽象輸入資料的處理方式,即無論請求是什麼格式,都可以使用框架提供的函式擴充套件庫來獲取資料。在這些成熟的案例中,我們發現封裝入參的方式可以使函式在同一個框架內具有很高的靈活性和可擴充套件性。當函式的資料輸入源變更後,函式本身不需要再做對應的入參適配,從而降低了使用者的開發成本。

從這個角度看,封裝入參方式比不封裝(或自定義)入參方式具備更大的潛力。接受了這個設定之後,我們再來看看函式框架的本質。函式框架本質上可以歸納為以下三個作用:

將使用者提供的函式轉換成可以執行的應用;

將使用者函式封裝為一個標準的訪問地址,提供給輸入端;

將輸出端封裝為一個標準的訪問地址,提供給使用者函式。

如果你瞭解過 Dapr,你就會發現後面兩點和 Dapr 的工作原理幾乎一致。Dapr 是一種分散式應用執行時,它以一種優雅的方式簡化了開發者與中介軟體的互動。在 Kubernetes 中,Dapr 可以看作以 Sidecar 的方式實現了函式轉換的功能。那麼是否能用 Dapr 作為 FaaS(Serverless)平臺中的 Functions framework?答案是肯定的。OpenFunction 正是基於 Dapr 提供了一套靈活的 functions framework 機制(其中包含了借鑑 Google functions-framework 處理 HTTP 函式的部分)實現了與各種複雜中介軟體的對接,並搭載兩種執行時——以 Knative serving 為基礎的同步函式執行時,和以 KEDA 結合 Dapr 為基礎的非同步函式執行時 OpenFunctionAsync,以期實現對實際生產中大部分應用場景的覆蓋。

為了能讓這個函式框架真正運作起來,往往還需要藉助一些函式範圍外的配置,用於定義函式和觸發器、資料來源、資料目標之間的關聯關係。我們稱之為函式上下文(OpenFunction Context),理論上它通常具備以下內容:

使用者通用元資料,如使用者 ID、RequestID 等其他上下文資訊;

事件源的定義,如名稱、型別、服務地址、資料型別等;

觸發器的定義,如名稱、型別、觸發規則、觸發週期、執行方式等;

函式的定義,如名稱、監聽地址等;

提供自定義的 key-value 引數,如環境變數,以及用於適配不同的 Runtime 等。

OpenFunction 元件示意圖

函式構建(Build)

我們通常會用 Build 來指代容器映象的打包,但實際上將原始碼打包成映象只是構建工作中的一個步驟,開發者還有諸如拉取程式碼、程式碼預處理、映象上傳等工作需要完成。由此我們將 Build 拆分為兩個主要的功能點,即製作容器映象與建立構建流水線。在調研了 Cloud Native Buildpacks(CNB)、Tekton、Shipwright 等開源專案後,我們最終設計了 OpenFunction Builder CRD, 使用者 提供了一種可以自由選擇 Build 方案的 Build 框架。

Docker 被 Kubernetes 放棄作為預設的容器執行時後,我們在 Kubernetes 中製作容器映象還有多種選擇比如 Kaniko、Buildah、BuildKit 以及 Cloud Native Buildpacks(CNB)。其中前三者均依賴 Dockerfile 去製作容器映象,而 Cloud Native Buildpacks(CNB)是雲原生領域最新湧現出來的新技術,它不依賴於 Dockerfile,而是能自動檢測要 build 的程式碼,並生成符合 OCI 標準的容器映象,已經被 Google Cloud、IBM Cloud、Heroku、Pivotal 等公司採用。

OpenFunction 選擇 Cloud Native Buildpacks(CNB) 作為容器映象製作的預設選擇,陸續也會支援 Kaniko、Buildah、BuildKit 等方式。

Cloud Native Buildpacks(CNB) 的核心是 CNB Lifecycle,它負責將由應用原始碼到映象的構建步驟抽象出來,形成一套標準規範從而完成對整個過程的編排,並最終產出應用映象。這樣一來,開發者就可以將不同邏輯的最小構建單元 buildpack(可以理解為 Dockerfile 中的映象分層) 按自身的需求組合到一起,生成一個構建器(builder),再交由 CNB 處理映象的構建過程。

因為這是一套開源的標準,所以在 OpenFunction Builder 中開發者不但可以選擇 OpenFunction 自身的構建器(builder)來構建映象,還可以選擇任何一種符合 CNB Lifecycle 的構建器,如 Google buildpacks、Paketo buildpacks 等,這意味著使用者可以構建任何語言、型別的應用。

Build 的另一個需求——構建流水線,就需要藉助 Tekton 這樣優秀的流水線工具作為支援。在最開始的版本中,OpenFunction 毫不猶豫地選擇 Tekton 來拆分構建環節的工作,為之前所談到的構建任務在 Tekton 中建立對應的 Task 及 Pipeline 等。

在對 Shipwright 的調研中我們發現 Shipwright 同樣由 Tekton 驅動,並且 Shipwright 將 Tekton 的設計理念帶入了映象構建過程,形成了非常雲原生的映象構建框架,同時也支援使用 Kaniko、Buildah、BuildKit 以及 Cloud Native Buildpacks(CNB)構建映象,並可以通過指定 BuildStrategy 和 ClusterBuildStrategy 在上述四種映象構建方法之間進行切換。

於是我們在 v0.3.0 版本中將原有的 Tekton + Cloud Native Buildpacks 的構建方案切換成了 Shipwright。 OpenFunction Builder 從設計上完美解決了如何在沒有 Dockerfile 的情況下製作容器映象的問題,並且具備了高度自由、雲原生的構建器(構建方案)選擇機制 。無論是使用現成的 Dockerfile 還是僅用一段原始碼,OpenFunction Builder 都可以將其構建為 Open Container Initiative(OCI)標準映象並上傳到指定的倉庫中。

函式服務(Serving)

函式服務 (Serving)指的是如何執行函式 / 應用,以及賦予函式 / 應用基於事件驅動或流量驅動的自動伸縮的能力(Autoscaling)。我們根據這兩個方面設計了負責執行函式 / 應用的 OpenFunction Serving CRD,並將函式分為同步函式和非同步函式。同步函式是指客戶端發出請求後,必須等到函式執行完成並獲取函式執行結果後才返回;非同步函式是指客戶端觸發函式後,無需等待函式執行結束即可返回。

在同步函式方面,Knative Serving 具備了非常出色的自動伸縮機制,OpenFunction 支援 Knative Serving 作為同步函式執行時,未來還將基於 KEDA http-add-on 開發 OpenFunctionSync 同步函式執行時。

在非同步函式方面,我們結合 KEDA 和 Dapr 開發了 OpenFunctionAsync 非同步函式執行時。Dapr 用於解耦函式對各種中介軟體的訪問;KEDA 提供了 ScaledObject 和 ScaledJob 兩種資源,用於根據實際事件源的監控指標自動進行工作負載副本數量的伸縮,它很好地彌補了 Knative Serving 在非 HTTP 驅動源場景中的不足。同時 KEDA 也在持續開發可以處理 HTTP 請求的 http-add-on 專案,這使得 OpenFunction 在後續的演進中具備了更多的選擇,OpenFunction 未來將整合 KEDA http-Add-on 實現不依賴 Knative Serving 的 OpenFunctionSync 執行時。

我們將上面的工作集合起來,即使用 OpenFunction Serving CRD 來管理控制函式執行的整個生命週期。Serving CRD 包含了使用者對函式型別、輸入、輸出端的定義,以及函式例項自動伸縮的定義。OpenFunction Controller 會按照這些定義,生成相應的 Knative Service、Dapr 和 KEDA 元件,其中 Knative Service 負責同步函式的執行與自動伸縮;KEDA 會負責非同步函式的自動伸縮,而 Dapr 會負責非同步函式對接外部輸入 / 輸出。展開來講, Dapr 會將外部的輸入通過 OpenFunction Context 傳遞給 Functions framework,進而傳遞給函式;函式執行完成會通過呼叫 Functions framework 中相應的函式將輸出通過 Dapr 輸出到外部。

事件驅動框架 (Events Framework)

OpenFunction 事件框架示意圖

除了核心的 FaaS 框架之外,OpenFunction 也設計了事件驅動框架以實現對非同步函式的驅動。目前事件框架參考了 Argo Events 與 Knative Eventing 的部分設計,同時避免了引入類似 Knative Eventing 中過於複雜的設計;通過引入 Dapr 解耦了 EventBus 與底層具體 Message Broker 的繫結,進而利用 Dapr 的 binding 和 pubsub 分別對接事件源與 EventBus,以更優雅和可插拔的方式實現了類似 Argo Events 的架構,具備了對事件源的條件判斷、對事件的流轉控制等能力。

本質上來看,事件框架也是一個由事件驅動的工作負載,那麼它本身可以是 Serverless 形式的工作負載嗎?可以用 OpenFunction 的非同步函式來驅動嗎?其實 OpenFunction 社群已將該設計列入路線圖中,目前也已實現部分元件的自驅動能力。

6

OpenFunction 的挑戰

我們從一些關於 Serverless 的報告中可以看出,Serverless 服務有著可觀的市場潛力,未來五年內也許就會達到千億級的市場規模。然而對於 Serverless 技術本身來說,仍有很多待解決的問題,如冷啟動、安全性、可觀測性等等。

OpenFunction 在發展的過程中非常看中趨勢中的技術,相信它們可以帶來活力與變革能力(也許 Wasm 會成為 OpenFunction 的下一個服務執行時)。 將成熟的與新生的技術掰開揉碎和在一起,再穿插進獨立的設計與思考,或許就是 OpenFunction 解決上述問題的後發者優勢 ,當然也是 OpenFunction 當下面臨的挑戰。

7

加入 OpenFunction 社群

期待感興趣的開發者加入 OpenFunction 社群。可以提出任何你對 OpenFunction 的疑問、設計提案與合作提議。

你可以在這裡找到 OpenFunction 的一些典型使用案例:

以 Serverless 的方式實現 Kubernetes 日誌告警

OpenFunction Serverless Samples :https://github.com/OpenFunction/samples

OpenFunction Events Samples:https://github.com/OpenFunction/OpenFunction/blob/main/docs/concepts/OpenFunction-events-framework.md

OpenFunction 官網:https://openfunction.dev/