Hello, AWS Lambda — an introduction
Let's have a practical introduction to the most fundamental service in AWS' serverless catalogue.
AWS Lambda
Python
AWS Lambda has been made available in 2014 and enabled a massive host of new use cases within AWS’ catalogue of services, including running code in response to events — providing somewhat of a bridge between services.
Within AWS Lambda, your Python, C#, Node.js or Java code can be triggered by just about anything you wish — e.g. a machine invoking internal devices after recording certain temperatures. Of course, there are many more examples, but we won’t be taking a deep dive in this article.
The execution of Lambda tasks could result in a report, or it could trigger other services (or even yet another Lambda). That’s why I used the word ‘bridge’ — we trigger events from one side, passing the results of their invocations around our system. Conceptually those work just like your typical function in programming — but they are distributed and serverless.
Advantages of AWS Lambda
It’s worth exploring different ways of creating software. We can try to use a monolith or to break it smaller, distributed parts — typically called microservices.
These two opposite approaches have their pros and cons but one major disadvantage of monoliths requires mentioning. perhaps, one big module may work better if we look at it from a programmer’s side. After all, it is easier to manage one service and debug/maintain it, but unpredictable errors on a single service will also cripple all other functionalities of the monolith.
This raises the question, why not cut the project into slices, just like we cut bread in the morning? This is precisely why we’re using Lambda… Providing the functionality of reacting and passing events, we get a tool which helps us divide modules into parts and establish good communication between them. But why AWS Lambda? Why can’t I write my local distributed system with all the necessary functionalities?
Of course, you can, but try to bind together a database, mail service, and the main part of service using bare Python code… I believe you’d consider using Lambda faster than you’d think, especially if two of these services are provided by AWS.
Common AWS Lambda use cases
There are many situations where Lambda rules the roost in practice.
Serverless websites
We could start off by taking advantage of hosting the web frontend on S3. This frontend can send requests to Lambda functions via API Gateway. Lambda can handle application logic and channel the data to our database (one example would be DynamoDB for non-relational databases). So… we tie the frontend and backend using just one service. Great facilitation, don’t you think?
Log analysis on the fly
What’s more, you could easily create a Lambda function to check log files from Cloudtrail or Cloudwatch. Lambda can search through the logs for specific entries and send out notifications via SNS. Of course, SNS is not the only service we can handle with lambda — we can use it to send messages with any other service using their own API.
Automated backups and everyday tasks
You could use
boto3
Python libraries to quickly implement tasks that create backups, check for idle resources, generate reports, and do any other fancy stuff. I’m aware that most people tend to forget about important things, like backups and work reports, but we shouldn’t! They are the things protecting us from some long-term problems with applications.Processing S3 object uploads
You can use S3 object event notifications to immediately start processing your files by Lambda once they land in S3 buckets. This is another type of invoking event, now connected with S3 buckets service.
Filtering and transforming data on the fly
Because Lambda is highly scalable, it is great for transitioning data between S3, Redshift, Kinesis, and database services, as well as filtering on the fly. So, Lambda is not just a thing that is loaded between services to provide communication, but it can also work with data, transform it, and pass it further if and when needed.
I’m sure we can agree that’s quite a lot, but the examples mentioned were theoretical textbook examples. That said, it’s time to take a look at some practical usage.
AWS Lambda handler function in Python
To create a Lambda function, in essence you specify a handler — i.e. a function in your code — that AWS Lambda can invoke when the service executes your code.
The following general structure and signature applies to Lambda handler functions (written in Python):
def handler_name(event, context):
...
return some_value
Parameters:
event
— used to pass event data to the handler. This is usually adict
type but can be of other types as well (this includes theNoneType
).context
— used to provide runtime information to your handler. This parameter is of theLambdaContext
type.
Here’s an example of an AWS Lambda handler function in Python:
def my_handler(event, context):
return {
'message': 'Hello {} {}!'.format(event['first_name'], event['last_name'])
}
The code above depicts a single function called my_handler
. It returns a message
containing data from the event
that is received as input.
AWS Lambda layers
Layers are a completely new feature made available in 2018. They are essentially ZIP archives which contain libraries and some dependencies. They help you keep your deployment package small and thus simplify development in general.
A typical way of lambda deployment is to pack the code into a zip file and upload it. It fulfills its role when we think about small pieces of code with little dependencies, otherwise, we need to be prepared for uploading the entire zip file every time, even if our changes are not that significant.
The layer feature gives us the possibility to divide our code into pieces and upload only parts that were modified or simply upload newly created code using new layers. Another great feature that is worth mentioning is the possibility to define programing language in runtime parameters to find corresponding libraries. If we are talking about runtime, we can introduce the last big advantage: defining default runtime. We can use it to prepare work environments for people e.g. without knowledge of dependencies in Python language.
Layers are extracted to the /opt
directory execution environment in function. Each runtime looks for libraries in a different location under /opt
, depending on the language.
Make sure your layers are structured properly so that the libraries can be accessed without any need for additional configuration. /opt
is added to the $PATH
environment variable.
Up to 5 layers can be specified in your function’s configuration. You choose a specific version of a layer to use. To add layers to your function, use the update-function-configuration command.
Creating your own layers
It’s a straightforward process, consisting of the following steps:
- Creating a virtual environment and installing required dependencies
pipenv --python 3.6
pipenv shell
pipenv install troposphere
pipenv install awacs
- Building a deployment package
PY_DIR='build/python/lib/python3.6/site-packages'
mkdir -p $PY_DIR
pipenv lock -r > requirements.txt
pip install -r requirements.txt --no-deps -t $PY_DIR # Install
cd build
zip -r ../tropo_layer.zip . # Zip
cd ..
rm -r build
- Creating a layer (and a test Lambda function)
aws lambda update-function-configuration --function-name tropo_function_test --layers arn:aws:lambda:eu-central-1:xxxxxxxxxxxx:layer:tropo_test:1
- Adding a local library to your layer
cp -r local_module 'build/python/lib/python3.6/site-packages'
- Finally, updating the AWS Lambda layer
aws lambda update-function-configuration --function-name tropo_function_test --layers arn:aws:lambda:eu-central-1:xxxxxxxxxxxx:layer:tropo_test:2
And that’s the gist of it.
I hope you found, at least, some of the information useful. AWS Lambda is one of the fastest-growing services, and it’s getting used in more and more modern software. I hope the article encouraged you to use it on your own, or at the very least, just to give Lambda a chance.