從同步函數 hello-world-dotnet 開始探索OpenFunction
- 2022 年 4 月 28 日
- 筆記
- Dapr, OpenFunction
OpenFunction[1] 是一個現代化的雲原生 FaaS(函數即服務)框架,它引入了很多非常優秀的開源技術棧,包括 Knative、Tekton、Shipwright、Dapr、KEDA 等,這些技術棧為打造新一代開源函數計算平台提供了無限可能:
- Shipwright 可以在函數構建的過程中讓用戶自由選擇和切換鏡像構建的工具,並對其進行抽象,提供了統一的 API;
- Knative 提供了優秀的同步函數運行時,具有強大的自動伸縮能力;
- KEDA 可以基於更多類型的指標來自動伸縮,更加靈活;
- Dapr 可以將不同應用的通用能力進行抽象,減輕開發分散式應用的工作量。
OpenFunction 最新發布了0.6版本,而且2022 年 4 月 27 日,OpenFunction[1] 順利通過了雲原生計算基金會 CNCF 技術監督委員會(TOC)的投票,正式進入 CNCF 沙箱(Sandbox)託管。OpenFunction 也將真正變成一個由 100% 社區驅動的開源項目。最近我也加入了OpenFunction項目開始規劃dotnet的支援開發,dotnet 框架支援的倉庫[2],目前完成0.1版本的開發。
經過我這2周時間的摸索,本文將會帶領大家快速部署和上手 OpenFunction,並通過一個 demo{hello-world-dotnet} 來體驗同步函數是如何運作的,以便對函數計算有一個感性的認知。
OpenFunction CLI 介紹
OpenFunction 從 0.5 版本開始使用全新的命令行工具 ofn[3] 來安裝各個依賴組件,它的功能更加全面,支援一鍵部署、一鍵卸載以及 Demo 演示的功能。用戶可以通過設置相應的參數自定義地選擇安裝各個組件,同時可以選擇特定的版本,使安裝更為靈活,安裝進程也提供了實時展示,使得介面更為美觀。它支援的組件和其依賴的 Kubernetes 版本如下:
ofn 的安裝參數 ofn install
解決了 OpenFunction 和 Kubernetes 的兼容問題,會自動根據 Kubernetes 版本選擇兼容組件進行安裝,同時提供多種參數以供用戶選擇。
使用 OpenFunction CLI 部署 OpenFunction
有了命令行工具 ofn 之後,OpenFunction 部署起來非常簡單。首先需要安裝 ofn,以 amd64 版本的 Linux 為例,僅需兩步即可:
1、下載 ofn,最新的ofn 是0.5.3
$ wget -c //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的情況下他也不會給重新安裝的,具體可以看下圖。
安裝成功了,之後我們就可以開始運行同步函數了,OpenFunction 還支援非同步函數,這部分今天就不演示了,留作後續在dotnet框架裡面實現了非同步函數的時候再來。
同步函數 demo 示例
OpenFunction 官方倉庫提供了多種語言的同步函數示例[4]:
這裡我們選擇 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: “//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=//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 //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 //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 //serving-wh6hs-ksvc-m7fc9.default.20.239.115.228.sslip.io serving-wh6hs-ksvc-m7fc9-v100 serving-wh6hs-ksvc-m7fc9-v100 True
這個地址是可以直接訪問的
訪問這個函數時會自動觸發運行一個 Pod:
這個 Pod 使用的鏡像就是之前 build 階段構建的鏡像。事實上這個 Pod 是由 Deployment 控制的,在沒有流量時,這個 Deployment 的副本數是 0。當有新的流量進入時,會先進入 Knative 的 Activator,Activator 接收到流量後會通知 Autoscaler(自動伸縮控制器),然後 Autoscaler 將 Deployment 的副本數擴展到 1,最後 Activator 會將流量轉發到實際的 Pod 中,從而實現服務調用。這個過程也叫冷啟動。
如果你不再訪問這個入口,過一段時間之後,Deployment 的副本數就會被收縮為 0:
通過上面的示例,相信大家應該能夠體會到一些函數計算的優勢,我們只需要專註於業務開發,編寫函數程式碼,並上傳到程式碼倉庫,其他的東西不需要關心,就連Dockerfile都不需要編寫,不需要了解基礎設施,甚至不需要知道容器和 Kubernetes 的存在。函數計算平台會自動為您分配好計算資源,並彈性地運行任務,只有當您需要訪問的時候,才會通過擴容來運行任務,其他時間並不會消耗計算資源,可以充分利用dotnet在雲原生時代的優勢,使用dotnet寫函數是很高效的,大家可以體驗一下我上面的示例//serving-wh6hs-ksvc-m7fc9.default.20.239.115.228.sslip.io 。OpenFunction基於Dapr 所提供的各種分散式能力,讓我們輕鬆的實現無服務微服務架構,獲得像Azure 容器應用[7] 一樣的能力。
相關鏈接
[1] openFunction: //github.com/OpenFunction/OpenFunction
[2] functions-framework-dotnet: //github.com/OpenFunction/functions-framework-dotnet
[3] ofn: //github.com/OpenFunction/cli
[4] OpenFunction 官方倉庫提供了多種語言的同步函數示例: //github.com/OpenFunction/samples/tree/main/functions/knative
[5] Docker Hub: //hub.docker.com/
[6] Quay.io: //quay.io/
[7] Azure 容器應用: //www.cnblogs.com/shanyou/p/15509042.html