Facebook Twitter
お問い合わせ
TOPICS
更新情報
ホーム > ブログ > ソフトウェア > Fn Projectを触ってみる

Fn Projectを触ってみる

ソフトウェア
2018.07.31

こんにちは id:dhigashi です。

7/27 に開催された Innovation Summit Tokyo 2018Fn Project: 今最も注目すべき「サーバレス」クラウドアプリケーション開発基盤 というタイトルで Fn Project についてのセッションがありました。

面白そうでしたので、今回は Oracle Cloud ではなく Fn Project について簡単に触ってみたいと思います。

セッション資料はこちらから見る事ができます。
http://www.oracle.co.jp/campaign/innovation/2018/pdfs/ist18_b-3.pdf

尚、Fn Project は Oracle Cloud 上で提供される FaaS の Oracle Functions として利用できるようになるようです。


Fn Project


インストールの前に

事前条件として以下を満たす必要があります。

  • Docker 17.10.0-ce 以上がインストールされていること
  • Docker Hub のアカウントを持ち、ログイン済みであること

尚、検証に使用した環境は以下の通りです。

$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.04
DISTRIB_CODENAME=xenial
DISTRIB_DESCRIPTION="Ubuntu 16.04.5 LTS"
$ docker version
Client:
Version:           18.06.0-ce
API version:       1.38
Go version:        go1.10.3
Git commit:        0ffa825
Built:             Wed Jul 18 19:11:02 2018
OS/Arch:           linux/amd64
Experimental:      false
Server:
Engine:
Version:          18.06.0-ce
API version:      1.38 (minimum version 1.12)
Go version:       go1.10.3
Git commit:       0ffa825
Built:            Wed Jul 18 19:09:05 2018
OS/Arch:          linux/amd64
Experimental:     false


インストール

fnproject/fn - quickstart に従いインストールします。

