🏰

OpenFaaSをKinD上に構築する

2022/11/21に公開

はじめに

Dockerコンテナをノードとして使用して、ローカルのKubernetesクラスターを簡易的に実行するためのKinD(Kubernetes in Docker)というツールがあるらしい。以前OpenFaasをK3sで作ったKubernetesクラスタ上に構築したが、同じことをKinDでもやってみたい。この記事もあらたか元記事を再利用していて、エコである。
https://zenn.dev/haccht/articles/90cba532a0e458

検証環境
Ubuntu 22.04
Docker 20.10.21
kind v0.17.0
OpenFaaS 0.15.4

必要なバイナリファイルをインストールする

kind, kubectl, helm, faas-cliなど複数のツールを利用する。今回はarkadeを利用して簡単にインストールしておく。

$ export PATH=$HOME/.arkade/bin:$PATH
$ curl -SLsf https://dl.get-arkade.dev/ | sudo sh

$ arkade get kind
$ arkade get kubectl
$ arkade get helm
$ arkade get faas-cli

KinD Kubernetesクラスタを構築

OpenFaasで自分のFunctionを作成・登録する場合、ローカルレジストリがあった方が何かと都合がよい。まずはdockerコンテナでレジストリを作成しておく。

$ export reg_name='kind-registry'
$ export reg_port='5000'
$ docker run -d --restart=always -p "${reg_port}:5000" --name "${reg_name}" registry:2

KinDでKubernetesクラスタを作成する。
このとき上記で作成したローカルレジストリをミラーとして参照できるようあわせて登録する。

$ cat <<EOF | kind create cluster --name openfaas --config -
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  extraPortMappings:
  - containerPort: 30080
    hostPort: 8080
    listenAddress: "0.0.0.0"
    protocol: TCP
