11
7

More than 3 years have passed since last update.

AWS Lambda、FlaskとOpenCVの環境構築

Last updated at Posted at 2019-11-11

はじめに

  • AWS LambdaでのOpenCVの環境構築は、大変です。具体的には、デプロイ環境の構築が大変です。
  • デプロイ環境は、AWSCLIServerless Framework等色々な物が必要です。
  • 今回も、以前作成した顔認識アプリをLambdaへ移植します。ソースコードは、同一です。上記のデプロイに関する設定ファイルが異なる程度です。
  • ソース一式は ここ です。

概要

  • Mac
    • 顔認識アプリ
      • Flask
      • OpenCV
      • Python
    • デプロイツール等
      • AWSCLI
      • Docker
      • Homebrew
      • Node.js
      • Serverless Framework
  • AWS
    • API Gateway
    • CloudFormation
    • CloudWatch
    • IAM
    • Lambda
    • S3

Homebrew

  • まず、各種ツールインストールのためのHomebrewを入れます。
  • これは、説明割愛でOKですよね?
$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

AWSCLI

  • AWSでIAMユーザーを作ります。今回は、serverlessにしました。
  • プログラムによるアクセスを有効にします。
  • アクセス許可は、AdministratorAccessにします。
  • アクセスキーIDとシークレットアクセスキーを控えます。

image.png
image.png
image.png

  • AWSCLIをインストールして、上記のアクセスキーIDとシークレットアクセスキーを登録します。
  • リージョンは、東京(ap-northeast-1)にしました。
  • ユーザー一覧を表示で出来るはずです。
$ brew install awscli

$ aws configure
AWS Access Key ID [None]: xxxxxxxxxxxxxxxxxxxx
AWS Secret Access Key [None]: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Default region name [None]: ap-northeast-1
Default output format [None]:

$ aws iam list-users

Node.js

  • Node.jsをインストールします。これは、後述のServerless Frameworkをインストールするためです。
  • npmと言う、パッケージ管理システムもインストールされるはずです。
$ brew install node

Serverless Framework

  • Serverless Frameworkは、各種クラウド(AWS、Azure、GCP等)でサーバレス環境構築を簡単にしてくれます。
  • Flaskのための、WSGIやrequirements.txtのプラグインも有り、かなり楽が出来ます。
  • 正直、これが無いとコントロールパネルポチポチで相当辛いと思う。

インストール

  • npmでserverlessをインストールします。
$ npm install -g serverless

プロジェクト作成

  • python3のプロジェクトを作成します。
  • プロジェクト名とフォルダ名は、flask_opencvにしました。
  • handler.pyは、参考で作成されます。今回は、顔認識アプリのmain.pyを利用するので、削除します。
  • serverless.ymlは、この後書き換えます。
$ serverless create --template aws-python3 --name flask_opencv --path flask_opencv
省略
Serverless: Successfully generated boilerplate for template: "aws-python3"

package.jsonの作成

  • パッケージ管理用の package.jsonを作成します。
$ npm init -f
{
  "name": "flask_opencv",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

プラグインのインストール

serverless-wsgi

  • Flask、DjangoやPyramid等のWSGIアプリのためのプラグインです。
  • Lambdaでは、LambdaとFlaskの間にこのWSGIプラグインを使うのが人気の様です。
    • HerokuやGoogle App Engineでは、Gunicornを使いました。
  • https://github.com/logandk/serverless-wsgi

serverless-python-requirements

  • requirements.txtを元に関連ライブラリをまとめてくれます。
  • デプロイ時にDockerを活用する事で、OpenCVの様なライブラリも利用可能にしてくれます。

serverless-apigw-binary

  • API Gatewayで、送受信時にバイナリデータを扱うための設定をしてくれます。
  • API Gatewayは、デフォルトでは、テキストでデータを扱うため、画像等の場合は、そのまま扱う様にする必要があります。

インストール

  • 上記3種をインストールします。package.jsonに追加されるはずです。
$ npm install --save-dev serverless-wsgi serverless-python-requirements serverless-apigw-binary

$ cat package.json
{
  "name": "flask_opencv",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "serverless-apigw-binary": "^0.4.4",
    "serverless-python-requirements": "^5.0.1",
    "serverless-wsgi": "^1.7.3"
  }
}

