AWS custom runtime for lambda really works: How I developed a lambda in Perl

Avijit Sarkar
Dec 9, 2018 · 6 min read
Image for post
Image for post

At re:Invent 2018, AWS announced a new lambda feature called custom runtime for lambda and what exactly it means is you can develop lambda functions in not only the out-of-box supported runtimes like Java, C#, Python etc but also using any other programming language.

So I decided to give it a try and guess what its worked as promised. I am able to develop and deploy a lambda function using Perl (no kidding!!).

Lets quickly review the key points for lambda custom runtimes and then we will go through some real code to try it out.

  • The runtime is responsible to execute the lambda function’s code, it reads the handler info (file name and the method name) from the pre-defined environment variable _HANDLER
  • The runtime passes the event data to the function handler, and posts the response from the handler back to Lambda.
  • The custom runtime runs on the standard lambda execution environment, so it will be your responsibility to bring along any library or language support you need for the custom runtime.
  • Make sure the lambda Runtime is as below on AWS console or “Provided” in the create-function lambda CLI.
Image for post
Image for post
  • The runtime can be included in your function’s deployment package, or in a layer.
  • A custom runtime’s entry point is an executable file named as “bootstrap”, it should be in the lambda deployment package or in a referenced lambda layer

Key environment variables that you should be using in the bootstrap file to initialize and executethe lambda task:

  • _HANDLER: The format is , the method in this file will be executed
  • LAMBDA_TASK_ROOT: This is where on lambda execution environment the deployment package files will be available. The value is “/var/task” and its a read-only location

I have mentioned a few of the key steps in bootstrap executable file below, for additional details refer here:

  • Initialize the function — Load the handler file.
  • Handle errors — If an error occurs, call the initialization error API and exit immediately.
  • Get an event — Call the next invocation API to get the next event. The response body contains the event data. Response headers contain the request ID and other information.
  • Create a context object — Create an object with context information from environment variables and headers in the API response.
  • Invoke the function handler — Pass the event and context object to the handler.
  • Handle the response — Call the invocation response API to post the response from the handler.

Lets deep-dive on how we can develop a lambda using perl runtime:

A lambda function code in perl needs the perl interpreter and the dependant libraries.

  • I downloaded the ActivePerl community edition for linux (x86_64) from here
  • I created a lambda layer using the download file, you cannot upload it as-is due to size limitation, lambda layer only supports a zip file upto 50MB so to keep the size within limit I had to delete the man and html directories, the final zip file only has below directories:
Image for post
Image for post
  • The lambda layer looks as below:
Image for post
Image for post

Let's take a quick look into the bootstrap file:

  • Its a shell script
  • Extract the lambda handler file name and the handler method from the environment variable _HANDLER
  • Run an infinite loop to handle incoming requests
  • Get the EVENT_DATA from the lambda runtime API: http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/next
  • Get the REQUEST_ID from the HEADERS
  • I have a template perl script perl_runtime.pl.tpl that acts as a glue code between the bootstrap and the actual lambda handler file, I have kept it so that I can create a perl script with the actual handler file name and the function name.
  • The bootstrap executable file and the perl_runtime.pl.tpl file is in a separate lambda layer named as perl-runtime:
Image for post
Image for post
  • The bootstrap file and perl_runtime.pl.tpl are already in PATH and available under “/opt/”
  • The bootstrap executable file copy over the perl_runtime.pl.tpl file to /tmp and replaces the placeholder variable with actual values and create the actual perl_runtime.pl
  • The bootstrap executable also copy over the actual lambda handler file to /tmp so that it can be invoked by the perl_runtime.pl
  • As we already have perl interpreter as runtime and the lambda will refer it, so the interpreter and the libraries are already available under “/opt/perl” and the bootstrap executable using them as below to involve the perl_runtime.pl script:

Lambda Handler Script:

The lambda handler script file “lambda_script.pl” just read the incoming json event and add a reply field and return back the same.

The actual execution flow:

Image for post
Image for post

Lambda function deployment:

  • Create perl interpreter lambda layer:

This is the perl interpreter and the library zip file.

  • Create perl-runtime lambda layer:

It has the bootstrap executable shell script and perl_runtime.pl.tpl files

  • Create the lambda function:

The perl-lambda-poc.zip file contains the lambda_script.pl file, the actual lambda function handler.

You can invoke the lambda function with any json payload, I tested it with:

And the response came back as:

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch

Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore

Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store