Rust で AWS Lambda を実装する機会がありましたが、ちょっとクセがあったので、備忘録も兼ねて記事にしておきます。
デプロイも簡略化できるよう、 Serverless Framework を使ってデプロイできるようにします。
環境
$ rustc -V
rustc 1.45.0 (5c1f21c3b 2020-07-13)
$ cargo --version
cargo 1.45.0 (744bd1fbb 2020-06-15)
とりあえず動かすまで
-
通常通り、プロジェクト作成
cargo new sample_lambda_function
-
使用する crete 等を
Cargo.toml
に記述Cargo.toml[package] name = "sample_lambda_function" version = "0.1.0" authors = ["example name <example@mail.com>"] edition = "2018" [dependencies] lambda_runtime = "0.2.1" serde = { version = "1.0.117", features = ["derive"] }
-
package.json
を作成して以下のように編集するpackage.json{ "scripts": { "build": "docker run --rm -v $PWD:/code -v $HOME/.cargo/registry:/root/.cargo/registry -v $HOME/.cargo/git:/root/.cargo/git softprops/lambda-rust:latest", "deploy": "sls deploy --stage dev --verbose" }, "devDependencies": { "serverless": "2.8.0", "serverless-rust": "0.3.8" } }
-
上記を作成したら
yarn install
で Serverless Framework を手元のプロジェクトにインストールする -
とりあえず動かすための Lambda 関数を作成する。
src/main.rs
を以下のように実装する:- メイン関数は
lambda
の マクロを用いて、ハンドラ関数を呼び出す。 - ハンドラ関数には、イベントとコンテキストを引数に指定する。
main.rsuse std::error::Error as StdError; use lambda_runtime::{error::HandlerError, lambda, Context}; use serde::{Deserialize, Serialize}; #[derive(Deserialize)] #[serde(rename_all = "camelCase")] struct CustomEvent { first_time: String, } #[derive(Serialize)] #[serde(rename_all = "camelCase")] struct CustomOutput { message: String, } fn main() -> Result<(), Box<dyn StdError>> { lambda!(handler); Ok(()) } fn handler( event: CustomEvent, _context: Context, ) -> Result<CustomOutput, HandlerError> { Ok(CustomOutput { message: format!("Hello, {}!", event.first_time), }) }
- メイン関数は
-
手元でビルドをしてみる。ビルドには
softprops/lambda-rust
の Docker イメージを利用するyarn build
- エラーなく無事にビルドできたら OK
-
serverless.yml
を以下のように作成する- 作成される関数名は
[seivice で指定した名前]-[ステージ名]-[functions の下で指定した名前]
となる。
serverless.ymlservice: sample-lambda-function provider: name: aws runtime: rust memorySize: 128 region: us-east-2 package: individually: true plugins: - serverless-rust custom: # this section customizes of the default # serverless-rust plugin settings rust: dockerTag: 'latest' functions: hello_world: handler: sample_lambda_function
- 作成される関数名は
-
デプロイは以下のコマンドで可能。
yarn deploy
複数の Lambda 関数をデプロイする
-
ライブラリ + 複数バイナリの構成にする方法を採用する
-
構成としてはこんな感じ
. |-- Cargo.toml |-- node_modules |-- package.json |-- serverless.yml |-- src | `-- bin | |-- function-a.rs | `-- function-b.rs `-- target
-
Cargo.toml
に以下の記述を追加するCargo.toml[[bin]] name = "function-a" path = "src/bin/function-a.rs" [[bin]] name = "function-b" path = "src/bin/function-b.rs"
-
serverless.yml
には以下のように書く- ハンドラの指定は、「【
Cargo.toml
の[package]
のname
】.【Cargo.toml
の[[bin]]
のname
】」と記述する
serverless.ymlfunctions: function-a: handler: sample_lambda_function.function-a function-b: handler: sample_lambda_function.function-b
- ハンドラの指定は、「【
-
ビルドとデプロイのコマンドは先程と同じ。
- 複数の関数は関連した関数としてデプロイされる。
参考資料
-
Rustで始めるCustom Runtime Lambda入門
- 記事の内容全般について参考にしました。