AWS Lambda and Rust

·

3 min read

Once I wanted to experiment with Rust and try to write and deploy a simple lambda function and deploy it to AWS Cloud. A lot of tutorials provide building and deployment of lambda by hand, but I am too lazy to do this.

At first glance, it seems like a simple task- build lambda and upload to AWS. I did it many times. We have a solution for this like https://www.cargo-lambda.info/commands/deploy.html project, but after some knowledge of https://www.serverless.com/ is cargo-lamda functionality very poor. What if I want to attach lambda authorizer, set up timeout, specify tags and duration of cloudwatch logs?

serverless

I quickly install serverless tool in a new folder

Than I create folder

mkdir aws-lambda-tempate && cd aws-lambda-tempate;

after that install serverless plugin

npm install -D serverless

First try

After basic preparation I tried to install sls-offline plugin for local development, but unfortunately, this plugin does not support rust runtime. I always fetch an error

"Unsupported runtime"

from https://github.com/dherault/serverless-offline/blob/eea2c7e16eb671a1615154ec4350678771627564/src/lambda/handler-runner/HandlerRunner.js#L94C21-L94C42 line. After that I have to install cargo-lamda for a local run.

Second try

Okay, locally I can run my lambda with cargo-lambda. How about deployment ?

I knew aws support go runtime (now they want to deprecate in favor provided.al2023 runtime). I write custom sls file like

service: rust-lambda
frameworkVersion: "3"
configValidationMode: "warn"

provider:
  name: aws
  runtime: provided.al2023
  stage: dev
  region: us-west-1

package:
 individually: true

functions:
  get:
    handler: ./target/debug/aws-lambda-template
    package:
      include:
        - ./target/debug/aws-lambda-template
    events:
      - http:
          path: get/{name}
          method: get

But it does not work. Firstly I fetch an error like

2024-02-02T13:04:02.826+02:00
INIT_REPORT Init Duration: 0.15 ms    Phase: invoke    Status: error    Error Type: Runtime.InvalidEntrypoint
INIT_REPORT Init Duration: 0.15 ms Phase: invoke Status: error Error Type: Runtime.InvalidEntrypoint
2024-02-02T13:04:02.826+02:00    START RequestId: 14bd2977-49e1-4049-8706-40e1a23fbc38 Version: $LATEST
2024-02-02T13:04:02.827+02:00
RequestId: 14bd2977-49e1-4049-8706-40e1a23fbc38 Error: Couldn't find valid bootstrap(s): [/var/task/bootstrap /opt/bootstrap]
Runtime.InvalidEntrypoint
RequestId: 14bd2977-49e1-4049-8706-40e1a23fbc38 Error: Couldn't find valid bootstrap(s): [/var/task/bootstrap /opt/bootstrap] Runtime.InvalidEntrypoint

Something wrong with that ? My previous experience with Golang told me I have to upload just a binary file with the correct architecture and that's all. But it does not not in new runtime provided.al2023 (. Okay, I renamed my binary file to bootstrap and uploaded it again. Error again.


 Error: fork/exec /var/task/bootstrap: exec format error

In this case, I have to rebuild my binary file for another architecture. So in result we have to

  1. Build binary file with correct architecture

  2. rename it to bootstrap

  3. and upload.

Thanks to the plugin serverless-rust, this plugin builds and renames file. So add to our sls file

npm i -D serverless-rust

and you will be result yaml file something like this

service: rust-lambda
frameworkVersion: "3"
configValidationMode: "warn"

provider:
  name: aws
  runtime: provided.al2023
  stage: dev
  region: us-west-1

package:
 individually: true

custom:
  rust:
    cargoLambda:
      docker: false

plugins:
  - serverless-rust-plugin

functions:
  get:
    handler: rust-lambda
    events:
      - http:
          path: get/{name}
          method: get

Repo where you can clone this template https://github.com/R11baka/rust-lambda-template