この記事の目的
Kubernetes を学ぶ途中で出現した OpenFaaS を使ってみます.
本記事では OpenFaaS を利用して API サーバを立ち上げる手順をご紹介します.
こちらの記事では OpenFaaS の立ち上げからモックサーバの作成までを行います.
本記事は API サーバを爆速で立ち上げる方法をご紹介するものではありません.
OpenFaaS を触ってみることを主眼に置いているので「json-server とか使った方が早くない?」は禁止です
構成
本記事では赤枠部分のサービスを扱います.
OpenFaaS はコンテナビルドをして起動する構成であるため CI/CD との相性は良さそうですが,本記事では扱いません.
ローカルの Minikube を使って一連のコンテナを立ち上げています.
サービスの紹介
OpenFaaS
OpenFaaS® makes it easy for developers to deploy event-driven functions and microservices to Kubernetes without repetitive, boiler-plate coding. Package your code or an existing binary in a Docker image to get a highly scalable endpoint with auto-scaling and metrics.
OpenFaaS は Kubernetes 環境上で動作するオープンソースの Function as a Service (FaaS) 1です.
サーバレス環境を提供することで,開発者が自作のコンテナイメージを利用したバッチサーバや API サーバなどを簡単に立ち上げることができます.
デフォルトで Go, Node.js, Python, PHP 等をサポートしていますが,OCI 準拠のコンテナイメージをあらかじめ作成しておくことで任意の言語にも対応することができます.
一方で,実際はコンテナを立ち上げて実行しているに過ぎないので,基盤目線だとコストや監視などの運用方法を検討したうえで導入することになります.
ここで AWS Lambda2 のような「起動した時間分だけ課金する」といったメリットを享受するには多大な工夫が必要に思います.
筆者は,小規模 (何なら自分だけ) の開発や閉じられた環境 (自宅など) でのサービス立ち上げをイメージした時には有力な候補になってくるのかなと考えています.
少しでも興味を持った場合は,公式のチュートリアルも準備されているため Kubernetes 環境さえあれば簡単に試してみることができます.
ドキュメントの参照だけでは心配な方向けに,丁寧な説明がされた eBook (有償) やワークショップ動画など3も準備されているようです.
なお OpenFaaS の金額体系は
- Community Edition (無償)
- OpenFaaS Standard ($1,000/月)
- OpenFaaS for Enterprises (要相談)
の 3 つからなりますが,今回はお試しで利用するので Community Edition を利用します.
動作確認環境
動作確認を行った環境情報を以下に示します.
名称 | バージョン |
---|---|
Windows 11 | 22H2 |
Ubuntu (WSL2) | 20.04.6 LTS |
Docker | 20.10.17 |
Docker Compose | v2.10.2 |
Kubernetes | v1.28.3 |
kubectl client | v1.25.0 |
kubectl kustomize | v4.5.7 |
minikube | v1.32.0 |
helm | v3.13.3 |
OpenFaaS | 0.27.3 |
faas-cli | 0.16.21 |
Go | 1.21.5 |
faas-cli 環境準備手順
OpenFaaS の公式 CLI である faas-cli を準備しておきます.
公式で準備されているシェルスクリプトを実行 (curl -sSL https://cli.openfaas.com | sudo -E sh
) すればいいだけですが,個人的な都合で配置場所と環境変数は管理しておきたいので手動で行います.
シェルスクリプトの中身を確認したい場合は wget https://cli.openfaas.com -O get.sh
を利用するとよいと思います.
# faas-cli の取得
mkdir -p $HOME/extracts/openfaas/bin && mkdir -p $HOME/installers/linux/openfaas && cd $_ && \
wget https://github.com/openfaas/faas-cli/releases/download/0.16.21/faas-cli && \
cp faas-cli $HOME/extracts/openfaas/bin
# パスを通す
vim $HOME/.bashrc
> # faas-cli
> export FAASCLI_HOME=$HOME/extracts/openfaas
> export PATH=$PATH:$FAASCLI_HOME/bin
source $HOME/.bashrc
# インストール確認
faas-cli version
OpenFaaS の起動
以下の記事を参考に作業を進めます.
ポートフォワード, faas-cli login
等の作業は変更しているので注意してください.
# openfaas および openfaas-fn の namespace を作成
kubectl apply -f https://raw.githubusercontent.com/openfaas/faas-netes/master/namespaces.yml
> namespace/openfaas created
> namespace/openfaas-fn created
# helm レポジトリ追加
helm repo add openfaas https://openfaas.github.io/faas-netes/
> "openfaas" has been added to your repositories
# チャート更新
helm repo update
# パスワード作成
export PASSWORD=$(head -c 12 /dev/urandom | shasum| cut -d' ' -f1)
echo $PASSWORD
# secret 発行
kubectl -n openfaas create secret generic basic-auth --from-literal=basic-auth-user=admin --from-literal=basic-auth-password="$PASSWORD"
> secret/basic-auth created
# OpenFaaS インストール
helm upgrade openfaas --install openfaas/openfaas --namespace openfaas --set functionNamespace=openfaas-fn --set basic_auth=true
# 起動待機
kubectl -n openfaas get pods
> NAME READY STATUS RESTARTS AGE
> alertmanager-795bbdc56c-f8qmp 1/1 Running 0 12m
> gateway-67df8c4d4-5bwsc 2/2 Running 0 12m
> nats-5c48bc8b46-56xbz 1/1 Running 0 12m
> prometheus-78d4c9f748-42f5l 1/1 Running 0 12m
> queue-worker-b9965cc56-wvjl9 1/1 Running 3 (11m ago) 12m
# OpenFaaS ログイン用パスワードの取得
LOGIN_PASSWORD=$(kubectl -n openfaas get secret basic-auth -o jsonpath="{.data.basic-auth-password}" | base64 --decode) && echo "OpenFaaS admin password: $LOGIN_PASSWORD"
# ポートフォワード http://localhost:8080 で OpenFaaS 管理 GUI にアクセスできるようになる
## ログインユーザは admin, パスワードは $LOGIN_PASSWORD を使う
kubectl port-forward -n openfaas svc/gateway 8080:8080
# ポートフォワード http://localhost:8090 で Prometheus GUI にアクセスできるようになる
kubectl port-forward -n openfaas deployment/prometheus 8090:9090
# faas-cli から OpenFaaS に接続 別ターミナルから
echo -n $LOGIN_PASSWORD | faas-cli login -g http://localhost:8080 -u admin --password-stdin
> Calling the OpenFaaS server to validate the credentials...
> credentials saved for admin http://localhost:8080
FaaS を試す
既存の関数を利用する
一番簡単に FaaS を試すには,公式が提供している既存の関数をそのまま利用するのがよいと思います.
faas-cli store list
を叩くことで既存の関数一覧を取得できます.
faas-cli store list
> FUNCTION AUTHOR DESCRIPTION
> nodeinfo openfaas NodeInfo
> env openfaas env
> sleep openfaas sleep
> shasum openfaas shasum
> figlet openfaas figlet
> printer openfaas printer
> curl openfaas curl
> external-ip openfaas external-ip
> youtube-dl openfaas youtube-dl
> sentimentanalysis openfaas SentimentAnalysis
> hey openfaas hey
> nslookup openfaas nslookup
> certinfo stefanprodan SSL/TLS cert info
> colorise alexellis Colorization
> inception alexellis Inception
> alpine openfaas alpine
> face-detect-pigo esimov Face Detection with Pigo
> ocr viveksyngh Tesseract OCR
> qrcode-go alexellis QR Code Generator - Go
> nmap openfaas Nmap Security Scanner
> cows openfaas ASCII Cows
> text-to-speech rorpage OpenFaaS Text-to-Speech
> mquery rgee0 Docker Image Manifest Query
> face-detect-opencv alexellis face-detect with OpenCV
> face-blur esimov Face blur by Endre Simo
> normalisecolor alexellis normalisecolor
> coherent-line-drawing esimov Line Drawing Generator from a photograph
> openfaas-exif servernull Image EXIF Reader
> openfaas-opennsfw servernull Open NSFW Model
> identicon rgee0 Identicon Generator
> chaos alexellis chaos
curl 関数を起動してみます.
関数を実行する Pod が起動していることを確認後 POST
で関数を実行します.
curl で API を叩き,curl 関数が curl
を実行します.
(もっとわかりやすい例にすればよかった...)
# 関数のデプロイ
faas-cli store deploy curl --gateway localhost:8080
> Deployed. 202 Accepted.
> URL: http://localhost:8080/function/curl
# 関数が Pod で起動していることを確認
kubectl -n openfaas-fn get svc
> NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
> curl ClusterIP 10.97.208.189 <none> 8080/TCP 4m
kubectl -n openfaas-fn get pods
> NAME READY STATUS RESTARTS AGE
> curl-5d499476b8-szksq 1/1 Running 0 4m6s
# 関数テスト実行
echo http://worldtimeapi.org/api/timezone/Asia/Tokyo | faas-cli invoke curl --gateway localhost:8080
> % Total % Received % Xferd Average Speed Time Time Time Current
> Dload Upload Total Spent Left Speed
> 100 343 100 343 0 0 3784 0 --:--:-- --:--:-- --:--:-- 3811
> {"abbreviation":"JST",..."week_number":1}
# 関数実行
curl -X POST http://localhost:8080/function/curl -d "http://worldtimeapi.org/api/timezone/Asia/Tokyo"
> % Total % Received % Xferd Average Speed Time Time Time Current
> Dload Upload Total Spent Left Speed
> 100 343 100 343 0 0 3784 0 --:--:-- --:--:-- --:--:-- 3811
> {"abbreviation":"JST",..."week_number":1}
OpenFaaS の管理 GUI からも既存関数のデプロイや,起動した関数のテスト実行を行うことできます.
表示からわかるようにコンテナイメージは ghcr.io/openfaas/curl:latest
が利用されています.
テンプレートから自作関数を作成して利用する
テンプレートを利用してビルドしたイメージを利用することで,自作のサーバーレス関数をデプロイすることができます.
現在 OpenFaaS で提供されているテンプレートは 2 種類存在します.
ひとつはクラシックテンプレートです.
mkdir -p $HOME/codes/GitHub/openfaas && cd $_ && \
# クラシックテンプレートを取得
faas-cli template pull
もうひとつは Template Store で提供しているテンプレートです.
# テンプレート一覧を確認
faas-cli template store list
# 特定のテンプレートを取得
faas-cli template store pull {template name}
これらの違いはアーキテクチャにあり,前者は Classic watchdog,後者は of-watchdog を利用しています.
通信方法や繰り返し起動時の挙動が異なり,基本的に of-watchdog の方がより高いパフォーマンスを発揮できるとのことです.
ここでは Template Store から取得できる golang-middleware
テンプレートを利用して新規関数を起動します.
# golang-http, golang-middleware テンプレート取得
faas-cli template store pull golang-http
> Fetch templates from repository: https://github.com/openfaas/golang-http-template at
> 2024/01/06 19:51:38 Attempting to expand templates from https://github.com/openfaas/golang-http-template
> 2024/01/06 19:51:40 Fetched 2 template(s) : [golang-http golang-middleware] from https://github.com/openfaas/golang-http-template
ls
> template
# テンプレートから新しい関数用ファイルを作成
faas-cli new --lang golang-middleware echo
> Folder: echo created.
> ___ _____ ____
> / _ \ _ __ ___ _ __ | ___|_ _ __ _/ ___|
> | | | | '_ \ / _ \ '_ \| |_ / _` |/ _` \___ \
> | |_| | |_) | __/ | | | _| (_| | (_| |___) |
> \___/| .__/ \___|_| |_|_| \__,_|\__,_|____/
> |_|
>
>
> Function created in folder: echo
> Stack file written: echo.yml
>
> Notes:
> You have created a new function which uses Go 1.21 and Alpine
> Linux as its base image.
>
> To disable the go module, for private vendor code, please use
> "--build-arg GO111MODULE=off" with faas-cli build or configure this
> via your stack.yml file.
>
> Learn more: https://docs.openfaas.com/languages/go/
ls
> echo echo.yml template
作成した echo
配下で go get
等を行って Go 開発手順で関数を準備することができます.4
本記事ではデフォルト状態のままでビルドしてみます.
デフォルトではリクエストボディを ("Body: %s", string(input))
でレスポンスに含める handler が準備されています.
package function
import (
"fmt"
"io"
"net/http"
)
func Handle(w http.ResponseWriter, r *http.Request) {
var input []byte
if r.Body != nil {
defer r.Body.Close()
body, _ := io.ReadAll(r.Body)
input = body
}
w.WriteHeader(http.StatusOK)
w.Write([]byte(fmt.Sprintf("Body: %s", string(input))))
}
echo.yml
を適切に設定します.
version: 1.0
provider:
name: openfaas
# gateway: http://192.168.49.2:31112
gateway: http://localhost:8080
functions:
echo:
lang: golang-middleware
handler: ./echo
image: echo:latest
faas-cli build
でコンテナイメージをビルドし,DockerHub などのレジストリに push しておきます.
# 念のため利用するイメージをあらかじめ pull しておく
docker pull golang:1.21-alpine
docker pull alpine:3.18.4
docker pull ghcr.io/openfaas/of-watchdog:0.9.13
# ビルド
faas-cli build -f ./echo.yml
> [0] > Building echo.
> Building: echo:latest with golang-middleware template. Please wait..
> ...
> Total build time: 111.72s
# イメージが準備できていることを確認
docker images
> REPOSITORY TAG IMAGE ID CREATED SIZE
> echo latest 33d10630847c 2 minutes ago 21.5MB
# イメージを DockerHub などに push しておく
## イメージ名変更
docker tag echo:latest caunus/openfass-echo:latest
## ログインして push
docker login
docker push caunus/openfass-echo:latest
OpenFaaS の管理 GUI から caunus/openfass-echo:latest
を利用した関数を起動してみます.
テスト実行 (INVOKE) でリクエストに含めた foo-bar
がレスポンスに含まれて返されていることがわかります.
# 関数の起動確認
kubectl -n openfaas-fn get svc
> NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
> curl ClusterIP 10.97.208.189 <none> 8080/TCP 134m
> openfass-echo ClusterIP 10.98.52.162 <none> 8080/TCP 6m20s
kubectl -n openfaas-fn get pods
> NAME READY STATUS RESTARTS AGE
> curl-5d499476b8-szksq 1/1 Running 0 134m
> openfass-echo-6947cb4976-2j9v2 1/1 Running 0 6m22s
# 関数実行
curl -X POST http://localhost:8080/function/openfass-echo -d "hoge-fuga"
> Body: hoge-fuga
実際に POST
してみても正しく関数が動いていることが確認できました.
まとめ
OpenFaaS を使って(特に Go 製の) API サーバーを立ち上げてみました.
テンプレートを使ってコンテナイメージのビルドが必要になってくるため,組織で使うにはある程度の知識習熟が必要になるサービスかもしれません...
そもそも刺さる人は一部の界隈に限るのかもしれませんが,個人的にはいくらか手元でサービスを立てて管理したいときがあるので活用できる機会はありそうと思いました.
後片付け (オマケ)
お試し環境を削除する手順も念のため載せておきます.
helm uninstall -n openfaas openfaas
kubectl delete namespace openfaas openfaas-fn