從同步函式 hello-world-dotnet 開始探索OpenFunction

張善友發表於2022-04-28

OpenFunction[1] 是一個現代化的雲原生 FaaS(函式即服務)框架,它引入了很多非常優秀的開源技術棧,包括 Knative、Tekton、Shipwright、Dapr、KEDA 等,這些技術棧為打造新一代開源函式計算平臺提供了無限可能:

  • Shipwright 可以在函式構建的過程中讓使用者自由選擇和切換映象構建的工具,並對其進行抽象,提供了統一的 API;
  • Knative 提供了優秀的同步函式執行時,具有強大的自動伸縮能力;
  • KEDA 可以基於更多型別的指標來自動伸縮,更加靈活;
  • Dapr 可以將不同應用的通用能力進行抽象,減輕開發分散式應用的工作量。

image

OpenFunction 最新發布了0.6版本,而且2022 年 4 月 27 日,OpenFunction[1] 順利通過了雲原生計算基金會 CNCF 技術監督委員會(TOC)的投票,正式進入 CNCF 沙箱(Sandbox)託管。OpenFunction 也將真正變成一個由 100% 社群驅動的開源專案。最近我也加入了OpenFunction專案開始規劃dotnet的支援開發,dotnet 框架支援的倉庫[2],目前完成0.1版本的開發。

從同步函式 hello-world-dotnet 開始探索OpenFunction

經過我這2周時間的摸索,本文將會帶領大家快速部署和上手 OpenFunction,並通過一個 demo{hello-world-dotnet} 來體驗同步函式是如何運作的,以便對函式計算有一個感性的認知。

OpenFunction CLI 介紹

OpenFunction 從 0.5 版本開始使用全新的命令列工具 ofn[3] 來安裝各個依賴元件,它的功能更加全面,支援一鍵部署、一鍵解除安裝以及 Demo 演示的功能。使用者可以通過設定相應的引數自定義地選擇安裝各個元件,同時可以選擇特定的版本,使安裝更為靈活,安裝程式也提供了實時展示,使得介面更為美觀。它支援的元件和其依賴的 Kubernetes 版本如下:

image

ofn 的安裝引數 ofn install 解決了 OpenFunction 和 Kubernetes 的相容問題,會自動根據 Kubernetes 版本選擇相容元件進行安裝,同時提供多種引數以供使用者選擇。

image

使用 OpenFunction CLI 部署 OpenFunction

有了命令列工具 ofn 之後,OpenFunction 部署起來非常簡單。首先需要安裝 ofn,以 amd64 版本的 Linux 為例,僅需兩步即可:

1、下載 ofn,最新的ofn 是0.5.3

$ wget -c  https://github.com/OpenFunction/cli/releases/download/v0.5.3/ofn_linux_amd64.tar.gz -O - | tar –xz

2、為 ofn 賦予許可權並移動到 /usr/local/bin/ 資料夾下。

$ chmod +x ofn && mv ofn /usr/local/bin/

安裝好 ofn 之後,僅需一步即可完成 OpenFunction 的安裝。雖然使用 --all 選項可以安裝所有元件,也可以選擇安裝指定需要安裝的元件,我們的叢集裡面已經安裝了Dapr的情況下,我們就不想額外安裝一遍Dapr ,不過如果叢集裡面已經安裝了Dapr的情況下他也不會給重新安裝的,具體可以看下圖。

image

安裝成功了,之後我們就可以開始執行同步函式了,OpenFunction 還支援非同步函式,這部分今天就不演示了,留作後續在dotnet框架裡面實現了非同步函式的時候再來。

同步函式 demo 示例

OpenFunction 官方倉庫提供了多種語言的同步函式示例[4]

image

這裡我們選擇 dotnet 的函式示例,先來看一下最核心的部署清單:

apiVersion: core.openfunction.io/v1beta1
kind: Function
metadata:
   name: dotnet-sample
   namespace: default
spec:
   version: "v1.0.0"
   image: "geffzhang/sample-dotnet-func:v1"
   imageCredentials:
     name: push-secret
   port: 8080 # default to 8080
   build:
     builder: "openfunction/gcp-builder:v1"
     env:
       GOOGLE_FUNCTION_TARGET: "helloworld"
       GOOGLE_FUNCTION_SIGNATURE_TYPE: "http"
     srcRepo:
       url: "https://github.com/openfunction/samples.git"
       sourceSubPath: "functions/knative/hello-world-dotnet"
       revision: "release-0.6"
   serving:
     runtime: "knative" # default to knative
     template:
       containers:
         - name: function
           imagePullPolicy: IfNotPresent

Function 是由 CRD 定義的一個 CR,用來將函式轉換為最終執行的應用。這個例子裡面包含了兩個元件:

  • build : 通過 Shipwright 選擇不同的映象構建工具,最終將應用構建為容器映象;
  • Serving : 通過 Serving CRD 將應用部署到不同的執行時中,可以選擇同步執行時或非同步執行時。這裡選擇的是同步執行時 knative。

