相変わらず、 serverless に勤しんでいる遠藤です。
今回は、 前回のブログ で Chalice 触ってみると宣言したので、実際にちょっと触ってみた記事になります。
Chalice とは
Githubの説明によれば...
Chaliceは、Pythonでサーバーレスアプリを作成するためのフレームワークです。
AWSLambdaを使用するアプリケーションをすばやく作成してデプロイできます。
Chaliceは以下の機能しています
- アプリを作成、デプロイ、管理するためのコマンドラインツール
- Amazon API Gateway、Amazon S3、Amazon SNS、Amazon SQS、およびその他のAWSサービスと統合するためのデコレータベースのAPI
- 自動IAMポリシー生成
とのことです。
環境準備
環境構築は、ほぼ以下の通りに進めれば問題ないと思います。
https://aws.github.io/chalice/quickstart.html
python のバージョン管理などにより、コマンドが若干違いましたので、メモとして残しておきます。
公式の Quick Start では venv を使っていますが、私は pyenv を使いました。
開発環境
OS macOS Monterey
pyenv 1.2.21-6-g2bf6111f
Python 3.9.1
pip 20.2.3
実行コマンド
プロジェクトディレクトリを作成
$ mkdir chalice_sample
$ cd chalice_sample
python のバージョンを指定
$ pyenv install 3.9.1
$ pyenv local 3.9.1
chalice のインストール
$ python -m pip install chalice
これで環境準備は終わりです。
インストールできたか確認するために、 --help
を実行してみても良いと思います。
$ chalice --help
Usage: chalice [OPTIONS] COMMAND [ARGS]...
Options:
--version Show the version and exit.
--project-dir TEXT The project directory path (absolute or
relative).Defaults to CWD
--debug / --no-debug Print debug logs to stderr.
--help Show this message and exit.
Commands:
delete
deploy
dev Development and debugging commands for chalice.
gen-policy
generate-models Generate a model from Chalice routes.
generate-pipeline Generate a cloudformation template for a starter CD...
generate-sdk
invoke Invoke the deployed lambda function NAME.
local
logs
new-project
package
url
新規プロジェクトの作成
以下のコマンドを一発叩くだけです。
$ chalice new-project {project_name}
すると、 current ディレクトリに project_name
ディレクトリが作成されます。
$ cd {project_name}
$ ls -la
drwxr-xr-x 6 endo staff 192 1 31 16:14 .
drwxr-xr-x 5 endo staff 160 1 31 16:14 ..
drwxr-xr-x 3 endo staff 96 1 31 16:14 .chalice
-rw-r--r-- 1 endo staff 37 1 31 16:14 .gitignore
-rw-r--r-- 1 endo staff 737 1 31 16:14 app.py
-rw-r--r-- 1 endo staff 0 1 31 16:14 requirements.txt
プロジェクトの中身
デフォルトで生成される app.py の中身は以下のようになっています。(コメントアウト部分は除いています。)
node.js の express で web サーバを構築した時と同じような雰囲気で書けますね。
from chalice import Chalice
app = Chalice(app_name='test_project')
@app.route('/')
def index():
return {'hello': 'world'}
コメントアウトされている部分は以下のようになっていて、 path パラメータの取得や、リクエストボディの取得も、特に違和感はなさそうです。
@app.route('/hello/{name}')
def hello_name(name):
# '/hello/james' -> {"hello": "james"}
return {'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.current_request.json_body
# We'll echo the json body back to the user in a 'user' key.
return {'user': user_as_json}
local 実行
では、こちらを local で実行してみます。
$ chalice local
Serving on http://127.0.0.1:8000
Restarting local dev server.
Serving on http://127.0.0.1:8000
などとログが出力され、 curl を叩けばちゃんと応答が返ってきます。
$ curl http://127.0.0.1:8000
{"hello":"world"}
port の変更や、 stage の変更も可能です。
デフォルトは以下の設定になっています。
$ chalice local --stage dev --port 8000
stage は config.json に細かく設定を書くことで、環境変数などを切り替えることができます。
また、コードを書き換えて保存すると、自動でリスタートしてくれるので、プロセスの再起動なども必要ありません。
(フロント開発のホットリロードみたいなイメージですね。)
debugする
前回のブログ で書いたように、こちらも PyCharm を使ってデバッグ実行が可能です。
$ chalice local --stage dev --port 8000
すると、 アタッチ可能なプロセスに出てきますので、(なぜか2つ出る)
アタッチした後に、 curl などを叩くと
$ curl http://127.0.0.1:8000/users -X POST \
--header 'Content-Type: application/json' \
--data-raw '{"hoge":"fuga"}'
ちゃんと止める事ができました。
ただし、上記で書いた通り、コードを書き換えた場合は、自動でプロセスが再起動してしまうので、毎回アタッチする必要があります。
(ちょっと不便です)
deploy
では、実際にデプロイすると何が作成されるか見てみます。
まず、初期状態でデプロイしてみます。
AWS のデフォルトプロファイルを正しく設定している人は、以下のコマンドでデプロイできます。
$ chalice deploy
いくつか使用していて、プロファイルを切り替えたい方はオプションを付けます。
$ chalice deploy --profile {aws_profile_name}
オプションで region を付けることはできないので、 ~/.aws/config
に region を書いておく必要があります。
[profile aws_profile_name]
region = ap-northeast-1
では、実際にコマンドを叩いた時の出力を確認します。
$ chalice deploy --profile xxxxxxxxxxxx
Creating deployment package.
Reusing existing deployment package.
Creating IAM role: helloworld-dev
Creating lambda function: helloworld-dev
Creating Rest API
Resources deployed:
- Lambda ARN: arn:aws:lambda:ap-northeast-1:xxxxxxxxxxxx:function:helloworld-dev
- Rest API URL: https://xxxxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/api/
というわけで、
- IAM Role
- Lambda
- Rest API(API Gateway)
の3つを作成していることが分かりました。
IAM Role の中身
IAM Role の中身は以下の通りで、CloudWatch ログに書き込みをするための権限だけを持っていました。
必要最低限という感じで分かりやすいです。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:*:logs:*:*:*"
}
]
}
Lambda の中身
特に何も変化なく、そのまま deploy されていました。
モジュールがでかくなると、 AWS コンソールではコードが見えなくなってしまうのですが、特にそんなこともありませんでした。
Rest API(API Gateway) の中身
シンプルに GET を待ち受けるだけの API Gateway が作成されました。
変更してデプロイしてみる
コードの修正
コメントアウト部分を有効にしてみます。
from chalice import Chalice
app = Chalice(app_name='helloworld')
@app.route('/')
def index():
return {'hello': 'world2'}
@app.route('/hello/{name}')
def hello_name(name):
# '/hello/james' -> {"hello": "james"}
return {'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.current_request.json_body
# We'll echo the json body back to the user in a 'user' key.
return {'user': user_as_json}
これで、デプロイします。
$ chalice deploy --profile xxxxxxxxxxxx
Creating deployment package.
Updating policy for IAM role: helloworld-dev
Updating lambda function: helloworld-dev
Updating rest API
Resources deployed:
- Lambda ARN: arn:aws:lambda:ap-northeast-1:xxxxxxxxxxxx:function:helloworld-dev
- Rest API URL: https://xxxxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/api/
デプロイは、 10 秒くらいで終わります。
Lambda の中身
エンドポイントを増やしても、関数は1つだけになるみたいです。
ログのストリームも1つみたいなので、この辺りは好みが分かれそうですね。
(細かく設定できるのかは、要調査です。)
Rest API(API Gateway) の中身
すごい。
コードを変えただけなのに、リソースがちゃんと追加されています。
同名のプロジェクトをデプロイしてみる
ふと気になって、手元で同名のプロジェクトを新規作成してデプロイしてみました。
すると、 API Gateway は新規作成され、(API ID が異なるもの) Lambda は上書きされました。
デプロイに成功すると、 deployed/dev.json
が生成され、その中に API ID の情報が書いてあったので、このファイルをちゃんと共有しておかないといけなさそうですね。
感想
というわけで、プロジェクトの準備からデプロイまでざっと一通り見てみました。
ちょっとした API をデプロイするのであれば、 Chalice の方が serverless よりもはるかにお手軽で高速にできました。
serverless の場合は、 Python のバージョンだけでなく、 npm などにも依存してくるので、依存関係が Python だけで完結する Chalice はとても好印象です。
ただし、シンプルに API だけが欲しいプロジェクトというのはあまりなく、 AWS の各種リソースと組み合わせるのが一般的かなと思います。
今回は、ほぼ初期状態でデプロイしてみただけですが、 CloudFormation を使ったり、その他のリソースと組み合わせたり、 API Gateway 以外のトリガーで起動させることなんかもできるようです。
これらを採用してしまうと、メリットである爆速なデプロイが実現できなくなる気もします。
今後は、その辺りをもう少し深掘りしてみて、最終的に実務で利用できそうか、考えてみたいと思います。
2022/07 追記
CDK でデプロイを試した記事を掲載しました!
こちらもあわせてご覧ください。
https://note.milldea.com/posts/chalice-with-aws-cdk-deploy