注目の記事

【新機能】Python Serverless Microframework for AWS(プレビュー版)が登場!

2016.07.12

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、せーのです。今日は昨今でのクラウド構築での主流となりつつある「サーバレスアーキテクチャ」を更に効率的に構築できる便利ツールをご紹介します。ちょっとワクワクしますよ。

できるだけ速く、できるだけ直感的に

AWSにてサーバレスアーキテクチャを実現するのに一番シンプルな方法は「Lambda + API Gateway」です。要件をREST APIの形に落とし込み、API Gatewayにデプロイ、URLを叩かれたらLambdaが連動して処理を開始する、というものです。Lambdaが自動的にスケールしてくれるので沢山のアクセスがきた時もうまいこと捌いてくれ、EC2無しでシステムの構築が可能となる、というものです。

しかし実際に組んだことがある方はわかるかと思いますが簡単なテストAPIを組むにしてもそこそこの準備が、特にAPI Gateway周りで必要となります。これをもっと直感的にパパっと組みたい。そんな願いを満たしてくれるのが今回プレビュー版としてリリースされた「Python Serverless Microframework for AWS」です。
このフレームワークの設計はPythonerにとってみればDjangoの一人勝ちを阻むかと今年注目されているマイクロフレームワークである「Flask」がベースになっています。軽量で取り回しの効きやすいフレームワークですね。

やってみる

とにかくどれだけ簡単か、見ていただきましょう。

インストール

インストールはPyPlかGithubからとなります。PyPlからサクッと入れてみます。
テストということでvirtualenvを使っておきます。virtualenvについてはこちらの記事を御覧ください。持っていない人は入れておきましょう。

sudo pip install virtualenv
virtualenv ~/.virtualenvs/chalice-demo
source ~/.virtualenvs/chalice-demo/bin/activate

pip install chalice

chalice...聖杯?どういう意味なんでしょう。

chalice --help
Usage: chalice [OPTIONS] COMMAND [ARGS]...

Options:
  --help  Show this message and exit.

Commands:
  deploy
  gen-policy
  local
  logs
  new-project

使うコマンドは現在5つです。簡単ですね。

新規プロジェクトを作る

次に新規プロジェクトを作ります。名前は最初らしく「helloworld」にしてみましょう。これもワンライナーです。

Tsuyoshis-iMac:chaliceTest Tsuyoshi$ chalice new-project helloworld
Tsuyoshis-iMac:chaliceTest Tsuyoshi$ ls
helloworld
Tsuyoshis-iMac:chaliceTest Tsuyoshi$ cd helloworld/
Tsuyoshis-iMac:helloworld Tsuyoshi$ ls -l
total 8
-rw-r--r--  1 Tsuyoshi  staff  783  7 12 06:57 app.py
-rw-r--r--  1 Tsuyoshi  staff    0  7 12 06:57 requirements.txt

プロジェクトを作ると[app.py]と[requirements.txt]という2つのファイル、隠しフォルダとして[.chalice]フォルダが作成されました。app.pyはプログラム本体、requirements.txtはFlaskで使うファイルでライブラリのバージョンを書き込むことで固定させるものです。ではapp.pyの中身を見てみましょう。

from chalice import Chalice

app = Chalice(app_name='helloworld')


@app.route('/')
def index():
    return {'hello': 'world'}


# The view function above will return {"hello": "world"}
# whenver you make an HTTP GET request to '/'.
#
# Here are a few more examples:
#
# @app.route('/hello/{name}')
# def hello_name(name):
#    # '/hello/james' -> {"hello": "james"}
#    {'hello': name}
#
# @app.route('/users/', methods=['POST'])
# def create_user():
#     # This is the JSON body the user sent in their POST request.
#     user_as_json = app.json_body
#     # Suppse we had some 'db' object that we used to
#     # read/write from our database.
#     # user_id = db.create_user(user_as_json)
#     return {'user_id': user_id}
#
# See the README documentation for more examples.
#

Pythonを知らない方でもコードを読むと何となくわかると思います。ルートパス('/')に対してindexという関数がマッピングされていて{'hello': 'world'}という値を返すんでしょうね。

デプロイ

ではまずそのままデプロイしてみます。。。とその前にAWSアカウントを確認しておいて下さい。~/.aws/configの[default]にAPI KEY, API SECRET KEY, REGIONが書いてあればOKです。

cat ~/.aws/config
[default]
region = ap-northeast-1
aws_access_key_id = XXXXXXXXXXXXXXXXXX
aws_secret_access_key = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

では、改めてデプロイです。

chalice deploy
Initial creation of lambda function.
Updating IAM policy.
Creating deployment package.
Lambda deploy done.
Initiating first time deployment...
Deploying to: dev
https://XXXXXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/dev/

なんと、これだけでLambda Functionの作成、API Gatewayの設定、IAM Policyまで自動的に行なってくれます。テストしてみましょう。

curl https://XXXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/dev/
{"hello": "world"}

できてます。。。すごい。環境を見てみます。

IAM Role

chalice1

CloudWatchへの権限が付いているようです。

chalice2

Lambdaもありました。

chalice3

API Gatewayもキチンとできてます。

chalice4

何も書いてないので流石に認証はそのままでした。

chalice5

これはすごいですね。30秒で環境ができました。

パラメータ付きのAPIを作ってみる

次に動的なパラメータのあるREST APIを作ってみたいと思います。app.pyにメソッドを一つ追加します。

from chalice import Chalice

app = Chalice(app_name='helloworld')


@app.route('/')
def index():
    return {'hello': 'world'}

@app.route('/{name}/hello')
def hello(name):
    return {'hello': name}

ではデプロイしてみます。

chalice deploy
Updating IAM policy.
Updating lambda function...
Regen deployment package...
Sending changes to lambda.
Lambda deploy done.
API Gateway rest API already found.
Deleting root resource id
Done deleting existing resources.
Deploying to: dev
https://XXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/dev/

できました。テストします。

curl https://XXXXXXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/dev/seino/hello
{"hello": "seino"}

あっという間ですね。

ログを出してみる

次にログを出してみたいと思います。先ほどのメソッドにワンライナー追加します。

@app.route('/{name}/hello')
def hello(name):
    print('return hello to {}'.format(name))
    return {'hello': name}

デプロイしてテストします。

chalice deploy
curl https://XXXXXXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/dev/seino/hello
{"hello": "seino"}

結果は変わりません。ではログを見てみます。

chalice logs 
........
2016-07-12 07:39:16.239000 999bfb START RequestId: 4c5b38b7-47b8-11e6-b927-857ad7ef1c1a Version: $LATEST
2016-07-12 07:39:16.246000 999bfb return hello to seino
2016-07-12 07:39:16.246000 999bfb END RequestId: 4c5b38b7-47b8-11e6-b927-857ad7ef1c1a
2016-07-12 07:39:16.246000 999bfb REPORT RequestId: 4c5b38b7-47b8-11e6-b927-857ad7ef1c1a	Duration: 0.41 ms	Billed Duration: 100 ms 	Memory Size: 128 MB	Max Memory Used: 15 MB

ログが吐かれている事を確認しました。このログを見る限りLambdaのログですね。ということはCloudWatch Logsのものでしょうか。見てみます。

chalice6

chalice7

ありました。ここを見てるんですね。

まとめ

いかがでしたでしょうか。ものすごく簡単です。現在ではこの他にもエラーメッセージの記述、複数メソッドの同時記述(PUTとPOST、とか)、ステージの選択、等もう少し細かい制御が可能となります。これが進化すると開発は非常に楽になりますね!

参考リンク