Fission:基於Kubernetes的Serverless函式框架

店家小二發表於2018-12-14

簡單的來講,Fission 是一個構建在 Kubernetes 之上的 FaaS/Serverless 函式框架。

注:Faas 即 Function as a Service 的縮寫

Fission 允許你通過函式輕鬆的在 Kubernetes 上建立 HTTP 服務。它工作在原始碼級別函式和抽象的容器映象之上(大多時候),同時簡化了 Kubernetes 的學習曲線,讓你不用深入瞭解 Kubernetes 就能建立出有用的服務。

通過 Fission CLI,你可以簡單地建立和新增函式,還可以將這些函式關聯到 HTTP 路由、Kubernetes 事件、或者其他觸發器。函式在排程器觸發後被執行,而且函式執行時只消耗 CPU 和記憶體(空閒的函式除了儲存不會消耗任何資源)。Fission 當前支援多種語言,包括 NodeJS 和 Python。

為什麼要在 Kubernetes 上建立一個 FaaS 框架?

基於 Fission 的特性,我們認為有必要讓一個 Faas 框架執行在不同的基礎設施上,包括公有云和專屬雲(on-premise)。但我們不清楚是否應該從無到有來構建,還是可以基於現有的編排系統。後來證明我們不應該從零開始去重複創造諸如叢集管理、排程、網路管理等一系列功能。

藉助強大和快速生長的社群,Kubernetes 提供了一個強大和靈活的編排系統,並有完善的 API 支援。在它上面構建意味著可以將容器編排功能留給 Kubernetes,而 Fission 就專注於 FaaS 特性。

另外,我們不想分離 FaaS 叢集的原因是 FaaS 可以和其它基礎設施很好的結合。比如,FaaS 可能適合做一個小的 REST API,但它需要和其它設施結合來儲存狀態。同時 FaaS 還有一個很好的工作機制,那就是作為事件處理者,用於處理來自儲存、資料庫,甚至 Kubernetes 本身的通知。Kubernetes 是一個讓所有這些設施相互合作的平臺。

部署和使用 Fission

