Rust AWS lambda with glibc
Why
AWS has announced supporting rust for the lambda, but does not provide an official runtime for it. You have to provide your own, and the official way is through building a target where you can statically link a libc implementation: musl.
While it appears you could statically link the glibc, it is not advised. (see here and here)
So for AWS:
What
While searching for alternative solutions to this (Because reasons), I found that since late 2020, they added a container image support to AWS lambda.
Sooooooo, if we want to use glibc, we need to have docker. Fine, let’s give it a try
How
First we have to create a simple rust application.
cargo new test_aws_lambda
cargo add lambda_runtime
cargo add tokio
cargo add aws_lambda_events
Let’s change the src/main.rs
a bit.
Basically we will just return everything that is sent to us.
use aws_lambda_events::event::sns::SnsEvent;
use lambda_runtime::Context;
use lambda_runtime::{handler_fn, Error};
#[tokio::main]
pub async fn main() -> Result<(), Error> {
let func = handler_fn(handler);
lambda_runtime::run(func).await?;
Ok(())
}
async fn handler(sns_event: SnsEvent, _context: Context) -> Result<SnsEvent, Error> {
println!("Handler");
Ok(sns_event)
}
Now comes the build part, we will use docker to build the release.
We will need a custom ENTRYPOINT for aws to be able to understand the lambda.
Here is the entry.sh
you’ll need:
#!/bin/sh
set -x
if [ -z "${AWS_LAMBDA_RUNTIME_API}" ]; then
exec /usr/bin/aws-lambda-rie "$@"
else
exec "$@"
fi
FROM rust:buster as build
COPY test_aws_lambda /test_aws_lambda
RUN cd test_aws_lambda && cargo build --release
FROM debian:buster
ADD https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/download/1.1/aws-lambda-rie /usr/bin/aws-lambda-rie
RUN chmod 755 /usr/bin/aws-lambda-rie
COPY entry.sh /
RUN chmod 755 /entry.sh
ENTRYPOINT [ "/entry.sh" ]
COPY --from=build /test_aws_lambda/target/release/test_aws_lambda /test_aws_lambda
CMD [ "/test_aws_lambda" ]
Now we have to build it: docker build -t aws-lambda-test .
Run it: docker run --rm -p 9000:8080 aws-lambda-test
And test it: curl -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{ "Records": [] }'
It should respond {"Records":[]}
Deploy on AWS
You need to have a docker registry (ECR) in the same account as your lambda.
First, create an ECR repository ACCOUNTID.dkr.ecr.AWS_REGION.amazonaws.com/aws-lambda-test
You can then tag and push your local image in this repository:
docker tag aws-lambda-test ACCOUNTID.dkr.ecr.AWS_REGION.amazonaws.com/aws-lambda-test
docker push ACCOUNTID.dkr.ecr.AWS_REGION.amazonaws.com/aws-lambda-test
Create the lambda, use the container image, and go to the test section.
And voilà, you now have a rust container running as an aws lambda!