Blog

Terraformからcargo lambdaを使って、Rustアプリケーションを高速にデプロイする

ニフティのN1! Machine Learning Product Engineer 中村です。

最近はRustを書いていて、TerraformとRustの組み合わせでの知見がネット上にないなと思ったので書き残します。

TerraformでLambdaのデプロイを完了させる

業務利用からプライベート開発に至るまで、自分自身はLambdaのデプロイは多くをTerraformで完結させています。

Terraformにアプリケーションコードを含めたくないという声があるのは知っているのですが、Lambdaはちょっとしたコードを書くことも多く、特にプライベートの開発などにおいてはLambda1個をデプロイするためにCI/CDを整備したりするのは大袈裟すぎるなと考えています。そこで、自分自身はLambdaのアプリケーションコードもインフラの一部だと考えて、terraform applyのみでデプロイまで完結させるようにしています。

今回はその手順を記します。

ここからの手順は以下のレポジトリにコードを残していますので、こちらも参照してください。

inakam/cargo-lambda-terraform-sample

inakam/cargo-lambda-terraform-sample

Contribute to inakam/cargo-lambda-terraform-sample development by creating an account on GitHub.

Cargo LambdaでRustコードを準備する

Rustのコード管理にはCargo Lambdaを用います。

cargo-lambda/cargo-lambda: Cargo Lambda is a Cargo subcommand to help you work with AWS Lambda.

cargo-lambda/cargo-lambda: Cargo Lambda is a Cargo subcommand to help you work with AWS Lambda.

Cargo Lambda is a Cargo subcommand to help you work with AWS Lambda. – cargo-lambda/cargo-lambda

LambdaにRustコードをデプロイするためには、クロスコンパイルなどで適切な設定をする必要があるのですが、cargo-lambdaはそれらの設定をやりやすくしてくれます。

今回はTerraformでデプロイするので、実はcargo-lambdaを使う必要性は薄い(自前でRustのコンパイル設定などを調整すればそれでもデプロイ可能)のですが、プロジェクトのセッティングなどでも手間が少なくなるので、cargo-lambdaを使用します。

cargo lambdaのインストール

Macの場合は以下でcargo-lambdaをインストールします。

そのほかのシステムにおいては、以下を参考にインストールしてください

https://www.cargo-lambda.info/guide/installation.html

cargo lambda new

cargo-lambdaを使ってLambda関数のテンプレートを作成します。

今回はAWS Lambda Function URLsを使いたいので、HTTP functionを統合するようにしてテンプレートを作成します。(lambda_httpが使える状態でテンプレートが作成されます)

ビルドしてみる

作成されたフォルダに移動して、プロジェクトをビルドしてみましょう。

コードのコンパイルが無事に完了すれば、コードの準備は完了です。

TerraformでLambdaをデプロイする準備をする

次にTerraformを整備していきます。今回想定しているフォルダ構成は以下のようになります。

先ほどcargo-lambdaで作成したrust-lambdaフォルダと同じ階層にterraformフォルダを作成し、そこからterraform applyを行うことでデプロイできるようにします。

Terraformの設定

それではterraformフォルダ内にファイルを作成し、インフラの設定を行なっていきます。

以下のようにTerraformを設定します。S3 Remote Stateなどが必要であれば適宜設定を追加します。AWSのプロファイルはローカルマシンなどに設定されているプロファイル名を指定してください。

terraform/variables.tf

Lambdaのモジュールを作成する

RustでLambdaにデプロイするためのモジュールを作成します。このようにモジュールを作成しておくことで、Lambdaごと分離したい・Lambdaを別の用途で増やしたいという場合に手軽に増やすことができて便利です。

modulesというフォルダの中にlambda_rust_moduleフォルダを作成し、以下の記述をします。

terraform/modules/lambda_rust_module/variables.tf

terraform/modules/lambda_rust_module/main.tf

terraform/modules/lambda_rust_module/variables.tf

このTerraformコードの中では、ローカル環境でビルドを行い、バイナリをzip化し、Function URLs付きのLambda関数としてデプロイするという構成が含まれています。

ファイルについてハッシュを計算することで、差分があった時のみデプロイするということを可能にしています。

Lambdaを設定する

モジュールが完成したらLambdaを作成します。

terraform/lambda.tf

Lambdaに付与するIAM権限も同時に作成します。Lambdaから使うサービスが増えてきたら、ここの権限を追加するといいでしょう。

terraform/iam.tf

実際にデプロイを行う

terraformフォルダ内から実際にデプロイしてみましょう。

最後に出てくるURLにアクセスして、Hello worldが表示されると完成です。

WebAPIを作成するためのLambdaテンプレート

Rustを使用したLambdaの場合に比較的需要があるのはWebAPIの作成だと思います。しかし、Lambdaを利用した場合にはactix-web, axum, Rocketなどのフレームワークをそのまま適用することができません。また、lambda_httpを使ったサンプルがWeb上に少なく、構築に苦労するケースが多いです。(苦労しました)

そこで以下のようにmain.rsを記述することで、Lambda上で比較的扱いやすくWebAPIを構築できるという例を載せておきます。

rust-lambda/main.rs

rust-lambda/Cargo.toml

また、axumはlambda_httpと統合して利用できるようなので、こちらを利用してもいいかもしれません。(この記事のレビュー中に社内で教わりました…!)

aws-lambda-rust-runtime/examples/http-axum/src/main.rs at main · awslabs/aws-lambda-rust-runtime

aws-lambda-rust-runtime/examples/http-axum/src/main.rs at main · awslabs/aws-lambda-rust-runtime

A Rust runtime for AWS Lambda. Contribute to awslabs/aws-lambda-rust-runtime development by creating an account on GitHub.

まとめ

今回はcargo-lambdaとTerraformを用いてRustでLambdaの環境を手軽に構築する方法について解説しました。

勉強がてらRustに触れてみたのですが、AWSサービスとの組み合わせにおいてもRustの速度は非常に高速で、学習コストは高いというデメリットはありますが、高速に動作すると言う何者にも変え難いメリットを得ることができます。(特に従量課金型のLambdaという環境においては高速に動作するというのは金銭的にもメリットがあると言えると思います)

みなさんも良きRustライフをお送りください。