#概要
AWSを利用してシンプルなサーバーレスWebAPIを作成します
※大雑把に構築の流れだけ追っていくので、細かいことは都度調べてください
#目次
- ローカルで仮想環境の構築(キーワード:pipenv)
- 開発環境の構築(VSCode)
- プログラムの作成(Flask)
- IAMユーザーの作成(AWS)
- ローカル環境をAWSにデプロイ(zappa)
- おまけ
- 参考サイト
#ローカルで仮想環境の構築(pipenv)
pipenvを使用して仮想環境を構築します。
環境変数に以下を追加します。
仮想環境で使用するインタープリターや参照パッケージを、作業フォルダに入れる設定です。(.venv)
PIPENV_VENV_IN_PROJECT = TRUE
pipenvをインストールします。
コマンドラインで以下を実行します。
pip install pipenv
バージョンが表示されればインストールできています。
pipenv --version
作業フォルダを作成して、初期化を行います。
コマンドラインで作成した作業フォルダに移動して、以下を実行します。
pipenv --three
「three」はpython3系のインストールコマンドです。バージョンを指定する場合は、以下のように実行します。
pipenv --python 3.7
初期化に成功すると、作業フォルダに以下のフォルダとファイルが作成されます。
.venv
Pipfile
#開発環境の構築(VSCode)
VSCodeで開発環境を構築します。(VSCodeは良いぞ...)
VSCodeで作業フォルダを開きます。
「ファイル」→「フォルダーを開く」
VSCodeは、pythonファイルを扱えるようにするために、拡張機能を入れる必要があります。
「表示」→「拡張機能」から「python」で検索してインストールしましょう。
pythonファイルを作成します。
テキトーに「app.py」などのファイルを作成します。作成したpythonファイルを選択すると、エディターの左下に実行する環境が表示されます。
ここから、作業フォルダのpipenvを指定します。
設定ファイルを編集します。
以下のファイルで、仮想環境等のパス設定、フォーマッター、Lintの設定を行います。参考
{
"python.pythonPath": "[ワークスペースフォルダ]\\.venv\\Scripts\\python.exe",
// 拡張機能のロード時にターミナルでPython環境をアクティブにする。
"python.terminal.activateEnvInCurrentTerminal": true,
// 仮想環境のパス。作成した仮想環境を指定する。
"python.venvPath": "{$workspaceFolder}/.venv",
"python.autoComplete.extraPaths": [
"{$workspaceFolder}/.venv/Lib/site-packages",
],
// フォーマッターの設定。autopep8 を指定する。
"python.formatting.provider": "autopep8",
"python.jediEnabled": false,
// Lintの設定
"python.linting.mypyEnabled": true,
"python.linting.pylintEnabled": false,
}
パッケージをインストールします。
setting.json の設定を行うと、使用している依存パッケージをインストールするように促されます。
まず、ターミナルを表示して、仮想環境がアクティブになっているか確認します。
「表示」→「ターミナル」
以下のように「(qiita_test)」のように出ていればOK
(qiita_test) C:\~\qiita_test>
以下を実行して、パッケージをインストールします。
pipenv install autopep8 mypy --dev
また、サンプルソースように「Flask」「numpy」もインストールします。
pipenv install Flask numpy
「--dev」は、開発環境のみで使用するパッケージを指定するものです。つまり、AWSにデプロイするときは含まれないパッケージとなります。
#プログラムの作成(Flask)
簡単なサンプルプログラムを作成します。
リクエストに対して、json形式のレスポンスを返すWebAPIです。
作成したら実行してエラーが出ないか確認しましょう。
from flask import Flask, jsonify, request
import numpy as np
app = Flask(__name__)
app.config["JSON_AS_ASCII"] = False
@app.route("/")
def index():
return jsonify({"language": "パイソン"})
# exp:http://127.0.0.1:5000/sqrt?val=4
@app.route("/sqrt")
def getSqrt():
param = request.args.get('val')
val = int(param)
return jsonify({"sqrt": np.sqrt(val)})
# exp:http://127.0.0.1:5000/sqrt/4
@app.route("/sqrt/<value>")
def getSqrt2(value):
val = int(value)
return jsonify({"sqrt": np.sqrt(val)})
if __name__ == "__main__":
app.run(debug=True)
折り返し地点です。
#IAMユーザーの作成(AWS)
ここからは、ローカルで作成したWebAPIを、AWSにデプロイしていきます。
AWSアカウントには、ルートユーザーとIAMユーザーの2つがあります。
(親です):ルートユーザーは、すべての権限を持つアカウントです。IAMユーザーの管理も行います。
(子です):IAMユーザーは、プロジェクト単位や開発者単位で、個別に権限を持つアカウントです。
まず、ルートユーザーを作成し、AWSコンソールにログインした後に、IAMユーザーを作成します。
IAMユーザーは以下の2つを作成します。
zappaデプロイ用のアカウント
AWSコンソールで管理する用のアカウント
zappaからデプロイする用のポリシーを作成します。
ポリシーとはIAMユーザーに付与する権限のことです。
AWSコンソールにルートユーザーでログインし、画面上の「サービス」→「IAM」を選択します。
「ポリシー」を選択して、[ポリシーの作成]を押します。
「JSON」タブを選択して、ポリシーを書き込みます。
参考:Pythonで作るはじめてのサーバレスアプリケーション Kindle版
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"iam:AttachRolePolicy",
"iam:CreateRole",
"iam:GetRole",
"iam:PutRolePolicy"
],
"Resource": [
"*"
]
},
{
"Effect": "Allow",
"Action": [
"iam:PassRole"
],
"Resource": [
"*"
]
},
{
"Effect": "Allow",
"Action": [
"apigateway:DELETE",
"apigateway:GET",
"apigateway:PATCH",
"apigateway:POST",
"apigateway:PUT",
"events:DeleteRule",
"events:DescribeRule",
"events:ListRules",
"events:ListTargetsByRule",
"events:ListRuleNamesByTarget",
"events:PutRule",
"events:PutTargets",
"events:RemoveTargets",
"lambda:AddPermission",
"lambda:CreateFunction",
"lambda:DeleteFunction",
"lambda:GetFunction",
"lambda:GetFunctionConfiguration",
"lambda:GetPolicy",
"lambda:ListVersionsByFunction",
"lambda:RemovePermission",
"lambda:UpdateFunctionCode",
"lambda:UpdateFunctionConfiguration",
"cloudformation:CreateStack",
"cloudformation:DeleteStack",
"cloudformation:DescribeStackResource",
"cloudformation:DescribeStacks",
"cloudformation:ListStackResources",
"cloudformation:UpdateStack",
"cloudfront:updateDistribution",
"logs:DescribeLogStreams",
"logs:FilterLogEvents",
"route53:ListHostedZones",
"route53:ChangeResourceRecordSets",
"route53:GetHostedZone",
"s3:CreateBucket",
"dynamodb:*"
],
"Resource": [
"*"
]
},
{
"Effect": "Allow",
"Action": [
"s3:ListBucket"
],
"Resource": [
"*"
]
},
{
"Effect": "Allow",
"Action": [
"s3:DeleteObject",
"s3:GetObject",
"s3:PutObject",
"s3:CreateMultipartUpload",
"s3:AbortMultipartUpload",
"s3:ListMultipartUploadParts",
"s3:ListBucketMultipartUploads"
],
"Resource": [
"*"
]
}
]
}
[ポリシーの確認]を押して、「名前」を付けます。ここでは「zappa-simple-policy」としました。
[ポリシーの作成]を押して、zappa用のポリシーが出来ました。
zappa用のIAMユーザーを作成します。
(AWSコンソールにルートユーザーでログインし、画面上の「サービス」→「IAM」を選択します。)
- 「ユーザー」を選択して、[ユーザーを追加]を押します。
- 「ユーザー名」を指定します。ここでは、「zappa-simple-user」としました。
- 「アクセスの種類」で「プログラムによるアクセス」に☑します。
- [次のステップ:アクセス権限]を押します。
- [既存のポリシーを直接アタッチ]を選択して、検索欄で「zappa-simple-policy」と入力し、☑します。
- [次のステップ:タグ]を押します。(飛ばします)
- [次のステップ:確認]を押します。
- [ユーザーの作成]を押します。
- 作成に成功すると、アクセスキーIDとシークレットアクセスキーが表示されるので、メモっておきます。
AWSコンソールで管理する用のIAMユーザーを作成します。
- 「ユーザー」を選択して、[ユーザーを追加]を押します。
- 「ユーザー名」を指定します。ここでは、「qiita-test」としました。
- 「アクセスの種類」で「AWS マネジメントコンソールへのアクセス」に☑します。
- [次のステップ:アクセス権限]を押します。
- [既存のポリシーを直接アタッチ]を選択して、以下を選択します。
- AmazonAPIGatewayAdministrator
- AWSLambdaFullAccess
- AmazonDynamoDBFullAccess(今回は利用していないが、DynamoDBを利用する場合)
- IAMUserChangePassword(3で初回ログイン時にパスワードを変更する設定にした場合、自動で選択されます)
- [次のステップ:タグ]を押します。(飛ばします)
- [次のステップ:確認]を押します。
- [ユーザーの作成]を押します。
- 作成に成功すると、アクセスキーIDとシークレットアクセスキーが表示されるので、メモっておきます。
もう少し
#ローカル環境をAWSにデプロイ(zappa)
zappaというpythonの拡張機能を使って、作成したプロジェクトをAWSにデプロイします。
AWS CLIを設定します。
IAMユーザーの情報をプロファイル単位で管理するために、AWS CLIをインストールします。
参考:AWS CLIのインストール
pipからもインストールできるみたいです。参考:https://www.suzu6.net/posts/4/
コマンドプロンプトで以下を実行して、[default]のプロファイルを設定します。
とりあえずzappa用のIAMユーザー(zappa-simple-user)情報を設定しましょう。
aws configure
AWS Access Key ID [********************]:
AWS Secret Access Key [********************]:
Default region name [ap-northeast-1]:
Default output format [json]:
regionは東京です。
インストールフォルダ以下の credentials ファイルに、作成したzappa用のIAMユーザー(zappa-simple-user)情報を設定します。
メモ帳か何かで開いて編集しましょう。
[zappa-simple-user]
aws_access_key_id = ********************
aws_secret_access_key = ********************
zappaをインストールします。
ターミナルにて、仮想環境がアクティブになっていることを確認してから、以下を実行します。
pipenv install zappa
次に初期設定を行います。
zappa init
- デプロイ環境の名前の指定。(デフォルトでも可)
- AWSプロファイルの指定。先ほどcredentialsファイルに設定した「zappa-simple-user」を指定します。
- S3バケットを利用するための仮の名前の指定。(デフォルトでも可)
- アプリケーションの起動ファイルの指定。.appファイルとして指定します。今回は「app.py」を起動したいので、「app.app」を指定します。
- リージョンごとの最適化設定。特にパフォーマンスが必要なければデフォルトにします。
- 作成される設定情報が表示されます。問題なければ、Enterで初期設定を終了します。
デプロイします。
ターミナルにて、仮想環境がアクティブになっていることを確認してから、以下を実行します。
zappa deploy
成功すると以下のようにエンドポイントが表示されます。
リンクに飛ぶと、json形式の値が表示されます。
Deployment complete!: [リンク]
AWSで確認してみます。
AWSコンソールで管理する用のIAMユーザーで、AWSコンソールにログインします。
「サービス」→「API Gateway」または「Lambda」を選択すると、デプロイしたアプリケーションを確認することができます。
ハイ、オツカレー(  ̄▽)_
#おまけ
zappaコマンド
zappa update dev
zappa undeploy dev
zappa tail dev
課題
AWSのポリシーがいまいちわかっていない。(ので、本稿の設定はあくまで参考程度に)
githubを使ってバージョン管理も絡めてみる。
なんで?
- なんで、WebAPI作るの?
これから5G技術が普及することによって、オンライン環境は今より格段に拡がり、よりストレスレスな通信が可能になるから。
ユーザーの環境に依存しない開発ができ、色々なプラットフォームでリソースを共有できるから。
- なんで、Pythonなの?
機械学習を勉強する上で、パッケージが豊富で、スクリプトもわかりやすく、参考事例も多いから。
参考書やサイトでコーディングしたリソースを形にしたくて、色々考えた結果 WebAPI という技術に至ったから。
(参考書のほとんどは、colaboratory等でデータ分析して「はいできましたね。~終わり~」となっていて、じゃあ具体的にどう活用するの?ってずっとモヤモヤしてました)
- なんで、サーバーレスなの?
サーバーの構築技術にはあまり興味がなく、自分でサーバー立てるよりAmazonやMicrosoftのサービスを利用したほうが早そうだなって思ったから。
自前でサーバー運用するよりもコストパフォーマンスに優れているから。
#参考サイト
Windows + Python + PipEnv + Visual Studio Code でPython開発環境
Zappaを使ってPythonのコードをAWS Lambdaにデプロイする
参考書籍です。こちらの筆者の環境はOSXでエディターは特に使ってません。
Pythonで作るはじめてのサーバレスアプリケーション Kindle版