背景
AWS Lambda × Phthon 2.7 でバッチ処理を動かしていたが、Python 2.7のサポート終了に伴い、Python3系にしたい。
また、あまり修正が入らないからという理由で、Lambda関数をローカルでパッケージングして手動でデプロイしていたのが辛いし、PCの環境も汚れるので、そこらへんを解消しつつデプロイできるようにしたい。
クラウドベンダーを選ばないことや、メンテナンスがしっかりされていることから、Serverless Frameworkを利用してデプロイを行えるようにする。
参考
- Serverless Framework公式サイト
- Serverlessを使って簡単にAWS Lambda Layers上でHeadless Chromeを動かす
- Headless ChromeとSeleniumをLambdaで動かす
ハマったポイント
AWS Lambda × Selenium × Chromeでハマったところ
環境
変更前
- Python 2.7
- PhantomJS
- Selenium
- RoboBrowser
変更後
- Serverless Framework 1.64.0
- Python 3.7
- serverless-chrome 1.0.0-55
- ChromeDriver 2.43
- Selenium
- RoboBrowser
対応概要
- Lambda Layer構築
- Lambda関数作成
- CircleCI導入(省略)
Lambda Layer構築
やりたいこと
関数のデプロイ時間を短縮するため、重いライブラリはLambda Layerとして切り出す。
対応
ライブラリのインストール
-
serverless-chrome 1.0.0-55 (chromium 69.0.3497.81)
https://github.com/adieuadieu/serverless-chrome/releases/tag/v1.0.0-55 -
ChromeDriver 2.43
https://chromedriver.chromium.org/downloads -
selenium
pip install -t selenium/python/lib/python3.7/site-packages selenium
- robobrowser
pip install -t robobrowser/python/lib/python3.7/site-packages robobrowser
フォルダ構成
以下のように配置
layer
├── headless-chrome
│ ├── chromedriver # binary
│ └── headless-chromium # binary
├── selenium
│ └── python
│ └── lib
│ └── python3.7
│ └── site-packages
│ └── ...
├── robobrowser
│ └── python
│ └── lib
│ └── python3.7
│ └── site-packages
│ └── ...
└── serverless.yml
service: layer
provider:
name: aws
runtime: python3.7
stage: production
region: ap-northeast-1
layers:
selenium:
path: selenium
description: selenium layer
CompatibleRuntimes:
- python3.7
chromedriver:
path: headless-chrome
description: chrome driver layer
CompatibleRuntimes:
- python3.7
robobrowser:
path: robobrowser
description: robobrowser layer
CompatibleRuntimes:
- python3.7
resources:
Outputs:
SeleniumLayerExport:
Value:
Ref: SeleniumLambdaLayer
Export:
Name: SeleniumLambdaLayer
ChromedriverLayerExport:
Value:
Ref: ChromedriverLambdaLayer
Export:
Name: ChromedriverLambdaLayer
RobobrowserLayerExport:
Value:
Ref: RobobrowserLambdaLayer
Export:
Name: RobobrowserLambdaLayer
デプロイ
事前に以下を実施しておく
sls deploy -v
Lambda関数作成
対応
serverless-python-requirementsのインストール
関数を動かすために必要なpythonライブラリをインストールせずとも、sls deploy時にrequirements.txtやPipfileを参照してデプロイパッケージを作ってくれる。
sls plugin install -n serverless-python-requirements
serverless-prune-pluginのインストール
Lambdaのコードストレージにコードを溜めすぎないように指定した数までしか直近のバージョンを保持しないようにしてくれる。
sls plugin install -n serverless-prune-plugin
フォルダ構成
以下のように配置
function
├── package-lock.json
├── package.json
├── requirements.txt
├── serverless.yml
└── test.py
service: test-service
provider:
name: aws
runtime: python3.7
stage: production
region: ap-northeast-1
timeout: 900
deploymentBucket:
name: serverless-deployment
environment:
LAYER_SERVICE: layer
logRetentionInDays: 30
iamRoleStatements: # 処理に応じて適切なポリシーにする
- Effect: 'Allow'
Action: 's3:*'
Resource: '*'
package:
exclude:
- package.*
functions:
test:
handler: test.lambda_function
name: test
package: {} # 'deploy function'コマンドを利用するための設定
events:
- schedule:
rate: cron(0 0 * * ? *)
input:
test_pattern: 0
layers:
- ${cf:${self:provider.environment.LAYER_SERVICE}-${self:provider.stage}.SeleniumLayerExport}
- ${cf:${self:provider.environment.LAYER_SERVICE}-${self:provider.stage}.ChromedriverLayerExport}
- ${cf:${self:provider.environment.LAYER_SERVICE}-${self:provider.stage}.RobobrowserLayerExport}
plugins:
- serverless-python-requirements
- serverless-prune-plugin
custom:
pythonRequirements:
dockerizePip: false
prune:
automatic: true
includeLayers: true
number: 5
デプロイ
sls deploy -v
最終的にCircleCIも導入して、出来るだけPCの環境を汚さずに、手軽そしてスピーディーに開発・デプロイできるようになりました。