fuzzy study

仕事・趣味で勉強したことのメモ

Swagger codegenで作ったFlaskアプリをAWS Lambdaにデプロイして使う

WEB+DB PRESS Vol.105 にあった記事にあった、FlaskアプリをAWS Lambdaにデプロイして使う方法を少しアレンジし、Swagger codegenで作ったFlaskアプリをデプロイしてみたので、手順のメモ。

手順メモ

Swagger codegen

swagger editorでAPI定義を書き、サーバコードをダウンロード。(Generate Server -> python-flask)

ちなみにこのとき、python-flaskをクリックしても全く反応しないんだけど、裏でHTTPS接続でエラーが出てるみたいで、ChromeならF12とかでデバッグログ出して、エラーになってるURLへ直接ブラウザで接続したらダウンロードできた。

f:id:fuzzy0:20180812234440p:plain

ローカルでコードの編集

フォルダ構成

mylambda/
├── functions
│   └── mylambda
│       └── main.py  # Lambdaのエントリポイントを記述するファイル
├── project.json  # Apexの設定ファイル
├── requirements.txt  # Lambdaのコンテナにデプロイするパッケージのインストール用
└── src
    └── swagger_server  # codegenの中のディレクトリをコピー

mylambdaのmain.pyには、swagger_server内の__main__.pyのほぼコピペの内容を記載する。

import sys
import pathlib

# 記事の通り
lib_path = str(pathlib.Path("./lib").absolute())
sys.path.append(lib_path)

import awsgi

# swaggerのコードをほぼコピペ
# パスの階層とかをちょっといじってあげる
import connexion
from swagger_server import encoder

def lambda_handler(event, context):
    app = connexion.App(__name__, specification_dir='./lib/swagger_server/swagger/')
    app.app.json_encoder = encoder.JSONEncoder
    app.add_api('swagger.yaml', arguments={'title': 'MyAPI'})
    return awsgi.response(app, event, context)

Apexの導入

公式の手順に沿って実施。

Apexの設定(project.json)の記述

{
  "name": "mylambda",
  "description": "",
  "memory": 128,
  "timeout": 5,
  "role": "arn:aws:iam::XXXXXXXXXXXX:role/mylambda_lambda_function",
  "environment": {},
  "runtime": "python3.6",
  "handler": "main.lambda_handler",

  "hooks": {
    "build": "mkdir ./lib && cp -r ../../src/* ./lib && pip install -r ../../requirements.txt -t ./lib"
  }
}
  • runtimeをpython3.6にする
  • hooksにて、デプロイ時に事前実行するコマンドを定義する。ここではWebDBの記事同様の手順で以下を行うようにする。
    • srcの中身をfunctions/mylambda/libへコピー
    • functions/mylambda/libへpipパッケージをインストール

requirements.txtの記述

Flask, aws-wsgi, connexionが必須。それ以外は自分のアプリに合わせて追加する。
DynamoDB使うならboto3とか。

Apexを使ってデプロイ

project.jsonのあるディレクトリにて、コマンドapex deployを実行。

このとき、AWSAPI接続できるよう、以下が必要。

  • awscliをインストール済みであること
  • 適切な権限を持ったユーザ・ロールのAPIアクセスキーを環境変数に設定済みであること(適切な権限は状況によるっぽいが、IAM作成権限が必要だったので、結構強い権限が要ると思う)

API Gatewayの設定

f:id:fuzzy0:20180809234551p:plain

メソッドの作成にて、図のようにプロキシリソースにチェックを入れれば、自動的にリクエストをスルーパスする設定になる。

次の画面でLambdaも指定してあげれば完了。

API デプロイ

APIGatewayにてAPIのデプロイをする。

ステージ名はswagger定義のパスには入らない。
swaggerのパス定義に/hogeapi/fuga とかしたら、https://xxxxx.amazonaws.com/[ステージ名]/hogeapi/fugaでアクセスできる。

デバッグしたいとき

上記でうまくいったんだけど、途中うまくいかなかったときにデバッグで便利だったことのメモ。

Lambdaのテスト

Lambdaの関数画面上部のテストでは、作成時にひな型を選べる。
この中からAPIGateway AWS Proxyのひな型を選ぶと、APIGatewayからLambda統合で呼び出すときのリクエストが再現できる。
パスとhttpmethodあたりだけ書き換えてあげればいい。

Cloudwatch

結果的にはできなかったんだけど、たぶんAPI Gatewayの設定でCloudWatchログを吐くようにしてあげればリクエスト時のエラーを確認できる。気がする。

その他

  • Apexのフォルダ構成とか、swaggerのmainをコピペとか、APIGatewayの設定ポチポチとか、ちょっとめんどい。

Zappa

その後、Zappaとかいう素敵感のあるものを見つけた!

  • ZappaはFlaskコードをそのままAPIGateway含めてサーバレス化(Lambdaデプロイ+APIGateway作成)をしてくれるすごいやつだった。
  • 使い方は、試すくらいなら公式チュートリアルでいけるし、ググるといくらか記事がある。
  • デプロイ時、/に対するヘルスチェックが入り、失敗するとデプロイ中断されるので、Swagger codegenしたものをデプロイするときは、/に対するGETに正常なレスポンスを返すように設計されている必要がありそう。(未検証)

以上。