containerdConfigPatches:
- |-
  [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"]
    endpoint = ["http://${reg_name}:${reg_port}"]
EOF
Creating cluster "openfaas" ...
 ✓ Ensuring node image (kindest/node:v1.25.3) 🖼
 ✓ Preparing nodes 📦
 ✓ Writing configuration 📜
 ✓ Starting control-plane 🕹️
 ✓ Installing CNI 🔌
 ✓ Installing StorageClass 💾
Set kubectl context to "kind-openfaas"
You can now use your cluster with:

kubectl cluster-info --context kind-openfaas

Not sure what to do next? 😅  Check out https://kind.sigs.k8s.io/docs/user/quick-start/

$ kubectl version
WARNING: This version information is deprecated and will be replaced with the output from kubectl version --short.  Use --output=yaml|json to get the full version.
Client Version: version.Info{Major:"1", Minor:"24", GitVersion:"v1.24.2", GitCommit:"f66044f4361b9f1f96f0053dd46cb7dce5e990a8", GitTreeState:"clean", BuildDate:"2022-06-15T14:22:29Z", GoVersion:"go1.18.3", Compiler:"gc", Platform:"linux/amd64"}
Kustomize Version: v4.5.4
Server Version: version.Info{Major:"1", Minor:"25", GitVersion:"v1.25.3", GitCommit:"434bfd82814af038ad94d62ebe59b133fcb50506", GitTreeState:"clean", BuildDate:"2022-10-25T19:35:11Z", GoVersion:"go1.19.2", Compiler:"gc", Platform:"linux/amd64"}

$ kubectl cluster-info --context kind-openfaas
Kubernetes control plane is running at https://127.0.0.1:35205
CoreDNS is running at https://127.0.0.1:35205/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

$ docker network connect "kind" "${reg_name}"
$ cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
  name: local-registry-hosting
  namespace: kube-public
data:
  localRegistryHosting.v1: |
    host: "localhost:${reg_port}"
    help: "https://kind.sigs.k8s.io/docs/user/local-registry/"
EOF

なお、K3sでOpenFaaSを構築した時にはserviceType=LoadBalancerを指定して外部からサービスを参照できるようにしていた。KinDではその性質上LoadBalancerが利用できないため、NodePortでポート転送できるよう事前にextraPortMappingを作成している。

HelmチャートでOpenFaaSインストール

Kuberntets上でOpenFaaSそのものはopenfaasというnamespaceに、deployしたFunctionはopenfaas-fnというnamescaceに作成する。これらのnamespaceを事前に作成しておく。

$ kubectl apply -f https://raw.githubusercontent.com/openfaas/faas-netes/master/namespaces.yml

OpenFaaSをインストールする。

$ helm repo add openfaas https://openfaas.github.io/faas-netes/
$ helm repo update
$ helm install openfaas openfaas/openfaas \
     --namespace openfaas \
     --set functionNamespace=openfaas-fn \
     --set generateBasicAuth=true

# しばらく待つ
$ kubectl -n openfaas get deployments -l "release=openfaas, app=openfaas"
NAME                READY   UP-TO-DATE   AVAILABLE   AGE
alertmanager        1/1     1            1           32m
basic-auth-plugin   1/1     1            1           32m
gateway             1/1     1            1           32m
nats                1/1     1            1           32m
prometheus          1/1     1            1           32m
queue-worker        1/1     1            1           32m

OpenFaaSのデプロイが完了したら、先ほどextraPortMappingで指定したcontainerPortgateway-externalサービスのNodePortで利用するよう修正をしておく。

$ kubectl -n openfaas patch svc/gateway-external --type=json -p='[{"op":"replace", "path":"/spec/ports/0/nodePort", "value":30080}]'
$ kubectl -n openfaas get svc/gateway-external
NAME               TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
gateway-external   NodePort   10.96.159.34   <none>        8080:30080/TCP   40m

OpenFaaSでFunctionのインストール

OpenFaaSにFunctionを登録・起動してみる。
まずはOpenFaaSにadminアカウントでログインする。

$ PASSWORD=$(kubectl get secret -n openfaas basic-auth -o jsonpath="{.data.basic-auth-password}" | base64 --decode; echo)
$ echo -n $PASSWORD | faas-cli login --username admin --password-stdin
Calling the OpenFaaS server to validate the credentials...
credentials saved for admin http://127.0.0.1:8080

事前にOpenFaaS StoreにはいくつかFuncitonが登録されているので、ここから試しにfigletをデプロイしてみる。他にどのようなFunctionがあるかfaas-cli store listで確認できる。

$ faas-cli store deploy figlet

Deployed. 202 Accepted.
URL: http://127.0.0.1:8080/function/figlet

$ faas-cli list
Function                        Invocations     Replicas
figlet                          0               1

デプロイしたFunctionを呼び出す方法は2通り。
ひとつはfaas-cli invokeコマンドによるもの。デプロイしたFunctionのテストに使うことが多い。

$ echo openfaas | faas-cli invoke figlet
                         __
  ___  _ __   ___ _ __  / _| __ _  __ _ ___
 / _ \| '_ \ / _ \ '_ \| |_ / _` |/ _` / __|
| (_) | |_) |  __/ | | |  _| (_| | (_| \__ \
 \___/| .__/ \___|_| |_|_|  \__,_|\__,_|___/
      |_|

もうひとつはOpenFaaSゲートウェイ( ここでは http://127.0.0.1:8080 )のエンドポイントからFunctionを起動するもの。

$ echo openfaas | curl -X POST -d @-  http://127.0.0.1:8080/function/figlet
                         __
  ___  _ __   ___ _ __  / _| __ _  __ _ ___
 / _ \| '_ \ / _ \ '_ \| |_ / _` |/ _` / __|
| (_) | |_) |  __/ | | |  _| (_| | (_| \__ \
 \___/| .__/ \___|_| |_|_|  \__,_|\__,_|___/
      |_|

楽しい🎉

自分でFunctionを作成する

さていよいよ自分でFunctionを登録・起動してみる。Functionは事前にOpenFaaSで用意されているTemplateから作成していく。[1]
まずは最新のTemplateをダウンロードしてくる。

$ faas-cli template pull
$ faas-cli new --list
Languages available as templates:
- csharp
- dockerfile
- go
- java11
- java11-vert-x
- node
- node12
- node12-debian
- node14
- node16
- node17
- php7
- python
- python3
- python3-debian
- ruby

それではpython3テンプレートを利用してFunctionを作成してみる。
Function名はhello-openfaas--prefixはコンテナイメージのprefixのことで、ビルドされたイメージの登録先レジストリを指す。

$ faas-cli new --lang python3 hello-openfaas --prefix localhost:5000
$ ls
hello-openfaas/  hello-openfaas.yml  template/

hello-openfaas/handler.pyがFunctionの実体。これを書き換えて以下のように変更する。

$ cat <<EOL > ./hello-openfaas/handler.py
def handle(req):
    print("Hello! You said: " + req)
EOL

このFunctionをデプロイする。
faas-cli upコマンドひとつで以下を一括で実施してくれる。

  • コンテナイメージの作成: faas-cli build
  • コンテナイメージのレジストリ登録: faas-cli push
  • Functionのデプロイ: faas-cli deploy
$ faas-cli up -f hello-openfaas.yml
$ faas-cli list
Function                        Invocations     Replicas
figlet                          2               1
hello-openfaas                  0               1

無事登録されたFunctionを起動する。

$ echo Nice to meet you! | curl -X POST -d @- http://127.0.0.1:8080/function/hello-openfaas
Hello! You said: Nice to meet you!

できた!
追加でpipモジュールが必要な場合には ./hello-openfaas/requirements.txtに必要なモジュール名を書いておけばコンテナイメージ作成時に読み込んでくれる。
楽しい🎉[2]

脚注
  1. もちろん自分でTemplateから作成することも可能 ↩︎

  2. OpenFaaS Workshopにより詳細なチュートリアルがある。なお本記事はLab.11まであるチュートリアルのうち、Lab.3程度までの内容。深い。。。 ↩︎

Discussion