LoginSignup
10
6

More than 3 years have passed since last update.

Lambda から Snowflake にシュッとつなぎたい!

Posted at

この記事はSnowflakeアドベントカレンダーちゅらデータアドベントカレンダーの8日目の記事でっす。

Lambda 好きですか?

Lambda 好きっすよね?
サーバレスですし、最近じゃコンテナサポートされたり、メモリが10Gまで使えるようになったり、もはやサーバレスにこれまでみんなが抱いていた、イメージってだいぶ払拭されたんじゃないかしら?

そんな Lambda から Snowflake に繋げば、もう簡単なETLは全部これにしちゃっても良いんじゃないですかね?
今回は Lambda の Python ランタイムを想定してます。

前準備

とりあえず、いつものように Lambda で Python ランタイムを作っておきましょう。
えいえい!(作ってる音)

Lambda-8.png
※関数名は適当です

ローカルでサクッと開発

まずは、開発するフォルダを作ります。

$ mkdir snow_lambda; cd $_

次に、この後ネイティブバイナリをつかうから、ライブラリは Docker のコンテナで作ってしまいましょう。
下記のファイルを Dockerfile という名前で上で作った開発用のフォルダに置きます。

FROM python:3.8
USER root

RUN apt-get update
RUN apt-get -y install locales && \
    localedef -f UTF-8 -i ja_JP ja_JP.UTF-8
ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP:ja
ENV LC_ALL ja_JP.UTF-8
ENV TZ JST-9
ENV TERM xterm

RUN apt-get install -y vim less zip
RUN pip install --upgrade pip
RUN pip install --upgrade setuptools

私はめんどくさがりだから、 docker-compose.yml 作ってしまいます。
下記のようなファイルを docker-compose.yml という名前で同じく開発用のフォルダに置きます。

version: "3.5"
services:
  app:
    restart: always
    build: .
    working_dir: "/root/"
    tty: true
    volumes:
      - ./:/root/

上記のコンテナ関係の作り方は気に入らなかったら随意に直してください。
私がいつも使ってる設定とかを適当に入れてます。

次にコンテナを立ち上げて、その後はコンテナの中でライブラリを zip に固める作業をします。

$ docker-compose up -d
# …ビルドログがブワーッと流れる…
Starting snowflake_lambda_app_1 ... done
$ docker-compose exec app bash
# ここからはコンテナ内での作業
$ python3 -m venv --without-pip venv  
$ source venv/bin/activate
$ cd venv/lib/python3.8/site-packages
$ pip install snowflake-connector-python --target .
$ chmod -R 755 .; deactivate
$ zip -r9 ../../../../snow_lambda.zip .

シャキン!!
これであとはコードを書いてzipに加えるだけ
下記の Python コードを lambda_function.py という名前で保存してね。
※user、password、accountは自分のSnowflakeのものを使ってね。


import snowflake.connector

def lambda_handler(event, context):
    print('## START FUNCTION')

    user='HOGE_USER' # 自分の
    password='HOGE_PASSWD'
    account='hogehoge.ap-northeast-1.aws'

    ctx = snowflake.connector.connect(
        user=user,
        password=password,
        account=account
        )
    cs = ctx.cursor()
    try:
        cs.execute("SELECT current_version()")
        one_row = cs.fetchone()
        print(one_row[0])
    finally:
        cs.close()
    ctx.close()

    print('## END FUNCTION')
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }

できた!
中身は Snowflake のバージョンを出力するクエリを叩いています。
うまく行けば、 Lambda から Snowflake につないでクエリができます。

上記のコードの動作が心配な人は、ローカルで main を作って動かしてみても良いかもです。

さぁ次のコマンドで、今書いた Python コードを、さっき固めた zip ファイルに追加しよう。

$ zip -g snow_lambda.zip lambda_function.py

そして、最後はこの zip ファイルを使って Lambda 関数を更新します。
aws コマンドで、更新しようと思ったのだけど、じつは zip ファイルが40MBくらいになってしまったので、下記のコマンドでは、 Lambda 関数を更新できません。参考程度に載せておきます。

# 多分動かないコマンド
$ aws lambda update-function-code --function-name snowflake-connect --zip-file fileb://snow_lambda.zip --profile hogehoge

かわりに、さっきの snow_lambda.zip を S3 に手でアップロードしよう。(コマンドでアップロードしてもいいです。
そして今度こそ最後にアップロードした S3 パスをコピーして、 Lambda の UI に入力して、 Lambda 関数を更新しましょう。

そしてテストする

ここまでできたらあとはテストを叩いて動かして見るだけ。
テストの結果、下記のようなログ出力が出れば成功です!

snowflake-connect_-_Lambda-2.png

終わりに

さて、いかがでしたか?

snowflake.connector ライブラリが、一部ネイティブライブラリに依存していたので、 Linux 環境で pip を使わないと、 Lambda 用のライブラリを作れないというのが唯一のハマリポイントですが、最初から Linux で作業してる人はコンテナを作ったりする工程は不要だったりします。

もし Mac でつくったりすると、下記のような invalid ELF header が Lambda からエラーとして出力されます。

[ERROR] Runtime.ImportModuleError: Unable to import module 'lambda_function': /var/task/cryptography/hazmat/bindings/_openssl.abi3.so: invalid ELF header

このあたりを気をつけていただくだけで、 サーバレス Snowflake がはかどりますよ!
ぜひ、皆さんも試してみてください!

10
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
6