ソモサン

私rohkiによる活動や読書の記録をつらつらと書くページです

AWS Lambda 上で Rust のコードを実行しようとして結構頑張った話

短く

OpenSSL はやはり鬼門
というわけでできたー。下が成果物。

github.com

概要

最近 Lambda 上で GC が走らない言語動かしてこれやりたかったなー、という変な実装をしたことがありまして。
できるか調査を始めてみた次第です。Rust なのは完全に趣味。

ライブラリ

使ったライブラリは下のもので、CPython を利用するものです。
github.com

個人的におもしれーと思ったのが、Docker を利用してビルド環境を提供してくれているところでした。
Lambda で実行する以上、場合によってはクロスコンパイラとかいるわけで、結構大事な気遣いだなーと感心しておりました。

はまった罠

GitHub - ROki1988/kinesis-crowbar at 9ef21c359194d2e7642b9528be4d9a5d2986c920

コミットとしてはこのあたりでしょうか。
Kinesis から呼び出される想定で、S3 にファイルを保存するコードをかいたときです。*1
コンパイルが通ってよしよし、と思ったら動かない…
なぜだ、とエラーを見てみると、以下のようになっていました。

Unable to import module 'liblambda': /lib64/libcrypto.so.10: version `OPENSSL_1.0.2' not found (required by /var/task/liblambda.so)

OpenSSL …またお前か…

長い迷走

こっから長い迷走が始まります。

ビルド環境の README.md に従って見る

README.mdに openssl-devel を更新するような指定方法があったので、初手としてならってみましたが、結果は同じでした。

Issue の存在を確認

github.com

おー Issue あんじゃん、と中を確認して Pull Request もある!と期待がでてきました。
コードを修正してみて、ビルドして、デプロイ。
結果、動いた。動いたんだけど、コメントにあるとおりなんか変…

rust-openssl の対応バージョンを確認

github.com

build.rs で対応バージョンを見てみると、1.0.1 以上に対応している模様。
Issue 通りなら動くはず???

openssl 1.0.2 を静的リンクする

rust-crowbar-builer

Lambda 上にないなら静的リンクでくっつければいいんだろ、と初 Dockerfile を書いてみました。
結果ビルドに成功したんですが、別のエラーで怒られました…

HttpDispatch(HttpDispatchError { message: "The OpenSSL library reported an error" }): RuntimeError
Traceback (most recent call last):
File "/var/runtime/awslambda/bootstrap.py", line 249, in handle_event_request
result = request_handler(json_input, context)
RuntimeError: HttpDispatch(HttpDispatchError { message: "The OpenSSL library reported an error" })

この時はサラッと次に行ってしまいましたが、今考えると TLS の検証とかで落ちてたのかもです。
CA の情報が見つからず、鍵の検証ではじかれて上記エラーかな。

そもそもの OpenSSL のバージョンを確認する

ん? そもそも Lambda 上の OpenSSL のバージョンはいくつだ? とやっとこさ気づき確認。
で、これです。

Python3.6が1.0.0 ってダメじゃん! なんで Pull Request のやつで動いたの?

Python2.7 + OpenSSL 1.0.1 でのビルド

幸いなことに rust-crowbarPython 2.7 でも呼び出せたので、そちらに切り替えます。
ビルド環境として、Issue に上がっていた lambci が使えそうだったので、こちらをベースに Dockerfile を書きました。

FROM lambci/lambda:build-python2.7
RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain stable
ADD build.sh /usr/local/bin/
VOLUME ["/code"]
WORKDIR /code
ENTRYPOINT ["/usr/local/bin/build.sh"]

で、コードも Python2.7 から呼び出せるように変えて、動いたー!!!
あーしんど。面白かったけどw

おわりに

迷走しすぎですね、こう書くと。静的リンクとか、もう。
環境の確認はいのいちやっていこう。

しかしこれ、Lambda OpenSSL のバージョンアップとかどうしてるんでしょう。

*1:Firehose でできるけどお試しなので許して