OpenFaaSをK3s上に構築する
はじめに
OpenFaaSを試してみたくなったので、K3sを利用してサクッと構築する。あわせてコンテナレジストリとしてローカルにPrivate Registryも一緒に構築してしまう。
検証環境
Ubuntu 22.04
Docker 20.10.16
K3s 1.23.6+k3s1
OpenFaaS 0.15.0
K3s Kubernetesクラスタを構築
なんとなくDocker環境は残しておきたかったので、コンテナランタイムをDockerに変更してK3sをインストールする。
$ curl -sfL https://get.k3s.io | sh -s - --docker --kubelet-arg 'cgroup-driver=systemd' --write-kubeconfig-mode 644
[INFO] Finding release for channel stable
[INFO] Using v1.23.6+k3s1 as release
[INFO] Downloading hash https://github.com/k3s-io/k3s/releases/download/v1.23.6+k3s1/sha256sum-amd64.txt
[INFO] Skipping binary downloaded, installed k3s matches hash
[INFO] Skipping installation of SELinux RPM
[INFO] Skipping /usr/local/bin/kubectl symlink to k3s, already exists
[INFO] Skipping /usr/local/bin/crictl symlink to k3s, already exists
[INFO] Skipping /usr/local/bin/ctr symlink to k3s, command exists in PATH at /usr/bin/ctr
[INFO] Creating killall script /usr/local/bin/k3s-killall.sh
[INFO] Creating uninstall script /usr/local/bin/k3s-uninstall.sh
[INFO] env: Creating environment file /etc/systemd/system/k3s.service.env
[INFO] systemd: Creating service file /etc/systemd/system/k3s.service
[INFO] systemd: Enabling k3s unit
Created symlink /etc/systemd/system/multi-user.target.wants/k3s.service → /etc/systemd/system/k3s.service.
[INFO] systemd: Starting k3s
$ kubectl version
Client Version: version.Info{Major:"1", Minor:"23", GitVersion:"v1.23.6+k3s1", GitCommit:"418c3fa858b69b12b9cefbcff0526f666a6236b9", GitTreeState:"clean", BuildDate:"2022-04-28T22:16:18Z", GoVersion:"go1.17.5", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"23", GitVersion:"v1.23.6+k3s1", GitCommit:"418c3fa858b69b12b9cefbcff0526f666a6236b9", GitTreeState:"clean", BuildDate:"2022-04-28T22:16:18Z", GoVersion:"go1.17.5", Compiler:"gc", Platform:"linux/amd64"}
$ kubectl cluster-info
Kubernetes control plane is running at https://127.0.0.1:6443
CoreDNS is running at https://127.0.0.1:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
Metrics-server is running at https://127.0.0.1:6443/api/v1/namespaces/kube-system/services/https:metrics-server:https/proxy
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
これだけでKubernetesクラスタ構築できるK3sほんと凄い。なおKubernetesもOpenFaaSもメモリをたくさん消費するので最低でもRAM 2GBくらいは確保しておいたほうが良い。[1]
以下でHelmを用いてOpenFaaSをインストールするが、HelmからKubernetesクラスタにアクセスできない旨のエラーが出ることがある。事前に~/.kube/config
を作成しておくとよい。
$ kubectl config view --raw > ~/.kube/config
$ chmod o-r ~/.kube/config
$ chmod g-r ~/.kube/config
HelmチャートでOpenFaaSインストール
Helmをインストール。
$ curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
$ helm version
version.BuildInfo{Version:"v3.5.2", GitCommit:"167aac70832d3a384f65f9745335e9fb40169dc2", GitTreeState:"dirty", GoVersion:"go1.15.7"}
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 \
--set serviceType=LoadBalancer
# しばらく待つ
$ kubectl -n openfaas get deployments -l "release=openfaas, app=openfaas"
NAME READY UP-TO-DATE AVAILABLE AGE
prometheus 1/1 1 1 65s
nats 1/1 1 1 65s
alertmanager 1/1 1 1 65s
basic-auth-plugin 1/1 1 1 65s
queue-worker 1/1 1 1 65s
gateway 1/1 1 1 65s
OpenFaaSはWebUIからも操作も可能だが、CLIで操作できる公式ツールが用意されているのでインストール。
$ curl -sSL https://cli.openfaas.com | sudo sh
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を登録・起動してみる。
OpenFaaSはコンテナ起動イメージからプロセスを起動するため、自前のFunctionも事前にコンテナレジストリに登録しておくことが必要。特に何も指定しなければ、OpenFaaSはDocker Hubをコンテナレジストリとする。
Docker Hubはダウンロード制限があったり無償プライベートレポジトリは1つだけとされていたりいくつかの制限があるため、ここでは自前でプライベートレジストリを構築しこれを利用したい。[2]
さっそくKubenetes上にプライベートレジストリを構築する。
$ kubectl create namespace docker-registry
$ cat << EOL | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: docker-registry
namespace: docker-registry
labels:
app: docker-registry
spec:
replicas: 1
selector:
matchLabels:
app: docker-registry
template:
metadata:
labels:
app: docker-registry
name: docker-registry
spec:
containers:
- name: docker-registry
image: registry
ports:
- containerPort: 5000
volumeMounts:
- name: storage
mountPath: /var/lib/registry
volumes:
- name: storage
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: docker-registry-service
namespace: docker-registry
spec:
selector:
app: docker-registry
type: NodePort
ports:
- name: docker-registry-port
protocol: TCP
port: 5000
targetPort: 5000
EOL
$ kubectl get service -n docker-registry
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
docker-registry-service NodePort 10.43.242.177 <none> 5000:30848/TCP 17s
無事に10.43.242.177:5000
でプライベートレジストリが起動している。
このレジストリを他のPodsから利用するためには、K3sにこのプライベートレジストリを登録しておく必要がある。
$ export REGISTRY_IP=$(kubectl get svc/docker-registry-service -n docker-registry -o jsonpath='{.spec.clusterIP}')
$ cat << EOF | sudo tee /etc/rancher/k3s/registries.yaml
mirrors:
"${REGISTRY_IP}:5000":
endpoint:
- "http://${REGISTRY_IP}:5000"
EOF
$ sudo systemctl restart k3s
また今回構築したプライベートレジストリは通信が暗号化されていないためinsecure-registries
としてDockerにも登録が必要。[3]
$ export REGISTRY_IP=$(kubectl get svc/docker-registry-service -n docker-registry -o jsonpath='{.spec.clusterIP}')
$ cat << EOL | sudo tee /etc/docker/daemon.json
{
"insecure-registries": [ "${REGISTRY_IP}:5000" ]
}
EOL
$ sudo systemctl restart docker
準備完了。FunctionはOpenFaaSで用意されているTemplateから作成していく。[4]
まずは最新の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 ${REGISTRY_IP}: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
に必要なモジュール名を書いておけばコンテナイメージ作成時に読み込んでくれる。
楽しい🎉[5]
-
なおこの環境構築のためにVagrantでVMをたてて色々試行錯誤していたところ、VMデフォルトのメモリサイズが512MBのままであったのを忘れてうまく起動しないことを愚痴っていたらOpenFaaS FounderのAlexさんに「何やってんの?」と言われてしまった。https://twitter.com/alexellisuk/status/1528994343125655552 ↩︎
-
GitHub Packages Container registryやGitlab Container Registryなども利用できるのかな?未検証。 ↩︎
-
もしすでに
/etc/docker/daemon.json
がある場合は上書きしないように気を付けてね ↩︎ -
もちろん自分でTemplateから作成することも可能 ↩︎
-
OpenFaaS Workshopにより詳細なチュートリアルがある。なお本記事はLab.11まであるチュートリアルのうち、Lab.3程度までの内容。深い。。。 ↩︎
Discussion