Oracle社が開発したFnは、サーバー上でサーバレス処理が実行できる、軽量なDockerベースのプラットフォームです。
サーバレスと言いつつもFn Serverは必要となります。Fn Projectについてこちらの記事が非常にわかりやすくまとめてくださっています。
AWS LambdaやCloud Functionsではリソースの管理はクラウド側でしますが、Fn はオープンソースであり、Fn Server側で自分達でリソース管理する必要があります。その分細かい制御、設定ができるというのが特徴です。
今回Oracle Linux7.6にFn Serverを構築します。Fn ServerはDockerとFn cliのインストールが必要です。
またFnサーバーは最初からPrometheusメトリクスを内蔵しているため、ファンクションの動きを監視できるよう、Prometheus+Grafanaをインストールします。
参考
oracle-functions-labs
Announcing Prometheus Metrics from Fn
前提
Oracle Linux7.6でFn Serverを構築
selinux無効化
8080,9090,3000ポートを開放していること
※rootユーザでの作業です。
dockerインストール
リポジトリ設定
# vi /etc/yum.repos.d/docker.repo
以下記載
[dockerrepo]
name=Docker Repository
baseurl=https://yum.dockerproject.org/repo/main/oraclelinux/7
enabled=1
gpgcheck=1
gpgkey=https://yum.dockerproject.org/gpg
インストール
# yum install docker-engine
確認
# dockerd --version
Docker version 18.09.1-ol, build e32a1bd
起動、自動起動設定
# systemctl start docker.service
# systemctl enable docker.service
FN CLIインストール・設定
インストールからスタートまで
インストール
# curl -LSs https://raw.githubusercontent.com/fnproject/cli/master/install | sh
※以下表示されたら成功です。
fn version 0.5.84
______
/ ____/___
/ /_ / __ \
/ __/ / / / /
/_/ /_/ /_/`
Fnサーバスタート
# (fn start > /dev/null 2>&1 &)
確認
# fn version
Client version is latest version: 0.5.84
Server version: 0.3.727
※Server version: が「?」と表示されると正しくインストールされていません。
docker ps
※ポート番号8080でfnseverのコンテナが稼働していること。
ブラウザ表示確認
http://FnサーバのIPアドレス:8080
※以下表示されること。
{"goto":"https://github.com/fnproject/fn","hello":"world!"}
※8080ポートを他のアプリで使用して違うポートを利用したい場合
スタート時以下で指定し、環境変数を設定します(8081番にしたい場合)。
# (fn start -p 8081 > /dev/null 2>&1 &)
# export FN_API_URL=http://127.0.0.1:8081
### FN CLI設定
続いて現在のコンテキストとしてdefaultを選択し、リモートまたはローカルのDockerで使用するためのレジストリ値を設定する必要があります。
コンテキストの確認
# fn list context
defaultを設定
# fn use context default
レジストリ設定
# fn update context registry fnuser
確認
# fn list contexts
※defaultコンテキストに「*」が付き、REGISTRYにfnuserと表示されること。
PrometheusとGrafanaインストール
PrometheusとGrafanaを使ってFn実行時メトリックを表示できるようにします。
FnサーバーのPrometheusメトリクスについて
Fnは3つのメトリックを提供しています。
1、機能数:現在キューに入れられているか実行されている機能の数、およびサーバーが最後に始動されてから正常に完了または失敗した機能の数。
2、操作期間:まざまな操作を実行するのにかかる時間を表します。関数の実行にかかる時間を取得するだけでなく、実行されているdockerコンテナの起動にかかる時間など、より詳細なデータを取得することもできます。。
3、Docker統計メトリクス:コンテナからCPUやメモリ使用量などのさまざまな統計情報を取得し、それらをPrometheusメトリクスとして利用できるようにします。
以下でメトリクスを表示できます。
http://FnサーバのIP:8080/metrics
Grafana/Prometheus環境導入
Goインストール
# yum install golang-bin
確認
# go version
ディレクトリ作成
# mkdir grafana
移動
# cd grafana
GOPATHを通す
# GOPATH=`pwd` ; export GOPATH
goでfnインストール
# go get github.com/fnproject/fn
※↓のディレクトリが作成されます。
$GOPATH/src/github.com/fnproject/fn
Prometheusインストール
# docker run --name=prometheus -d -p 9090:9090 -v ${GOPATH}/src/github.com/fnproject/fn/examples/grafana/prometheus.yml:/etc/prometheus/prometheus.yml --link fnserver prom/prometheus
prometheusとfn serverを紐づけるためのdockerIPを確認
# docker network inspect bridge -f '{{range .IPAM.Config}}{{.Gateway}}{{end}}'
※以下のように表示されます。
172.17.0.1
設定確認
tail -1 ${GOPATH}/src/github.com/fnproject/fn/examples/grafana/prometheus.yml
- targets: ['fnserver:8080'] # Uses /metrics by default
※Fnサーバーのホスト名とポートが指定されています。
Prometheusのブラウザ確認
http://Fn ServerのIP:9090/graph
Status > Targetsより fnseverのメトリクスが取得されています。
Grafanaインストール
# docker run --name=grafana -d -p 3000:3000 --link prometheus grafana/grafana
Grafnaの設定
ブラウザで以下指定します。
http://Fn ServerのIP:3000/graph
ユーザ名:パスワードはどちらも admin。
Prometheusからメトリックを取得するためのデータソースを作成します。
データソースの追加でPrometheusをクリックしてください。
開かれたフォームで:
・Name: PromDS(任意)
・Type: Prometheus
・URL: http://prometheus:9090
・Access: Server(Default)
上記入力し、「Save and test」をクリックします。
次に、Fnサーバーからのメトリックを表示するサンプルダッシュボードをインポートします。
・左メニュー「+」をクリックして、Importを選択します。
・以下パスにあるjsonファイルをアップロードします。
$GOPATH/src/github.com/fnproject/fn/examples/grafana/fn_grafana_dashboard.json
・先ほど作成したPrometheusデータソース(PromDS)を指定します。
・Importをクリック
ダッシュボードが表示されます。まだファンクションを実行していないため、値が表示されていません。
$GOPATH/src/github.com/fnproject/fn/examples/grafanaにあるjsonファイルはあと2つありますので、そちらもインポートしてください。
各ダッシュボードのjsonファイルは、先ほど説明した3つのメトリクスを表示します。
・機能数メトリクス - fn_grafana_dashboard.json
・操作期間メトリクス - fn_grafana_dashboard2.json
・Docker統計メトリクス - fn_grafana_dashboard3.json
Goで関数を作成する。
簡単にテスト関数を作成して実行してみます。
まずfn initコマンドで、関数作成のための基本的な機能を備えたファイルを配置します。
# fn init --runtime go --trigger http gofn
※上記は--runtimeで言語を選択。httpトリガーを設定し、関数名がgofnとなります。
gofnディレクトリが作成されるので移動
# cd gofn
ディレクトリには3つのファイルが作成されています。
# ls
func.go func.yaml go.mod
各ファイルの説明
func.goは関数のメイン処理を記載します。
↓はjson形式で name に値を指定して渡すと {"Hello ,nameで渡した値"} と表示され、値を渡さないと{"Hello ,World"} と表示する関数です。
# cat func.go
package main
import (
"context"
"encoding/json"
"fmt"
"io"
fdk "github.com/fnproject/fdk-go"
)
func main() {
fdk.Handle(fdk.HandlerFunc(myHandler))
}
type Person struct {
Name string `json:"name"`
}
func myHandler(ctx context.Context, in io.Reader, out io.Writer) {
p := &Person{Name: "World"}
json.NewDecoder(in).Decode(p)
msg := struct {
Msg string `json:"message"`
}{
Msg: fmt.Sprintf("Hello %s", p.Name),
}
json.NewEncoder(out).Encode(&msg)
}
func.yamlは関数の設定ファイルです。
※下記の内容。
・schema_version - この関数のスキーマのバージョン
・name - 関数の名前 ディレクトリ名と一致します。
・version - バージョン。自動的に0.0.1から始まる。
・runtime - ランタイム/言語の名前
・entrypoint - 関数を実行した時に呼び出す実行可能ファイルの名前。この場合 ./func
・triggers - トリガーのエンドポイントを決めます。上記の場合⇒http://localhost:8080/t/appname/gofn-triggerで実行されます。
# cat func.yaml
schema_version: 20180708
name: gofn
version: 0.0.2
runtime: go
entrypoint: ./func
triggers:
- name: gofn
type: http
source: /gofn
Gopkg.tomlは関数のすべての依存関係を指定するファイルです。
デプロイ
関数を格納するアプリケーション作成
# fn create app goapp
関数をデプロイ
# fn -v deploy --app goapp --local
※--localでローカルサーバーにデプロイされます。
関数を呼び出す
関数実行方法は複数あります。
fn invokeコマンドを使います。
# fn invoke goapp gofn
※{"message":"Hello World"} と表示されます。
json形式で値を渡して実行してみます。
# echo -n '{"name":"Bob"}' | fn invoke goapp gofn --content-type application/json
※{"message":"Hello Bob"}と表示されます。
また今回 fn initコマンド時にhttpトリガーを設定しているため、エンドポイントをcurlして実行することもできます。
エンドポイント確認
# fn list triggers goapp
例)
FUNCTION NAME TYPE SOURCE ENDPOINT
gofn gofn-trigger http /gofn-trigger http://localhost:8080/t/goapp/gofn-trigger
Curlで実行
# curl -H "Content-Type: application/json" http://localhost:8080/t/goapp/gofn-trigger
もしくは
# curl -H "Content-Type: application/json" -d '{"name":"Bob"}' http://localhost:8080/t/goapp/gofn-trigger
※結果はfn invokeの時と同じです。
httpトリガーを設定すれば、他のサーバから関数を呼び出しfn serverが処理を実行してくれるということが可能です。
とりあえず実行環境が整ったということで本記事はここまでです。
ワークフローの可視化、実行管理などをするFn Flowなど、他のUIツールも導入すれば
更に使い勝手がよくなると思います。