はじめに
運用レスのインフラ基盤でアプリ動かしたいと考え、
Flask(pythonのフレームワーク)を使った簡単なアプリをLambdaで動かしてみた。
※ すでにpython3.6がインストールされている前提(Cloud9は初期から入っている)
※ すでにNode.jsがインストールされており、npmコマンドが打てる前提(Cloud9は初期から入っている)
所要時間
本手順は30分ほどで完了する想定です。(60分あれば十分なハズ)
モジュールのインストール
ここではCloud9でserverless frameworkを用いてLambdaにFlaskをデプロイする方法を載せます。
npmがインストールされていることを確認
$ npm --version
npmのバージョンアップ
$ npm update -g
serverless frameworkのインストール
$ npm install -g serverless
labmdaでflaskを使用するためのモジュールをインストール
$ npm install --save-dev serverless-wsgi serverless-python-requirements
Flaskのインストール
$ sudo python -m pip install flask
Serverless Frameworkの初期設定
IAMユーザ作成
Serverless Framework用のIAM作成 Serverless Frameworkに管理者権限を渡すと権限がでかすぎるので、 下記のポリシーを付与したIAMユーザを作成した。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "cloudformation0",
"Effect": "Allow",
"Action": [
"cloudformation:DescribeStackEvents",
"cloudformation:CreateStack",
"cloudformation:DeleteStack",
"cloudformation:UpdateStack",
"cloudformation:DescribeStackResources",
"cloudformation:DescribeStackResource",
"cloudformation:DescribeStacks",
"cloudformation:ListStackResources"
],
"Resource": "arn:aws:cloudformation:ap-northeast-1:<アカウントID>:stack/<サービス名>*"
},
{
"Sid": "cloudformation1",
"Effect": "Allow",
"Action": [
"cloudformation:ValidateTemplate"
],
"Resource": "*"
},
{
"Sid": "iam",
"Effect": "Allow",
"Action": [
"iam:*"
],
"Resource": [
"arn:aws:iam::<アカウントID>:policy/<サービス名>*",
"arn:aws:iam::<アカウントID>:role/<サービス名>*"
]
},
{
"Sid": "s3",
"Effect": "Allow",
"Action": [
"s3:Get*",
"s3:List*",
"s3:Put*",
"s3:CreateBucket",
"s3:DeleteBucket",
"s3:DeleteBucketPolicy",
"s3:DeleteObject"
],
"Resource": "arn:aws:s3:::<サービス名>*"
},
{
"Sid": "cloudwatch",
"Effect": "Allow",
"Action": [
"logs:DescribeLogGroups",
"logs:CreateLogGroup",
"logs:DeleteLogGroup",
"logs:PutRetentionPolicy"
],
"Resource": "arn:aws:logs:ap-northeast-1:<アカウントID>:*"
},
{
"Sid": "cloudwatchevents",
"Effect": "Allow",
"Action": [
"events:PutRule",
"events:DescribeRule",
"events:DeleteRule",
"events:PutTargets",
"events:RemoveTargets"
],
"Resource": "arn:aws:events:ap-northeast-1:<アカウントID>:rule/<サービス名>*"
},
{
"Sid": "apigateway",
"Effect": "Allow",
"Action": [
"apigateway:*"
],
"Resource": "arn:aws:apigateway:ap-northeast-1::*"
},
{
"Sid": "lambda",
"Effect": "Allow",
"Action": [
"lambda:GetFunction",
"lambda:DeleteFunction",
"lambda:CreateFunction",
"lambda:GetFunctionConfiguration",
"lambda:ListVersionsByFunction",
"lambda:AddPermission",
"lambda:RemovePermission",
"lambda:PublishVersion",
"lambda:UpdateFunctionCode",
"lambda:ListAliases",
"lambda:UpdateFunctionConfiguration"
],
"Resource": "arn:aws:lambda:ap-northeast-1:<アカウントID>:function:<サービス名>*"
}
]
}
<サービス名>:この後serverless.ymlで設定するサービス名
<アカウントID>:各自のAWSのアカウントID
権限を絞るのがすごく苦労しました。(IAMとAPI Gatewayは結局絞り切れなかった。)
まだ絞れる場合は教えてもらえると助かります。
参考:https://docs.aws.amazon.com/index.html
参考:https://blog.kozakana.net/2019/12/serverless-framework-deploy-policy-for-aws/
Serverless Framework用のAWSアカウント設定
$ serverless config credentials --profile sls --provider aws --key <アクセスキーID> --secret <シークレットアクセスキー>
※ profileを指定しないと[Defalt]のアカウントが使用されます。
Flaskアプリの構築
プロジェクト作成
$ sls create -t aws-python3 -p <プロジェクト名>
$ cd <プロジェクト名>
requirements.txtの作成
pythonで使用するライブラリはrequirements.txtで指定しないと
Lambdaにデプロイする際にデプロイモジュールの中に含まれない。
$ pip freeze > requirements.txt
requirements.txtの中身はデプロイしたいライブラリだけ残して後は消します。
下記は今回残しておいたものです。
boto3==1.12.14
Flask==1.0.4
requests==2.22.0
serverless-wsgi==1.7.5
serverlessrepo==0.1.9
Werkzeug==1.0.0
Flaskアプリの配置
今回は動作することまで確認するので、プロジェクトディレクトリ配下に以下の内容のmain.pyを配置します。
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello, Flask!"
if __name__ == "__main__":
app.run()
serverless.ymlの編集
プロジェクトディレクトリ配下にあるserverless.ymlを編集します。
service:
name: <サービス名>
plugins:
- serverless-python-requirements
- serverless-wsgi
provider:
name: aws
runtime: python3.6
stage: ${opt:stage, 'dev'}
region: ap-northeast-1
timeout: 300
memorySize: 2048 # Overwrite the default memory size. Default is 1024
deploymentBucket: ${self:service}-deployment
custom:
name: ${self:service.name}
wsgi:
app: main.app
packRequirements: false
stage: ${opt:stage, self:provider.stage}
logRetentionInDays:
dev: "30"
stg: "60"
prod: "90"
pythonRequirements:
dockerizePip: non-linux
functions:
app:
handler: wsgi.handler
events:
- http: ANY /
- http: 'ANY {proxy+}'
※ logRetentionInDaysはログを何日分保存するかの設定です。デプロイしたLambdaのログはCloudWatch Logsに吐き出されますが、この保持期間を設定しています。
プロジェクトディレクトリ内のファイル ここまでで、プロジェクトディレクトリ内には以下が配置されているかと思います。
- requirements.txt
- main.py
- serverless.yml
Lambdaモジュールデプロイ先のS3構築
上記のyamlの中身に「deploymentBucket: ${self:service}-deployment」という部分があったが、
ここでLambdaのデプロイ先S3を指定している。
特に指定しなければServerless FrameworkがS3を作ってくれるが、
名前がいまいちだと感じたため自分で作ったS3を指定することにした。
S3バケット名は${self:service}-deploymentとなりますが、
これは「<サービス名>-deployment」を指しているので、
「<サービス名>-deployment」という名前のS3バケットをあらかじめ作っておく。
デプロイ
Serverless Frameworkを用いてLambdaにデプロイしていきます。
$ sls deploy -v --aws-profile <プロファイル名>
デプロイが完了すると、以下の出力があると思います。
ブラウザからURLにアクセスしてうまく動作していることを確認できます。
※ 何か問題がある場合はCloudWatch Logsへ行き、ログを確認します。
endpoints:
ANY - https://xxxxxxxxxxxx.ap-northeast-1.amazonaws.com/dev
削除
検証が終わって不要な場合は以下のコマンドで削除します。
$ serverless remove -v --aws-profile <プロファイル名>
おわりに
簡単なアプリながら、Lambdaを用いてFlaskアプリを動かすことができました。
サーバレスによる運用フリーなアプリが作成できることが確認できました。
最後に、調査のきっかけになったLambdaについての記事リンクを張っておきます。
すごくまとまっていて、サーバレスアプリをこれから勉強していきたいと思う内容でした。
- サーバレス用のRDSについて
- サーバレスのメリデメについて