はじめに
OCIのサーバレスプラットフォームとしてFunctionsがあります。これはAWSのLambdaに相当するサービスです。
Functionsを使い始めたのですが、アーキテクチャがよくわからなかったので、以下のFn projectのQuickstartをやりながら、アーキテクチャを整理したいと思います。
Functionsはfn projectのマネージドサービスです。
事前準備
以下のようなサーバとクライアントを用意します。
なお、図ではサーバとクライアントが別れていますが、今回サーバとクライアントは同一のマシンを使用します。
OSはOracle Linux、Dockerはインストール済みです。
$ cat /etc/oracle-release
Oracle Linux Server release 8.8
$ docker -v
Docker version 24.0.2, build cb74dfc
CLI Toolのインストール
CLI Toolをインストールします。
$ curl -LSs https://raw.githubusercontent.com/fnproject/cli/master/install | sh
fn version 0.6.25
______
/ ____/___
/ /_ / __ \
/ __/ / / / /
/_/ /_/ /_/`
$ fn --version
fn version 0.6.25
接続先のサーバは自分自身になっています。
$ fn list context
CURRENT NAME PROVIDER API URL REGISTRY
* default default http://localhost:8080
fn serverの起動
fn serverを起動します。
fn serverはコンテナで実行されるFunctionのオーケストレーターです。
$ fn start
2023/07/01 07:00:31 ¡¡¡ 'fn start' should NOT be used for PRODUCTION !!! see https://github.com/fnproject/fn-helm/
Unable to find image 'fnproject/fnserver:latest' locally
latest: Pulling from fnproject/fnserver
ff3a5c916c92: Pull complete
1a649ea86bca: Pull complete
ce35f4d5f86a: Pull complete
b6206661264b: Pull complete
b8b71dba24d3: Pull complete
3873004a68ee: Pull complete
f4205b132661: Pull complete
91a85eeeb257: Pull complete
93c96d032b32: Pull complete
bb761748d6e1: Pull complete
81f6c51c4ac2: Pull complete
2ba715696dba: Pull complete
f46c2b56aaf3: Pull complete
66d07b1eeeb9: Pull complete
bf871b66822c: Pull complete
Digest: sha256:2a2071f8af6ed6ad6476ad2e794f757874dad347b5ef14869dd31ee252810655
Status: Downloaded newer image for fnproject/fnserver:latest
time="2023-07-01T07:00:39Z" level=info msg="Setting log level to" fields.level=info
time="2023-07-01T07:00:39Z" level=info msg="Registering data store provider 'sql'"
time="2023-07-01T07:00:39Z" level=info msg="Connecting to DB" url="sqlite3:///app/data/fn.db"
time="2023-07-01T07:00:39Z" level=info msg="datastore dialed" datastore=sqlite3 max_idle_connections=256 url="sqlite3:///app/data/fn.db"
time="2023-07-01T07:00:39Z" level=info msg="agent starting cfg={MinDockerVersion:17.10.0-ce ContainerLabelTag: DockerNetworks: DockerLoadFile: DisableUnprivilegedContainers:false FreezeIdle:50ms HotPoll:200ms HotLauncherTimeout:1h0m0s HotPullTimeout:10m0s HotStartTimeout:5s DetachedHeadRoom:6m0s MaxResponseSize:0 MaxHdrResponseSize:0 MaxLogSize:1048576 MaxTotalCPU:0 MaxTotalMemory:0 MaxFsSize:0 MaxPIDs:50 MaxOpenFiles:0xc42037b2d0 MaxLockedMemory:0xc42037b2d8 MaxPendingSignals:0xc42037b2e0 MaxMessageQueue:0xc42037b2e8 PreForkPoolSize:0 PreForkImage:busybox PreForkCmd:tail -f /dev/null PreForkUseOnce:0 PreForkNetworks: EnableNBResourceTracker:false MaxTmpFsInodes:0 DisableReadOnlyRootFs:false DisableDebugUserLogs:false IOFSEnableTmpfs:false EnableFDKDebugInfo:false IOFSAgentPath:/iofs IOFSMountRoot:/home/opc/.fn/iofs IOFSOpts: ImageCleanMaxSize:0 ImageCleanExemptTags: ImageEnableVolume:false}"
time="2023-07-01T07:00:39Z" level=info msg="no docker auths from config files found (this is fine)" error="open /root/.dockercfg: no such file or directory"
time="2023-07-01T07:00:40Z" level=info msg="available memory" cgroup_limit=9223372036854771712 head_room=1461135769 total_memory=14611357696
time="2023-07-01T07:00:40Z" level=info msg="ram reservations" avail_memory=13150221927
time="2023-07-01T07:00:40Z" level=info msg="available cpu" avail_cpu=2000 total_cpu=2000
time="2023-07-01T07:00:40Z" level=info msg="cpu reservations" cpu=2000
time="2023-07-01T07:00:40Z" level=info msg="\n ______\n / ____/___\n / /_ / __ \\\n / __/ / / / /\n /_/ /_/ /_/\n"
time="2023-07-01T07:00:40Z" level=info msg="Fn serving on `:8080`" type=full version=0.3.750
Fn serverがコンテナで実行されていることがわかります。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1c5c069f2dfc fnproject/fnserver:latest "./fnserver" 10 minutes ago Up 10 minutes 2375/tcp, 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp fnserver
Functionの雛形作成
Goの雛形を作成します。引数のgo
をjava
やpython
などに変えれば、各言語の雛形が作成されます。
$ fn init --runtime go hello
Creating function at: ./hello
Function boilerplate generated.
func.yaml created.
作成された雛形を確認します。
$ tree hello/
hello/
|-- func.go
|-- func.yaml
`-- go.mod
$ cd hello/
各ファイルの中身を確認してみます。
詳しくはわからないのですが、Hello Worldを返すコードです。
package main
import (
"context"
"encoding/json"
"fmt"
"io"
"log"
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),
}
log.Print("Inside Go Hello World function")
json.NewEncoder(out).Encode(&msg)
}
Functionはコンテナで実行されますが、実装言語やBuildする時のベースイメージ、ENTRYPOINTなどを指定します。
schema_version: 20180708
name: hello
version: 0.0.2
runtime: go
build_image: fnproject/go:1.15-dev
run_image: fnproject/go:1.15
entrypoint: ./func
Goモジュールのパスを書いておくファイルです。
module func
require github.com/fnproject/fdk-go v0.0.33
アプリケーションの作成
複数のFunctionやその他の要素を管理するための単位としてアプリケーションを作成します。
$ fn create app myapp
Successfully created app: myapp
$ fn list a
NAME ID
myapp 01H484S9DMNG8G00GZJ0000001
Functionのデプロイ
作成したアプリケーションにFunctionをデプロイします。--local
オプションはBuildしたコンテナイメージをリモートリポジトリにPushしないで、Localに保存するのみとするオプションです。
$ fn deploy --app myapp --local
Deploying hello to app: myapp
Bumped to version 0.0.2
Using Container engine docker
Building image hello:0.0.2 .......................
Updating function hello using image hello:0.0.2...
Successfully created function: hello with hello:0.0.2
Functionのイメージ(hello)が作成されています。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello 0.0.2 736144c8de40 14 seconds ago 116MB
fnproject/fnserver latest 49e4484aa70f 6 weeks ago 162MB
Functionの実行
アプリケーション名、Function名を指定して、Functionを実行します。
$ fn invoke myapp hello
{"message":"Hello World"}
Hello World
が表示されています。
Function実行直後に確認するとFunctionのコンテナが起動しています。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f33c04e23747 hello:0.0.2 "./func" 6 seconds ago Up 6 seconds (Paused) 01H4850XQ4NG8G00GZJ0000004
1c5c069f2dfc fnproject/fnserver:latest "./fnserver" 17 minutes ago Up 17 minutes 2375/tcp, 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp fnserver
数秒後に再度確認すると、コンテナが削除されています。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1c5c069f2dfc fnproject/fnserver:latest "./fnserver" 17 minutes ago Up 17 minutes 2375/tcp, 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp fnserver
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1c5c069f2dfc fnproject/fnserver:latest "./fnserver" 22 minutes ago Up 22 minutes 2375/tcp, 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp fnserver
Function(Fn project)のライフサイクルを辿ることで、アーキテクチャが理解できたような気がします。Kubernetesと似てる印象です。