AWS Chalice で AWS Data Wrangler を利用する

# はじめに
AWS 上のデータを Pandas[^pandas] で処理したいときには、各種 AWS サービス（RDS, DynamoDB, Athena, S3 など）からのデータの load/unload を簡単化してくれる Python モジュール AWS Data Wrangler[^awswrangler] が超便利です。しかも、AWS 自体が開発してオープンソース公開しているものなので、ある程度安心して使えます。
なんですが、この AWS Data Wrangler を Lambda で利用する際には、デプロイパッケージのサイズに適用されるクォータ（未圧縮で 250MB、zip 圧縮済みで 50MB）が問題になります。具体的には、AWS Data Wrangler を普通に pip でインストールすると、それだけでパッケージサイズが 250MB を超えてしまいデプロイすることができません。
実はこの問題、[AWS Data Wrangler のドキュメント](https://aws-data-wrangler.readthedocs.io/en/2.14.0/install.html#aws-lambda-layer)に示されているとおり、Lambda Layer を活用することで解決できます。本記事では、これを Lambda 開発のための Python フレームワークである AWS Chalice[^chalice] を使ったプロジェクトに適用する方法をまとめます。

# 準備
説明のために、まずは Chalice でシンプルなプロジェクトを用意します。公式のチュートリアル[^quick]などにある通り、`chalice new-project app_skelton` で新たなプロジェクトを作り、生成された `app.py` に、AWS Data Wrangler のバージョンを出力するだけの Lambda 関数を定義します。
```python:app.py
from chalice import Chalice
import awswrangler as wr

app = Chalice(app_name='app_skelton')

@app.lambda_function()
def func(event, context):
    return {'version': wr.__version__}
```
通常の外部モジュール利用時と同じように、`requirements.txt` に `awswrangler==2.14.0` を追加して、`chalice deploy` してみると、、、パッケージサイズクォータに引っかかってデプロイできません。
このシンプルなプロジェクトを例に、AWS Data Wrangler を利用できるようにするための方法を説明します。

:::note
以下に説明する方法では、`requirements.txt` に `awswrangler` に関するモジュール情報を記載しません（追加する必要はありません）。
:::

# 方法
AWS Chalice で AWS Data Wrangler を利用するためには、Lambda Layer を活用する必要があります。具体的には2つの方法があるのでそれぞれ説明します。

## 方法1 「AWS が公開している Lambda Layer を活用する」
特定の AWS リージョン[^region]とバージョン[^version]については、AWS Data Wrangler がデプロイされた Lambda Layer を、AWS が公開してくれています。Chalice プロジェクトの設定ファイルでそれらの Layer ARN を指定すれば利用できる、ということです。Chalice プロジェクト側で手を入れる必要がある箇所は、設定ファイルの `.chalice/config.json` のみで、デフォルトからの差分（diff）は以下のとおり2行（行頭に + のある行）の追加だけです。

```diff_json:.chalice/config.json
{
  "version": "2.0",
  "app_name": "app_skelton",
+ "automatic_layer": true,
+ "layers": ["arn:aws:lambda:ap-northeast-1:336392948345:layer:AWSDataWrangler-Python38:2"],
  "stages": {
    "dev": {
    }
  }
}
```
ちなみに、上記の例で指定している Layer ARN は、Python `3.8` 用の AWS Data Wrangler `2.13.0` です[^version]。

## 方法2 「AWS が配布している Layer 用パッケージを活用する」
方法1 はお手軽ではあるのですが、特定リージョン[^region]以外のリージョンで利用したいときや、公開されている Managed Layer に何らかの原因でアクセスできなくなる等のリスクを回避したいとき、などのために、代替手段が用意されています。それは、AWS が github で配布している Layer 用パッケージ（Lambda のパッケージサイズクォータに引っかからないサイズにコンパクト化したパッケージ）[^release]の活用です。
例えば、Python `3.8` 用の AWS Data Wrangler `2.14.0` に対応する Layer 用パッケージを利用する場合、手順は以下のとおりです。

1. Layer 用パッケージ（`awswrangler-layer-2.14.0-py3.8.zip`）をダウンロード
1. ダウンロードした zip ファイルを解凍
1. 解凍された `python` ディレクトリ内を、Chalice プロジェクトのディレクトリ直下の `vendor`ディレクトリに配置[^vendor]
1. `.chalice/config.json` に `"automatic_layer": true` を追加

```diff_json:.chalice/config.json
{
  "version": "2.0",
  "app_name": "app_skelton",
+ "automatic_layer": true,
  "stages": {
    "dev": {
    }
  }
}
```

これで、クォータに引っかかることなく `chalice deploy` できるようになります。実際にデプロイすると、Lambda 関数などを含むメインパッケージとは別に、AWS Data Wrangler 一式が格納された Lambda Layer が新たに生成されます。デプロイされた Lambda Layer をダウンロードしてサイズを確認すると 44MB ほどでした。上限 50MB に収まる絶妙なサイズです。

# おわりに
今回は、Jupyter Notebook 上で書いた ETL 処理を Lambda に移植しようとしたときに必要になったことをまとめてみました。AWS Data Wrangler に限らず、Chalice プロジェクトでサイズが大きめのモジュールを使う場合に活用できると思います。

[^pandas]: [pandas - Python Data Analysis Library](https://pandas.pydata.org/)
[^awswrangler]: [What is AWS Data Wrangler? — AWS Data Wrangler documentation](https://aws-data-wrangler.readthedocs.io/en/stable/what.html)
[^developer]: [Lambdaでawswranglerを使う | DevelopersIO](https://dev.classmethod.jp/articles/use-awswrangler-in-aws-lambda/)
[^chalice]: [Documentation — AWS Chalice](https://aws.github.io/chalice/)
[^quick]: [Quickstart — AWS Chalice](https://aws.github.io/chalice/quickstart.html)
[^region]: 2022年3月21日時点でのドキュメント（[Install — AWS Data Wrangler 2.14.0 documentation](https://aws-data-wrangler.readthedocs.io/en/2.14.0/install.html#managed-layer)）によると、ap-northeast-1, ap-southeast-2, eu-central-1, eu-west-1, us-east-1, us-east-2, us-west-2 の計7リージョンで利用できるようです。
[^version]: 2022年3月21日時点でのドキュメント（[Install — AWS Data Wrangler 2.14.0 documentation](https://aws-data-wrangler.readthedocs.io/en/2.14.0/install.html#managed-layer)）によると、Python の `3.7` から `3.9`、AWS Data Wrangler の `2.12.0` と `2.13.0` に対応する Layer ARN が利用できるとあります。最新版である `2.14.0` 用の Layer ARN は記載されていないのですが、Lambda の管理コンソールで調査できる範囲では、Python `3.8` 用の AWS Data Wrangler `2.14.0` に対応する Layer ARN（`arn:aws:lambda:ap-northeast-1:336392948345:layer:AWSDataWrangler-Python38:3`）が存在していて利用もできるようです。
[^release]: [Releases · awslabs/aws-data-wrangler · GitHub](https://github.com/awslabs/aws-data-wrangler/releases)
[^vendor]: [App Packaging — AWS Chalice](https://aws.github.io/chalice/topics/packaging.html#rd-party-packages)