$ curl -LSs https://raw.githubusercontent.com/fnproject/cli/master/install | sh
fn version 0.4.140
______
/ ____/___
/ /_  / __ \
/ __/ / / / /
/_/   /_/ /_/`

インストールが完了したら Fn サーバを起動します。

$ fn start
Unable to find image 'fnproject/fnserver:latest' locally
latest: Pulling from fnproject/fnserver
略
______
/ ____/___
/ /_  / __ \
/ __/ / / / /
/_/   /_/ /_/
v0.3.520

起動できたらバージョンを確認してみます。

$ fn version
Client version is latest version: 0.4.140
Server version:  0.3.520

尚、Fn サーバは Dockerコンテナとして起動しています。

$ docker ps
CONTAINER ID        IMAGE                COMMAND             CREATED             STATUS              PORTS                              NAMES
7156fd345aa1        fnproject/fnserver   "./fnserver"        2 hours ago         Up 2 hours          2375/tcp, 0.0.0.0:8080->8080/tcp   fnserver

最後に、環境変数 FN_REGISTRY に自身の Docker Hub のユーザ名を設定し準備は完了です。

export FN_REGISTRY=my_dockerhub_username


関数の作成

fn init コマンドで新しい関数を作成します。

$ fn init --help
DEVELOPMENT COMMANDS
fn init -   Create a local func.yaml file
USAGE
fn [global options] init [command options] [function-subdirectory]
DESCRIPTION
This command creates a func.yaml file in the current directory.
COMMAND OPTIONS
--name value                   Name of the function. Defaults to directory name in lowercase.
--force                        Overwrite existing func.yaml
--runtime value                Choose an existing runtime - dotnet, go, java8, java9, java, lambda-nodejs4.3, lambda-node-4, node, php, python, python3.6, ruby, rust, kotlin
--entrypoint value             Entrypoint is the command to run to start this function - equivalent to Dockerfile ENTRYPOINT.
--cmd value                    Command to run to start this function - equivalent to Dockerfile CMD.
--version value                Set initial function version (default: "0.0.1")
--working-dir value, -w value  Specify the working directory to initialise a function, must be the full path.
--trigger value                Specify the trigger type.
--memory value, -m value       Memory in MiB (default: 0)
--type value, -t value         Route type - sync or async
--config value, -c value       Route configuration
--headers value                Route response headers
--format value, -f value       Hot container IO format - default or http
--timeout value                Route timeout (eg. 30) (default: 0)
--idle-timeout value           Route idle timeout (eg. 30) (default: 0)
--annotation value             Route annotation (can be specified multiple times)
$ fn init --runtime go hello
Creating function at: /hello
Runtime: go
Function boilerplate generated.
func.yaml created.

今回はランタイムに go 言語を選択しましたが、ヘルプを見ると現時点では dotnet、java、node、python、ruby...などの言語が選択できるようです。
特に rust、kotlin は珍しい気がします。

function-subdirectory として指定した hello ディレクトリ以下にファイルが作成されました。

$ cd hello
$ ls -1
Gopkg.toml
func.go
func.yaml
test.json

func.go は以下のような内容になっています。

$ 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)
}

myHandler 関数をみると in から入力し out へ出力するだけのシンプルなものです。
入力は json を期待しているようです。

次に func.yaml を見てみます。

$ cat func.yaml
name: hello
version: 0.0.1
runtime: go
entrypoint: ./func
format: json

関数の名前やバージョン、ランタイム、実行ファイル名などが記されています。
ここに format として json が指定されており、関数の入出力に json を用いる事を示しています。


ローカルで関数の実行

fn init コマンドによって作成された関数をローカルで実行してみます。
ローカルで実行するには fn run コマンドを使用します。

$ fn run
Building image my_dockerhub_username/hello:0.0.1 ............................
{"message":"Hello World"}

入力に何も指定していないので、出力された message の値が Hello World となっています。
次に標準入力で値を渡して実行してみます。

$ echo -n '{"name":"Jason"}' | fn run
Building image my_dockerhub_username/hello:0.0.1 ...
{"message":"Hello Jason"}

標準入力で与えられた値によって出力を変える事ができました。


関数のデプロイ

ローカルで動作を確認した関数を Fn サーバへデプロイします。
デプロイを行うためには fn deploy コマンドを使用します。

$ fn deploy --help
DEVELOPMENT COMMANDS
fn deploy -   Deploys a function to the functions server (bumps, build, pushes and updates route).
USAGE
fn [global options] deploy [command options] [function-subdirectory]
DESCRIPTION
This command deploys one or all (--all) functions to the function server.
COMMAND OPTIONS
--app value                     App name to deploy to
--verbose, -v                   Verbose mode
--no-cache                      Don't use Docker cache for the build
  --local, --skip-push            Do not push Docker built images onto Docker Hub - useful for local development.
  --registry --registry username  Set the Docker owner for images and optionally the registry. This will be prefixed to your function name for pushing to Docker registries  eg: --registry username will set your Docker Hub owner. --registry registry.hub.docker.com/username will set the registry and owner.
  --all app.yaml                  If in root directory containing app.yaml, this will deploy all functions
  --no-bump                       Do not bump the version, assuming external version management
  --build-arg value               Set build time variables
  --working-dir value, -w value   Specify the working directory to deploy a function, must be the full path.
$ fn deploy --app myapp --local
Deploying hello to app: myapp at path: /hello
Bumped to version 0.0.2
Building image my_dockerhub_username/hello:0.0.2 ...
Updating route /hello using image my_dockerhub_username/hello:0.0.2...

アプリケーション名に myapp と指定しデプロイを行います。
※ 今回 Docker Hub へのプッシュを行わないため、--local オプションを指定しています。

アプリケーションの一覧を取得すると myapp が存在する事が確認できます。

$ fn list apps
NAME
myapp

また myapp のルーティングを確認すると、先程デプロイした /hello が存在する事が確認できます。

$ fn list routes myapp
PATH    IMAGE                   ENDPOINT
/hello  my_dockerhub_username/hello:0.0.2     localhost:8080/r/myapp/hello


デプロイした関数の実行

Fn サーバへデプロイした関数を実行してみます。
関数の呼び出しには fn call コマンドを使用します。

ローカルで実行した時と同じように、デプロイした関数を実行できます。

$ fn call myapp /hello
{"message":"Hello World"}
$ echo -n '{"name":"Jason"}' | fn call myapp /hello
{"message":"Hello Jason"}

また、デプロイした関数は HTTP 経由でも実行する事ができます。

$ curl -H "Content-Type: application/json" http://localhost:8080/r/myapp/hello
{"message":"Hello World"}
$ curl -H "Content-Type: application/json" -d '{"name": "Jason"}' http://localhost:8080/r/myapp/hello
{"message":"Hello Jason"}


ダッシュボード(おまけ)

Fn Project には UI が用意されており、ダッシュボードで関数のメトリクスを参照する事ができます。

github.com

f:id:dhigashi:20180731185914p:plain

先程デプロイした関数とそのルーティングや、呼び出された数などを確認する事ができました。

まとめ

今回は チュートリアル に沿ってFn Project を簡単に触ってみました。

Fn Project には Fn Flow という機能があり、セッション資料では以下のように説明されています。

Fork-join/連鎖/遅延/エラーハンドリングなどの要素を含む高信頼、スケーラブルな長期に渡る実行が可能なfunction

次はこちらを使用してより実用的なアプリケーションを作成してみたいと思います。


この記事が気に入ったら
「いいね!」

この記事を書いた人


関連コンテンツ

CONTACT お問い合わせ

Cloudiiのサービスやプロダクトについて
興味をお持ちの方は、
お気軽にお問い合わせください。