執行這個示例之前,需要在執行函式的名稱空間下建立Secret ,生成一個Secret 來訪問您的容器登錄檔,例如Docker Hub[5]Quay.io[6] 上的一個。這一點非常重要,不然就在Build 階段就失敗了

REGISTRY_SERVER您可以通過編輯以下命令中的REGISTRY_USER和欄位來建立此金鑰REGISTRY_PASSWORD,然後執行它。

REGISTRY_SERVER=https://index.docker.io/v1/ REGISTRY_USER= < your_registry_user > REGISTRY_PASSWORD= < your_registry_password >
kubectl create secret –n default docker-registry push-secret \
     --docker-server= $REGISTRY_SERVER \
     --docker-username= $REGISTRY_USER \
     --docker-password= $REGISTRY_PASSWORD


然後將上面的部署清單儲存為function-dotnet-sample.yaml ,修改spec.image 欄位為您自己的容器登錄檔地址,使用以下命令建立此函式:

kubectl apply –f  function-dotnet-sample.yaml

在Build 階段,builder會啟動一個 Pod 來構建映象,這個 Pod 中包含了 4 個容器:

  • step-source-default : 拉取原始碼;
  • step-prepare : 設定環境變數;
  • step-create : 構建映象;
  • step-results : 輸出映象的 digest。


您可以使用以下命令觀察函式的過程。

kubectl get functions -n default

NAME              BUILDSTATE   SERVINGSTATE   BUILDER         SERVING         URL                                              AGE
dotnet-sample     Succeeded    Running        builder-hf74t   serving-wh6hs   http://openfunction.io/default/dotnet-sample     54m

URL是OpenFunction Domain提供的可以訪問的地址。要通過此 URL 地址訪問該功能,您需要確保 DNS 可以解析此地址。使用以下命令在叢集中建立一個 pod,並從該 pod 訪問該功能

kubectl run  curl --image=radial/busyboxplus:curl -i –tty

[ root@curl:/ ]$ curl http://openfunction.io.svc.cluster.local/default/dotnet-sample/

還可以通過 Knative Services 提供的訪問地址觸發該功能

kubectl get ksvc

geffzhang@edgevm1:~/openfunctionsamples/functions/knative/hello-world-dotnet$ sudo kubectl get ksvc
NAME                       URL                                                               LATESTCREATED                   LATESTREADY                     READY   REASON
serving-wh6hs-ksvc-m7fc9   http://serving-wh6hs-ksvc-m7fc9.default.20.239.115.228.sslip.io   serving-wh6hs-ksvc-m7fc9-v100   serving-wh6hs-ksvc-m7fc9-v100   True

這個地址是可以直接訪問的

image

訪問這個函式時會自動觸發執行一個 Pod:

image

這個 Pod 使用的映象就是之前 build 階段構建的映象。事實上這個 Pod 是由 Deployment 控制的,在沒有流量時,這個 Deployment 的副本數是 0。當有新的流量進入時,會先進入 Knative 的 Activator,Activator 接收到流量後會通知 Autoscaler(自動伸縮控制器),然後 Autoscaler 將 Deployment 的副本數擴充套件到 1,最後 Activator 會將流量轉發到實際的 Pod 中,從而實現服務呼叫。這個過程也叫冷啟動

如果你不再訪問這個入口,過一段時間之後,Deployment 的副本數就會被收縮為 0:

image


通過上面的示例,相信大家應該能夠體會到一些函式計算的優勢,我們只需要專注於業務開發,編寫函式程式碼,並上傳到程式碼倉庫,其他的東西不需要關心,就連Dockerfile都不需要編寫,不需要了解基礎設施,甚至不需要知道容器和 Kubernetes 的存在。函式計算平臺會自動為您分配好計算資源,並彈性地執行任務,只有當您需要訪問的時候,才會通過擴容來執行任務,其他時間並不會消耗計算資源,可以充分利用dotnet在雲原生時代的優勢,使用dotnet寫函式是很高效的,大家可以體驗一下我上面的示例http://serving-wh6hs-ksvc-m7fc9.default.20.239.115.228.sslip.io 。OpenFunction基於Dapr 所提供的各種分散式能力,讓我們輕鬆的實現無服務微服務架構,獲得像Azure 容器應用[7] 一樣的能力。


相關連結

[1] openFunction: https://github.com/OpenFunction/OpenFunction

[2] functions-framework-dotnet: https://github.com/OpenFunction/functions-framework-dotnet

[3] ofn: https://github.com/OpenFunction/cli

[4] OpenFunction 官方倉庫提供了多種語言的同步函式示例:  https://github.com/OpenFunction/samples/tree/main/functions/knative

[5] Docker Hub: https://hub.docker.com/

[6] Quay.io: https://quay.io/

[7] Azure 容器應用: https://www.cnblogs.com/shanyou/p/15509042.html

相關文章