serverless.yml

  • 今回の設定ファイルの中心ファイルです。ここに、デプロイの設定を記載します。
  • service: は分かりやすい名前を適当につけてOKです。ただし、_など使えない文字が有ります。
  • provider: は、AWS、Python3.7、東京リージョン、タイムアウトは30秒など指定します。
  • provider: stage: は、デフォルトで dev が指定されます。場合に応じて stgprod などへ変更して下さい。
  • plugins: は、上記でインストールしたプラグインを記載しています。
  • functions: main: handler: は、wsgi_handler.handlerを指定します。つまり、Lambdaは、serverless-wsgiを経由してFlaskへアクセスする事になります。
  • functions: main: events: は、httpのすべてのアクセスを通過させています。
  • custom: wsgi: app: は、main.pyappを対象とするようにします。
  • custom: pythonRequirements: dockerizePip: は、Dockerを使って、requirements.txtのライブラリをパッケージします。このおかげで、OpenCVを利用できる様になります。
  • custom: apigwBinary: types: は、API Gatewayでバイナリデータをテキストデータへ変換しない様にするためのものです。今回は、顔画像の送信は、POSTでmultipart/form-dataを使います。顔画像の受信は、生jpegなのですが、image/jpegではうまく行かず、text/htmlを追加したらOKでした。このあたりの理由は、調べきれていません。
$ cat serverless.yml
service: flask-opencv
provider:
  name: aws
  runtime: python3.7
# stage: dev
  region: ap-northeast-1
  timeout: 30
plugins:
  - serverless-apigw-binary
  - serverless-python-requirements
  - serverless-wsgi
functions:
  main:
    handler: wsgi_handler.handler
    events:
      - http: ANY /
      - http: ANY {proxy+}
custom:
  wsgi:
    app: main.app
    packRequirements: false
  pythonRequirements:
    dockerizePip: true
  apigwBinary:
    types:
#     - 'image/jpeg'
      - 'multipart/form-data'
      - 'text/html'

Docker

  • あと少しでデプロイ出来ます。
  • 上記で、serverless-python-requirementsのDocker機能を利用してOpenCVのライブラリを利用すると話ました。
  • Install Docker Desktopを参考にインストールして下さい。
  • もしくは、下記でもOKなはずです。
$ brew install docker

顔認識アプリ

デプロイ

  • いよいよ、デプロイです。
  • requirements.txt を読み込んで、Docker Image lambci/lambda:build-python3.7 を利用して docker runしています。
  • そのあと、CloudFormationを利用して、S3バケットを作成し、ソース、パッケージ等のzipがアップロードされています。
  • 引き続き、CloudFormationがIAMロール、API Gateway、CloudWatch、Lambdaを作成します。
  • 作成が終わると、エンドポイントが表示されます。
$ serverless deploy -v
省略
Serverless: Stack update finished...
Service Information
service: flask-opencv
stage: dev
region: ap-northeast-1
stack: flask-opencv-dev
resources: 12
api keys:
  None
endpoints:
  ANY - https://dlhkrgpmfi.execute-api.ap-northeast-1.amazonaws.com/dev
  ANY - https://dlhkrgpmfi.execute-api.ap-northeast-1.amazonaws.com/dev/{proxy+}
functions:
  main: flask-opencv-dev-main
layers:
  None

動作確認

  • 上記のエンドポイントへアクセスします。
  • 画像(jpeg)と処理回数(1〜100)を送信し、顔認識の画像を受信します。
  • 処理回数は、性能評価用に準備したものです。今回は、10回にします。

image.png

送信画像

  • 顔認識に使う画像は、一部界隈ではおなじみの顔画像を使いました。
  • Heroku用アプリ、Google App Engine用アプリで利用した物と同じです。

image.jpeg

ログの確認

  • 今回は、約9秒でした。1回あたり、0.9秒ですね。Google App Engineよりは速く、Herokuよりは遅いって感じか。
  • まぁ、時間帯や色々違うし、参考程度にしておきます。
$ serverless logs -f main
START RequestId: f88920f5-27d1-417f-bada-4bafde912fc2 Version: $LATEST
opencv version: 4.1.1, elapsed second: 9.593120813369751

おわりに

  • AWS LambdaでFlaskとOpenCVを使う方法と動作確認をしました。
  • 正直、Serverless Frameworkや関連プラグインが無いと辛いんだろうなぁと思いました。しかし、これらのおかげで、コントロールパネルをポチポイせずに簡単な作業となりました。
  • あと、エンドポイントに関しては、Serverless Domain Managerを使うと、ドメインを利用出来たり、パスを修正出来そうです。
  • 今後は、Azureで同様の事をやってみたいと思います。
11
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
7