OpenFunction入門

2022/11/15に公開

OpenFunctionの概要

OpenFunctionはFaaSを構築するためのOSSで、2022/11時点ではCNCFのSandboxプロジェクトになっています。
https://landscape.cncf.io/?group=serverless&item=serverless--installable-platform--openfunction-serverless

アプリケーションのビルド、オートスケーリング、トリガーなどの機能を、daprKnativeなど複数のOSSを活用して実現しています。

もう少し軽量なFaaSとしてのOSSだとFissionなどがあります。

OpenFunctionを試す

OpenFunctionの構築

公式ドキュメントに沿ってローカル環境(kind)にOpenFunctionを構築してみます。
https://openfunction.dev/docs/getting-started/

# Use helm https://helm.sh/
helm repo add openfunction https://openfunction.github.io/charts/
helm repo update

# Install all components
kubectl create namespace openfunction
helm install openfunction openfunction/openfunction -n openfunction --version 0.3.1
# Verify
$ kubectl get po -n openfunction
NAME                                               READY   STATUS    RESTARTS   AGE
openfunction-controller-manager-7cf4b8dbb9-8sztz   2/2     Running   0          3m14s

$ kubectl get po -n dapr-system
NAME                                     READY   STATUS    RESTARTS        AGE
dapr-dashboard-797b56749f-52mrs          1/1     Running   0               5m44s
dapr-operator-7df6df9787-nwd48           1/1     Running   1 (4m20s ago)   5m44s
dapr-placement-server-0                  1/1     Running   2 (4m8s ago)    5m44s
dapr-sentry-6fd7776f6-z2xss              1/1     Running   0               5m44s
dapr-sidecar-injector-59d9fb8755-fk8c5   1/1     Running   0               5m42s

$ kubectl get po -n keda
NAME                                               READY   STATUS    RESTARTS   AGE
keda-operator-6d779f6495-995dd                     1/1     Running   0          6m13s
keda-operator-metrics-apiserver-68447799f9-m6jck   1/1     Running   0          6m12s

$ kubectl get po -n knative-serving
NAME                                      READY   STATUS    RESTARTS   AGE
activator-6787f64478-8j4j5                1/1     Running   0          6m44s
autoscaler-7fc74d5b74-qtpgg               1/1     Running   0          6m44s
controller-777d76ffcf-bxfkn               1/1     Running   0          6m44s
default-domain-h5k4s                      1/1     Running   0          6m44s
domain-mapping-59fbb89fc-rrwdk            1/1     Running   0          6m44s
domainmapping-webhook-84d8bbf76-jz5dn     1/1     Running   0          6m44s
net-contour-controller-66fc467c5b-d9dzx   1/1     Running   0          6m43s
webhook-5d6d699997-h42fx                  1/1     Running   0          6m44s

$ kubectl get po -n shipwright-build
NAME                                           READY   STATUS    RESTARTS   AGE
shipwright-build-controller-5954dff84f-qm6gd   1/1     Running   0          7m1s

$ kubectl get po -n tekton-pipelines
NAME                                           READY   STATUS    RESTARTS   AGE
tekton-pipelines-controller-6f4d68c857-94z9s   1/1     Running   0          7m6s
tekton-pipelines-webhook-57f46d6794-sn4mf      1/1     Running   0          7m7s

多くのリソースが反映されてます。
使わない機能がある場合は、without buildsync runtime onlyなどのオプションがあります。

コンテナイメージをpushするレジストリとしてDocker Hubの情報も登録しておきます。

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

Functionの作成と実行

非同期関数を使う場合はKafkaなどのMQも用意する必要があるため、同期関数を試してみます。
https://openfunction.dev/docs/getting-started/quickstarts/sync-functions/

今回はGoで試してみます。(Node.jsやPython、Javaもある)
https://github.com/OpenFunction/samples/tree/main/functions/knative/hello-world-go

実行される関数はこちら

hello.go
package hello

import (
	"fmt"
	ofctx "github.com/OpenFunction/functions-framework-go/context"
	"net/http"

	"github.com/OpenFunction/functions-framework-go/functions"
)

func init() {
	functions.HTTP("HelloWorld", HelloWorld,
		functions.WithFunctionPath("/{greeting}"))
}

func HelloWorld(w http.ResponseWriter, r *http.Request) {
	vars := ofctx.VarsFromCtx(r.Context())
	fmt.Fprintf(w, "Hello, %s!\n", vars["greeting"])
}

カスタムリソースの用意

function-sample.yaml
apiVersion: core.openfunction.io/v1beta1
kind: Function
metadata:
  name: function-sample
spec:
  version: "v2.0.0"
  image: "ryutoyasugi/sample-go-func:v1"
  imageCredentials:
    name: push-secret
  port: 8080
  build:
    builder: openfunction/builder-go:latest
    env:
      FUNC_NAME: "HelloWorld"
      FUNC_CLEAR_SOURCE: "true"
    srcRepo:
      url: "https://github.com/OpenFunction/samples.git"
      sourceSubPath: "functions/knative/hello-world-go"
      revision: "main"
  serving:
    template:
      containers:
        - name: function
          imagePullPolicy: IfNotPresent 
    runtime: "knative"
# Deploy
kubectl apply -f function-sample.yaml

ビルドされたイメージがレジストリにpushされ、KnativeのリソースができPodが起動しています。(リクエストがない状況が続くとゼロスケールする)

$ kubectl get functions.core.openfunction.io
NAME              BUILDSTATE   SERVINGSTATE   BUILDER         SERVING         ADDRESS                                             AGE
function-sample   Succeeded    Running        builder-kjv2g   serving-lbsv7   http://function-sample.default.svc.cluster.local/   112s

$ kubectl get services.serving.knative.dev
NAME                       URL                                                   LATESTCREATED                   LATESTREADY                     READY   REASON
serving-lbsv7-ksvc-qtzhk   http://serving-lbsv7-ksvc-qtzhk.default.example.com   serving-lbsv7-ksvc-qtzhk-v200   serving-lbsv7-ksvc-qtzhk-v200   True

$ kubectl get po
NAME                                                        READY   STATUS    RESTARTS       AGE
serving-lbsv7-ksvc-qtzhk-v200-deployment-78988b65c9-g6xx2   2/2     Running   0              17s

Internalなアドレスが払い出されているので、Podからリクエストを送って実行してみます。

$ kubectl get function function-sample -o=jsonpath='{.status.addresses}' | jq
[
  {
    "type": "External",
    "value": "http://function-sample.default.ofn.io/"
  },
  {
    "type": "Internal",
    "value": "http://function-sample.default.svc.cluster.local/"
  }
]

$ kubectl run curl --image=radial/busyboxplus:curl -i --tty
[ root@curl:/ ]$ curl http://function-sample.default.svc.cluster.local/World
Hello, World!

まとめ

OpenFunctionをkind上に構築して、Functionの作成・実行まで試しました。
複数のOSSの知識が必要なので使いこなすのは簡単ではないと思いますが、面白い取り組みだと思います。

Discussion