見出し画像

LambdaのベースイメージをslimイメージからAWSベースイメージに置き換えてコールドスタートを改善した話

こんにちは。株式会社GA technologies、Advanced Innovation Strategy Center(AISC)三田です。

先日、Lambdaのコールドスタートについて実験してこのような記事を書きました。

このとき気になって実験してたことのひとつが、Lambdaに使うコンテナイメージのベースイメージ(DockerfileのFROMに指定するイメージ)を「AWSベースイメージとPython3-slimなどの軽量なイメージのどちらを使ったほうがコールドスタートが速くなるのか」でした。今回はこの点について触れていきます。


まず用語の定義をしていきます(正式な用語がよくわからず勝手に命名しているため)。

本記事におけるAWSベースイメージとはAWSが https://gallery.ecr.aws/lambda/ で公開しているイメージです。例えば「public.ecr.aws/lambda/python:3.12」です。Dockerfileで

FROM public.ecr.aws/lambda/python:3.12

というふうにAWSベースイメージをベースイメージに指定することで、Lambdaで動かすために必要な設定(ENTRYPOINTや環境変数の設定など)を自分でやらなくて済むのがメリットです。

slimイメージは軽量なベースイメージです。例えばpython:3.12-slimです。Dockerfileに

FROM python:3.12-slim

といったふうにslimイメージをベースにしてイメージをbuildすることで、AWSベースイメージを使うよりもファイルサイズが小さいコンテナイメージを作ることができます。

AWSベースイメージとslimイメージのどちらを使うほうがコールドスタートが速いのか

記事執筆時点で最新の両者のPython3.12イメージは

であり、Lambdaのコールドスタート時にイメージをダウンロードする処理を考えるとサイズの小さいpython:3.12-slimを使ったイメージのほうが有利に思えます。しかし、実際に両者を比較してみると、AWSベースイメージのほうがコールドスタートが短いケースが非常に多かったです。

次の画像はboto3パッケージのみを入れた簡単なPythonのイメージで、AWSベースイメージを使ったイメージとpython:3.12-slimを使ったイメージとで比較したものです。

コールドスタート時間の比較。なお、slimイメージを使うほうはAWSのドキュメントに書かれていたmulti-stage buildする方法で作りました。また実験時のbuild後のイメージのサイズは officialが209.9MB、 slimが60.6MB でした。

slimイメージ(図中の"slim")のLambdaよりも、ファイルサイズが3倍以上大きいAWSベースイメージを用いたLambda(図中の"official")のほうが平均的に短いコールドスタート時間(init duration)であることがわかります。なお両者の平均はofficialが440.3msでslimが879.4msと、slimのほうがofficialより約440ms遅い状態でした。

なお、これは実験を始めてから気づいたのですが、AWSの過去のブログでもAWSベースイメージの優位性が解説されていました(カッコ内はGoogle翻訳です)。

the AWS-provided base images are cached pro-actively by the Lambda service.
(AWS が提供するベースイメージは、Lambda サービスによってプロアクティブにキャッシュされます。)

…(中略)…

Despite being much larger, the deployment time may still be shorter when compared to third-party base images, which may not be cached.
(サイズははるかに大きいにもかかわらず、キャッシュされない可能性のあるサードパーティのベースイメージと比較すると、デプロイ時間は短くなる可能性があります。)

Optimizing Lambda functions packaged as container images | AWS Compute Blog

実験的にもLambdaの内部のキャッシュシステム的にもAWSベースイメージを使うほうが望ましいことがわかりました。

LambdaのベースイメージをslimイメージからAWSベースイメージに置き換えてコールドスタートを改善した話

実際のサービスでslimイメージを使っていたものがあり、AWSベースイメージへの置き換えを行いましたのでご共有いたします。

AISCでは社内の業務効率化やtoC事業において賃料や価格の予測機能をAPIとして提供しております。例えば以下のサービスの「AI査定」機能の裏側でAPIが動いております。

こうした予測APIたちの一部のLambdaではPython3-slimベースのイメージを使っておりました。その背景としては

  1. PythonのAWSベースイメージが長らくAmazon Linux 2のOSがベースであったため、対応しているC++のコンパイラやライブラリの関係でLightGBMが動かなかった

  2. 当時は「AWSベースイメージのほうが望ましい」ということを知らなかった(むしろ「軽量なイメージのほうがいいだろう」という思い込みすらあった)

といったことから、開発した当時はslimイメージを使うという選択をしたのでした。

しかし、AWSベースイメージのPython 3.12からはAmazon Linux 2023のOSがベースになりLightGBMが動くようになったため、ベースイメージのリプレイスを行いました。具体的には、Python3.12のAWSベースイメージ(public.ecr.aws/lambda/python:3.12)を使い、LightGBMで必要なOpenMPなどをインストールしたDockerfileを使いました。

このDockerfileを使うようにした結果、こちらも平均で約420msのコールドスタートの短縮が実現できました。

まとめ

まとめますと、

slimイメージをベースにした軽量なイメージよりも、AWSベースイメージを使ったイメージのほうがLambdaのコールドスタートが速い。

→ よほどの理由がなければAWSベースイメージを使ったほうがいい。

というのが今回の学びでした。

もし同様にLambdaでslimイメージや他の非AWSベースイメージを使っている方がいらっしゃいましたらAWSベースイメージへの乗り換えを検討されてみてはいかがでしょうか。

いいなと思ったら応援しよう!