Package your Lambda function as a container image
By: Yan Cui
Tags: Cloud, AWS, Serverless, Containers, AWS Lambda

Today, AWS announced another major feature to the Lambda platform: the option to package your code and dependencies as container images. The advantage of this capability is that it makes it easier for enterprise users to use a consistent set of tools for security scanning, code signing, and more. It also raises the maximum code package size for a function to a whopping 10GB.

As an official launch partner, we are proud to add support for container images in the Lumigo platform so you can quickly identify functions that are deployed as a container image.

This feature blurs the line between Lambda and containers and might cause confusion, so I think it’s prudent for us to start with the understanding of what this feature is not.

It is not a replacement for ECS or Fargate.

You can’t run long-running services in Lambda, your code is still bound by Lambda’s invocation model (i.e., it only runs when the function is invoked). Function invocations are still bound by the same 15 minutes max duration. Additionally, your container image must interact with the Lambda Runtime API to request events and send responses, in the same way as a custom Lambda runtime does.

What this new feature lets you do is to ship the content of a Lambda function as a container image instead of a zip file. It also runs the base image as-is, so you can use your preferred Linux base image such as Alpine or Debian.

How it works

You can use one of the many base images that AWS provides, which includes the OS and everything it needs to support the Lambda programming model. And like the managed Lambda runtimes, you can find additional libraries such as the AWS SDK too.

You can also use an arbitrary base image. If you do, then you can use the open-sourced AWS Lambda Runtime Interface Client (RIC) to make your base image compatible with the Lambda’s Runtime API.

You can package container images up to 10GB, which is significantly higher than the 250MB limit on (unzipped) deployment package size.

It’s also worth mentioning that although the container image can be up to 10GB, the Lambda runtime provides a read-only filesystem for the function. If your application requires writing to the filesystem then make sure it’s configured to write to the /tmp directory. The existing 512MB /tmp directory storage limit still applies.

Like a custom Lambda runtime, the container image must have a bootstrap file that interacts with the Lambda Runtime API to request events and send responses. You can specify the location of the bootstrap file using the ENTRYPOINT and CMD settings in the Docker file. You can also configure the working directory using the WORKDIR settings and configure environment variables with the ENV setting.

Once you have built the Docker image you need to deploy the image to Amazon Elastic Container Registry (ECR). Additionally, you need to give the Lambda service the necessary IAM permissions to access the repository and get the container image.

Function Lifecycle

When a function is deployed to Lambda as a container image, it first has to undergo an optimization process before it can be invoked. This process takes a few seconds during which the function is in a PENDING state and cannot be invoked. When the optimization process is complete, the function enters the ACTIVE state.

The existing freeze-thaw process remains the same.

Furthermore, if a function has not been invoked for more than 14 days, the Lambda service might reclaim the optimized version of your function and mark the function as INACTIVE . When that happens, the next invocation will fail but it will reactivate the function and the function will undergo the optimization process again. This process only takes a few seconds during which, the function is in a PENDING state and cannot be invoked. Once the optimization is complete the function will be marked as ACTIVE and is operational again (meaning, it can handle invocation requests).

Caveats

The fact that idle functions can become inoperational (albeit for a few seconds) after a certain amount of idle time is a caveat to keep in mind. This is due to the container image needing to be optimized again because it can be run by Lambda.

At the time of writing, the following Lambda features are not supported for functions that are packed as container images:

Lambda layers are not supported.

Code signing is not supported.

Functions are not automatically patched with runtime updates.

All other existing Lambda features and integrations will continue to work.

When should I use it?

As with many of the recent features in Lambda, such as EFS integration or Lambda Extensions, container image support is designed to address particular pain points and comes with its own complexities.

It’s not something that everyone should use. But for some customers, it can remove technical and organizational roadblocks for adopting Lambda as a technology choice.

For instance, if you need to include really large dependencies that are not permissible by the 250MB deployment package limit. Or maybe you work in an enterprise and/or highly regulated environment where you need to ensure all your applications meet a consistent standard for security and audit purposes. Therefore, it’s of paramount importance that security and operations teams can use a consistent set of tools to provide governance and oversight across the entire organization’s applications.

In these cases, being able to use the same tools for both Lambda and container-based workloads makes Lambda a viable platform.

Container image vs EFS

Back in June, Lambda added support for EFS so you can attach your functions to an EFS volume. Both container images and EFS can be used to work around the limits on the deployment package size and /tmp directory space. But there are some important points to consider:

Functions that are deployed as container images have a read-only filesystem and still have to use the /tmp directory as writable space. Therefore, the same limit of 512MB on the /tmp directory space still applies.

directory as writable space. Therefore, the same limit of 512MB on the directory space still applies. EFS can add potentially unlimited storage space to Lambda functions, but the read and write latency of EFS is orders of magnitude higher than reading from a local filesystem. Reading a large Tensorflow model (say, 1GB?) can therefore take many seconds or even tens of seconds. Reading from the local filesystem for a function deployed as a container image would take a fraction of that time.

It’s possible to use EFS with a function that’s deployed as a container image. So it’s possible to have the best of both worlds.

Both EFS and container images require additional configurations, IAM permissions, and add complexity to how you build and deploy your serverless application. Unless you have specific problems that require these solutions, you should keep your functions as simple as possible.

Summary

Today’s launch of container image support for Lambda is yet another signal that AWS is willing to meet customers where they are. In this post, we discussed how it works, the new lifecycle for a function deployed as a container image, when you should use it, and how it differs from the EFS support.

I think this feature is going to address a common concern from many enterprise customers and help drive the adoption of Lambda as a platform. However, I must reiterate that it’s not something that everyone should use by default. It brings with it all the complexity and overhead of managing container images and puts the responsibility of patching the runtime back on your shoulders. Unless you have a container-shaped problem then you should continue to deploy your functions as zip files.