Fission 可以用 kubectl create 命令來安裝:詳情可檢視專案 README(https://github.com/fission/fission#get-and-run-fission-minikube-or-local-cluster) 。

如下是一個如何寫 hello world HTTP 服務的例子:

$ cat > hello.py
 def main(context): print "Hello, world!"

$ fission function create --name hello --env python --code hello.py --route /hello

$ curl http:///hello Hello, world!

Fission 會關心如何將函式載入到容器當中,如何將請求路由過去等等。接下來我們將探討更多的技術細節。

Fission 是怎樣在 Kubernetes 上實現的

最核心的,一個 FaaS 框架必須做好:

  • 將函式轉化為服務
  • 管理這些服務的生命週期

有很多種方法可以達到以上目標,每種方法都需要權衡。框架計算是基於原始碼級別,還是 Docker 映象級別,又或者是兩者之間(類似buildpacks)?一個函式首次執行時間上限是多少?這些選擇都會影響平臺的靈活性、易用性、資源的利用率和消耗,當然還有效能。

打包,原始碼和映象

我們的目標是想讓 Fission 對新手友好。我們選擇基於原始碼級別來計算,所以使用者能避免處理容器映象打包、推送映象到映象中心、管理映象中心證照、映象版本等問題。

然而,容器映象還是最靈活的打包應用的方式,比如,一個純粹的程式碼級別介面是不允許使用者打包二進位制依賴的。

所以,Fission 選擇了一種混合的方法—-容器映象包含函式所需的動態裝載器。這種方法允許大多數使用者純粹從原始碼級別來使用 Fission,但需要時也允許他們自定義容器映象。

在 Fission 中,這些映象被稱作“環境映象”,包含了程式語言(比如說 NodeJS 或者 Python) 所需的執行環境,一系列通用的依賴和為函式準備動態載入器。如果這些依賴滿足使用者所寫的函式,映象無需重新構建,否則,依賴列表需要修改,映象需要重新構建。

這些環境映象只是和 Fission 的特定語言相關,它們給框架提供了一個統一的介面。這樣的設計可以讓 Fission 相對容易地擴充套件到其他語言。

冷啟動效能

Serverless 函式其中一個目標就是函式只在執行時使用 CPU/記憶體資源。這樣優化了函式的資源消耗,但也帶來了從空閒到啟動的效能損耗(冷啟動損耗)。

冷啟動損耗在很多場景下非常重要。特別是互動式應用的場景——就像使用者等待一個 web 或移動應用響應——幾秒的冷啟動延遲是不能接收的。

為了優化冷啟動延遲,Fission 為每個環境保持著一個執行容器池。當一個函式請求進來之後, Fission 不需要部署一個新容器——它只需要選擇一個已經在執行的容器,將函式拷貝到容器當中,將函式動態載入起來,並將請求路由到這個例項即可。對 NodeJS 和 Python 函式來說,這個過程的損耗差不多是 100 毫秒。

Fissin 是怎樣在 Kuberntes 上工作的

如上圖所示,Fission 被設計為一系列的微服務。Controller 負責追蹤函式、HTTP 路由、事件觸發器和環境映象。poolmgr 負責管理空閒的環境容器池、將函式載入到這些容器當中、以及殺死空閒的函式例項。Router 接收 HTTP 請求,並將他們路由到函式例項上,如果需要會向 poolmgr 請求新的例項。

Controller 提供 Fission API,所有其他元件通過關注 controller 來更新。Router 被暴露為 Kubernetes 的服務,可能是 LoadBalancer 型別或 NodePort 型別,依賴於 Kubernetes 叢集在哪裡託管。

當 router 獲得請求,它會查詢快取,看是否有一個路由過去的服務。如果沒有,它會查詢匹配請求的函式,並且向 poolmgr 請求一個新的例項。poolmgr 有一個空閒 pods 池,它會選擇一個 pod,將函式載入進去(將請求傳送到 pod 的容器中),並將 pod 地址返回給 router。Router 將請求代理到這個pod。這個 pod 也會被快取給隨後的請求,如果空閒了好幾分鐘,那就會被殺掉。

注:目前,Fission 對映一個函式到一個容器;自動擴容到多例項還在計劃當中;還計劃加入重用函式 pods 用以託管多函式,特別是對於那種無需隔離的場景。

Fission 的用法

Bots,Webhooks,REST APIs

Fission 是一個不錯的框架,易於構建小的 REST APIs,實現 webhooks,以及為 Slack 等服務編寫聊天機器人(Chatbots)。

以一個簡單的 REST API 為例,我們製作了一個小的留言板(guestbook)應用,它用函式來完成讀寫,結合 redis 來跟蹤狀態。你可以在 Fission GitHub 倉庫中找到該應用。

這個應用包含兩個訪問終端——其中一個是 GET 終端, 它從 redis 快取獲取留言板實體,並將它們轉化為 HTML 輸出;另一個是 POST 終端,它向 redis 快取中新增留言板列表想的新實體。函式所做的就這些而已——不需要管理 Dockerfile,更新 app 只需要簡單地更新 Fission 函式即可。

處理 Kubernetes 事件

Fission 同樣支援基於 Kubernetes watches 來觸發函式。舉個例子,你可以構造一個函式來觀察在特定 namespace 中, 匹配特定 label 的 pod。函式獲取序列化物件,監聽事件,並基於上下文做相應操作(增加/刪除/修改)。

這些事件處理函式可以用來做簡單的監控,比如,無論何時當一個新的服務被加入到叢集當中,你就可以傳送一個 slack 訊息。還有其它更復雜的應用場景,比如寫一個自定義的 controller,來監聽 Kubernetes 的第三方資源。

狀態和路線圖

Fission 當前還是早期的 alpha 版。還沒做好生產使用的準備。我們正在尋找早期的使用者和反饋。

Fission 接下來要做什麼呢?我們在努力使基於 Kubernetes 的 FaaS 更便捷,更容易使用和整合。在接下來的幾個月我們會做這些支援:單元測試、Git 整合、函式監控和日誌聚合。我們同樣在考慮整合其它的事件源。

建立更多的語言環境也在工作當中,當前已經支援 NodeJS、Python、PHP7、.Net、Golang、Ruby。

你也可以在我們的 GitHub issues 和 projects 中查詢當前的路線圖。

本文轉自中文社群-Fission:基於 Kubernetes 的 Serverless 函式框架


相關文章