Lambdaでの手軽な検証用にActionsでboto3用Lambda Layerを定期更新してみる

AWS LambdaにてBoto3を用いた検証を手軽に行えるようにしつつ、Boto3の更新に関する手間を省くために、GitHub Actionsで定期的にBoto3用Layerを更新するWorkflowを作ってみました。
2021.09.08

AWS上の複数サービスを連携させた処理を行いたい時やとりあえず一回手軽く動かしてみたいなーと思った場合、boto3を準備する手間に目を瞑るとAWS Lambdaがとても便利です。今ではMWAAという選択肢もありそうですが、これはこれでDAGの実装に一手間かかります。

boto3がLambda Layerへ勝手に仕込まれるようにしておけば、管理コンソール上からでもLambda関数化する際にLayerを使うように指定するだけで色々実験は可能だろうという目論見で、GitHub Actions上からboto3用のLambda Layer定期更新のWorkflowを組んでみることにしました。

ローカルの事前設定

homebrewで以下ライブラリをインストールしておきます。

brew install pyenv
brew install pipenv
brew install direnv

必要なバージョンのPythonのインストールも行っておきます。今回はGitHub ActionsのホストランナーUbuntu-20.04のPythonバージョンに合わせて3.8.10にしています。

専用リポジトリのセットアップ

GitHub上に以下のような設定でリポジトリを作成してcloneします。

git clone git@github.com:xxxxxxxx/boto3_layer.git

次にPipfile.lock作成のため、pipenv用設定の追加と仮想環境のセットアップを行います。

cd boto3_layer/
echo "3.8.10" >> .python-version
echo "export PIPENV_VENV_IN_PROJECT=true" >> .envrc
echo "layout pipenv" >> .envrc

pipenv install boto3
direnv allow .

これで必要なPipfile.lockが作成されました。

Lambda Layerの作成

次にLambda Layerの作成です。上記でセットアップしたvenvが存在するとlayerの作成がし辛いため仮想環境を一度削除します。

pipenv --rm

layer用のzipファイルを作成してアップします。

mkdir layer/
PIP_TARGET=./layer pipenv sync
zip -r boto3.zip ./layer
export AWS_PROFILE=XXXXX
aws lambda publish-layer-version --layer-name boto3 --zip-file fileb://boto3.zip --compatible-runtimes python3.8

以下実行ログ。

% mkdir layer/
% PIP_TARGET=./layer pipenv sync
% zip -r boto3.zip ./layer
  adding: layer/ (stored 0%)
  adding: layer/boto3-1.18.37.dist-info/ (stored 0%)
  adding: layer/boto3-1.18.37.dist-info/RECORD (deflated 60%)
  adding: layer/boto3-1.18.37.dist-info/LICENSE (deflated 65%)
  adding: layer/boto3-1.18.37.dist-info/WHEEL (stored 0%)
  ...
% export AWS_PROFILE=XXXXX
% aws lambda publish-layer-version --layer-name boto3 --zip-file fileb://boto3.zip --compatible-runtimes python3.8
{
    "Content": {
        "Location": "https://awslambda-ap-ne-1-layers.s3.ap-northeast-1.amazonaws.com/snapshots/....",
        "CodeSha256": "......",
        "CodeSize": 9523215
    },
    "LayerArn": "arn:aws:lambda:ap-northeast-1:XXXXXXXXXX:layer:boto3",
    "LayerVersionArn": "arn:aws:lambda:ap-northeast-1:XXXXXXXXXX:layer:boto3:1",
    "Description": "",
    "CreatedDate": "2021-09-08T07:28:12.932+0000",
    "Version": 1,
    "CompatibleRuntimes": [
        "python3.8"
    ]
}

これでローカルからの作成は完了しました。

定期更新させる

次に定期的にLayerを更新させるようにします。まずはpipenv関係のコミット。

echo "layer/" >> .gitignore
git add -f Pipfile Pipfile.lock .envrc .python-version .gitignore
git commit -m'add pipfile settings'
git push origin HEAD

次にGitHub Actions用Workflowの作成を行います。

mkdir .github/workflows/
vim .github/workflows/layer_update.yml
git add .github/workflows/layer_update.yml
git push origin HEAD

layer_update.yml の内容は以下の通り。

name: UpdateBoto3Layer

on:
  workflow_dispatch:
  schedule:
    - cron:  '0 0 * * *'

jobs:
  update:
    runs-on: ubuntu-20.04
    steps:
      - uses: actions/checkout@v2

      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ap-northeast-1

      - name: Install pipenv
        shell: bash
        run: |
          python -m pip install --upgrade pip
          python -m pip install pipenv

      - name: Upload Lambda Layer
        run: |
          mkdir layer/
          PIP_TARGET=./layer pipenv sync
          zip -r boto3.zip ./layer
          aws lambda publish-layer-version --layer-name boto3 --zip-file fileb://boto3.zip --compatible-runtimes python3.8

実行するとLayerとしてboto3が追加可能になり、追加後は関数内でimport可能になります。

import boto3

def lambda_hundler(event, context):
    return {
        'status': 'ok'
    }

あとがき

boto3のimport用にcdkでスタックを作成するのも過剰かと思い、一番手軽に且つ定期的にアップできる手段を考えて見た結果今回の方法に至りました。

特にboto3に限ったものではないため、必要な共有ライブラリの更新手段として活用するのも一つの手です。