軽量なJavaScriptランタイムLLRTで動くAWS Lambda関数をlambrollでデプロイする

Posts

LLRTは、AWSがオープンソースとして公開した、軽量なJavaScriptランタイムである。
この記事では、LLRTで動かすAWS Lambda関数をlambrollでデプロイする方法を記載する。

LLRTとは

LLRT(Low Latency Runtime)は、サーバレス環境で使用されることを想定したJavaScriptランタイムである。
軽量さを特徴とし、他のJavaScriptランタイムに比べて、高速な起動を謳っている。
なお、JavaScriptエンジンには組み込み環境などでも動作するQuickJSを利用しており、LLRT自体はRustで実装されている。

LLRT (Low Latency Runtime) is an experimental, lightweight JavaScript runtime designed to address the growing demand for fast and efficient Serverless applications. - awslabs/llrt
GitHub

LLRTを使用したLambda関数の作成方法は、リポジトリのREADMEに記載されている。
今回は、Lambdaレイヤーを使わずにLambda関数を作成し、デプロイする方法を記載する。
デプロイにはlambrollを使用する。lambrollの使い方は次の記事に詳細を書いた。

動作を確認した環境

  • LLRT v0.1.11-beta
  • lambroll v1.0.1

LLRTで動かすAWS Lambda関数の作成

プロジェクトの作成

まずは、lambrollでLambda関数を作成する。

# ディレクトリを作成
mkdir hello-llrt && cd $_
# lambroll用の設定ファイルを作成
lambroll init --function-name hello-llrt

# ディレクトリ構成
# .
# ├── .lambdaignore
# └── function.json

Lambda関数のコードの作成

Lambda関数のコードを作成する。
起動時間を確認したいだけなので、引数を受け取って返すだけの関数のファイルを作成する。

src/index.js
export const handler = async (event) => {
  return {
    statusCode: 200,
    body: JSON.stringify(`Hello ${event.name}`),
  };
};

ちなみにexportsでエクスポートすると、実行時に「handler関数が見つからない」というエラーが出た。

{
  "errorType":"Error",
  "errorMessage":"\"handler\" is not a function in \"src/index\"",
  "stackTrace":["    at main (@llrt/runtime:5:928)",""]
}

ランタイムの変更

LLRTは公式サポートされたランタイムではないため、カスタムランタイムの「Amazon Linux 2023」を使用する。
lambrollのLambda関数の設定ファイルfunction.jsonを編集し、ランタイムを修正する。
指定するランタイム名は次のページで確認した。
Lambda ランタイム

function.json
{
  "FunctionName": "hello-llrt",
  "Handler": "index.handler",
  "MemorySize": 128,
  "Role": "arn:aws:iam::123456789012:role/LambrollDeploy",
-  "Runtime": "nodejs18.x",
+  "Runtime": "provided.al2023",
  "Timeout": 3
}

provided.al2023ランタイムではハンドラー名を「bootstrap」にする必要があるため、ハンドラー名を修正する。

function.json
{
  "FunctionName": "hello-llrt",
-  "Handler": "index.handler",
+  "Handler": "bootstrap",
  "MemorySize": 128,
  "Role": "arn:aws:iam::123456789012:role/LambrollDeploy",
  "Runtime": "provided.al2023",
  "Timeout": 3
}

LLRTバイナリの配置

LLRTのバイナリをダウンロードし、Lambda関数のディレクトリに配置する。
GitHubリポジトリのリリースページから「llrt-linux-x64.zip」をダウンロードする。
zipファイルを展開するとLLRTのバイナリファイル「llrt」があるので、「bootstrap」という名前にリネームする。
「bootstrap」にリネームしたら、プロジェクトのルートに配置する。

.
├── .lambdaignore
├── bootstrap # LLRTのバイナリ
├── function.json
└── src
    └── index.js

呼び出すハンドラー名の定義

LLRTで動かすLambda関数のハンドラー名を、環境変数LAMBDA_HANDLERに定義する。

function.json
{
  "FunctionName": "hello-llrt",
  "Handler": "bootstrap",
  "MemorySize": 128,
  "Role": "arn:aws:iam::123456789012:role/LambrollDeploy",
  "Runtime": "provided.al2023",
-  "Timeout": 3,
+  "Timeout": 3,
+  "Environment": {
+    "Variables": {
+      "LAMBDA_HANDLER": "src/index.handler"
+    }
+  }
}

準備が完了したので、関数をデプロイする。

デプロイ

lambroll deployコマンドで関数をデプロイする。

lambroll deploy

2024/03/18 20:31:14 [info] lambroll v1.0.1
2024/03/18 20:31:14 [info] starting deploy function hello-llrt
2024/03/18 20:44:06 [info] creating zip archive from .
2024/03/18 20:31:15 [info] zip archive wrote 3312162 bytes
2024/03/18 20:31:15 [info] creating function
2024/03/18 20:31:16 [info] State:Pending LastUpdateStatus:
2024/03/18 20:31:16 [info] waiting for LastUpdateStatus Successful
2024/03/18 20:31:17 [info] State:Pending LastUpdateStatus:
2024/03/18 20:31:17 [info] waiting for LastUpdateStatus Successful
2024/03/18 20:31:19 [info] State:Pending LastUpdateStatus:
2024/03/18 20:31:19 [info] waiting for LastUpdateStatus Successful
2024/03/18 20:31:23 [info] State:Active LastUpdateStatus:Successful
2024/03/18 20:31:23 [info] deployed function version 13
2024/03/18 20:31:23 [info] creating alias set current to version 13
2024/03/18 20:31:23 [info] alias created

動作確認

デプロイが完了したら、lambroll invokeコマンドで動作を確認する。

echo '{"name":"chick-p"}' | lambroll invoke

2024/03/18 20:33:00 [info] lambroll v1.0.1
{"statusCode":200,"body":"\"Hello chick-p\""}
2024/03/18 20:33:00 [info] StatusCode:200
2024/03/18 20:33:00 [info] ExecutionVersion:$LATEST

Node.js 18.xランタイムとの所要時間の比較

LLRTとNode.js 18.xランタイムの所要時間を比較した。
それぞれ5回ずつ呼び出して所要時間を計測した結果は次のとおり。

1 回目2 回目3 回目4 回目5 回目
LLRT1.05 ms1.06 ms1.08 ms1.03 ms0.90 ms
Node.js 18.x81.79 ms54.09 ms1.51 ms1.58 ms1.69 ms

2回目以降は、コールドスリープで起動したと思われるため、Node.jsでも所要時間が短くなっていたが、1回目の時間で比較するとLLRTの方が短かかった。

まとめ

LLRTで動くLambda関数をlambrollを使ってデプロイする方法を記載した。
LLRTは軽量なJavaScriptランタイムで、起動時間の短さが特徴である。
起動時間が短くなるとLambda関数の実行時間が短縮されるため、コスト低減効果が期待できる。
LLRTは実験的なランタイムであるため、本番運用に使用するには注意が必要だが、GA版になって標準のランタイムとして使用できる未来を期待したい。