AWS Lambdaでpython-snowflake-connectorを使う
前置き
こんにちは。さすらいのデータエンジニアのこみぃです。
AWS Lambdaでpython-snowflake-connectorを使いたいこと、ありますよね。
先日それをやろうとしてちょっと苦戦したので本日はそんなお話です。
Layerを使う
AWS Lambdaでライブラリを使いたい場合には、デフォルトで組み込まれているライブラリ以外はLayerというものを作って関数にセットする必要があります。
python-snowflake-connectorは残念ながらデフォルトには入っていないので、Layerを使う必要があります。
実はLayerは有志で作成して公開されているものがあります。みんなが使うようなLayerは置いてあります。
なのでそこにあれば楽なのですが、python-snowflake-connectorは残念ながら存在しませんので自分で作る必要があります。
Layerを作る
さて、Layerはpip installを-tオプションでディレクトリ指定で行って、作られたディレクトリをzip圧縮することで作ることができるのですが、ここが最大のハマりポイント。
何も考えずにMac or Windowsで作ると以下のようなエラーに悩まされることになります。
Unable to import module 'lambda_function': /opt/python/cryptography/hazmat/bindings/_rust.abi3.so: cannot open shared object file: No such file or directory
これはなぜ起こるかというと、Layerを作った環境とLambdaが実行される環境で違いがあるからです。Lambdaが実行されるのはAmazonlinux2なので、その環境でLayerを作らなければなりません。
EC2にAmazonlinux2を立てるという作戦もありますが、こんなときこそコンテナ技術の出番です。そう、Dockerだね!!
ここからは先駆者様の以下の記事を参考に作ります。
DockerDesktopをインストールした後、適当にディレクトリを切って、2つのファイルを作ります。
FROM amazonlinux:2
ARG PYTHON_VERSION=3.12.1
RUN yum update -y && yum install -y tar gzip make gcc openssl11 openssl11-devel bzip2-devel libffi-devel \
&& curl https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tgz | tar xz \
&& cd Python-${PYTHON_VERSION} && ./configure && make && make install \
&& cd - && rm -rf Python-${PYTHON_VERSION}
ADD entrypoint.sh /
RUN yum install -y zip \
&& mkdir /python \
&& chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
#!/bin/bash -eu
SRC=/python
DIST=/dist/layer.zip
pip3 install -t ${SRC} $@
rm -f ${DIST}
zip -q -r ${DIST} ${SRC}
元記事様のものからDockerfileをいじっていて、opensslではなくopenssl11にしています。合わせてrequestsを使いたいことが多かったのですが、openssl11じゃないとうまく動かなかったのでこうしています。
ここまでできたらdockerをbuild
docker build . -t python_layer_build_312 --platform linux/x86_64 --no-cache
ここで注意が必要なのが、platformを指定する必要があることです。Lambdaのデフォルトがx86_64なのでここではそちらを指定しています。ここが多分エラーの根本的な原因です。
後はdockerをrunしてsnowflake-python-connectorのLayerを作ります
docker run --rm -v ./:/dist python_layer_build_312 snowflake-connector-python
うまくいったらカレントディレクトリにlayer.zipというファイルが作られています。
$ ls
Dockerfile entrypoint.sh layer.zip
こうしてできたlayer.zipが求めていたLayerのファイルになります。
Lambdaにセット
ここまでできたらLambdaのLayerを作成しましょう。
Lambdaの左メニューからLayerを選んで新規作成ボタンを押して、こんな感じで追加します。
続いてLambdaの編集画面の一番下でカスタムレイヤーを追加すればOK
Lambdaを実行してみる
最後に、ちゃんとimportできるか試してみましょう。
import json
import requests
import snowflake.connector
def lambda_handler(event, context):
# TODO implement
return {
'statusCode': 200,
'body': json.dumps('Hello from Lambda!')
}
ね。簡単でしょ?
結びの言葉
今だと他に定期処理をするためのいろいろな方法がありますので、そもそもLambdaでやらないほうがいい可能性はあるのですが、使いたい人はいそうですよね。そんな方の助けになりましたら幸いです。
そんなわけで、案外とどこにも記事が見つからなかったので、記事にしてみました。記事がなかったら自分で記事を書く、エンジニアの鑑。
最後に一つ宣伝を。
GENDAデータチームではプロダクトのデータ解析や機械学習プロジェクトを推進できるデータサイエンティストを募集しています。
興味がおありの方は、ぜひぜひご連絡ください。
また、データサイエンティスト以外でも、なんならデータ系以外の方でも、優秀な方を常に求めています。GENDAという会社に興味があれば、是非お声おかけください。
本日はこのあたりで。
それじゃあ、バイバイ!
Discussion