背景
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の環境を汚さずに、手軽そしてスピーディーに開発・デプロイできるようになりました。