Developers write code. They shouldn’t have to worry about the infrastructure running that code. Luckily, they have AWS cloud services like Amazon Web Services’ AWS Lambda functions, also known as Lambda, to let them get back to what they do best. In this guide, you’re going to learn how to get started with AWS Lambda and, more specifically, learn how to set up your first AWS Lambda Python!
Stay tuned to learn how Lambda functions work and how to apply your newfound Lambda knowledge by using the Boto3 AWS Python SDK to create a Lambda function and start an EC2 instance.
AWS Lambda Functions: What’s the Hype on Serverless?
Before you get down to brass tax and start learning how to build an AWS Lambda function in Python, let’s first cover why Lambda is great and why you should do this in the first place.
What is Lambda?
AWS Lambda is a serverless computing technology. At a high level, the term ‘serverless’ defines services that allow developers to run code “without” a server. Depending on the programming language you’re using, you’ll find a few different ways of creating a serverless application. One of the most common ways is via Python.
When the underlying server requirements go out the window, it opens up more opportunities to do what developers do; write code. Developers can deploy code and see it in action.
Why Lambda?
Using a serverless platform gives you some key abilities that you may not have elsewhere. Some of those key abilities include:
- Running code based on a response or event – You can schedule code to run at any given time and as many times as you want based on nearly any AWS event. You no longer have to run scripts ad-hoc.
- You don’t need an operating system to run the code on – With serverless functions, you don’t need to set up an environment to run code on. That means you don’t have to set up networking, virtual machines, storage, etc. You just have a place to run code.
- Run almost any type of code – Lambda is compatible with Python, Node.JS, Ruby, Go, Java, C#, and even PowerShell.
- Built-in failover/fault tolerance – The servers that Lambda runs on are located across multiple availability zones in a region.
- Cheap – Lambda functions are cheap. You only pay for what you use for. The code could be sitting in a Lambda Function for as long as you want. As long as it’s not being used, you don’t get charged.
Tutorial Overview on writing AWS Lambda Python
The rest of this article will be a step-by-step tutorial. In this in-depth guide, you’ll create a Lambda function to run Python code to start an EC2 instance. You will learn how to build a Lambda function that:
- Starts an EC2 instance using the Python SDK, Boto3
- Creates an archive of the Boto3 code so it can be ran from Lambda
- Creates an S3 bucket to store the Boto3 code
- Creates a Lambda function using Boto3
- Tests the Lambda function
- Starts an EC2 instance
Prerequisites
If you’d like to follow along with the tutorial, you’ll need a few key items and pieces of software to accomplish the task at hand.
- An AWS EC2 instance – You won’t need anything special for this tutorial.
- Python v3 – You can download and install Python from here. All examples will be using v3.7.6.
- A code editor of your choice – All examples will be using Visual Studio Code with the Python extension installed. If you decide to use another code editor, the screenshots will not be the same.
- An AWS profile configured – The code you’ll be writing with the Boto3 Python library requires authentication to AWS. Configuring a profile using the AWS CLI creates the required profile on the computer.
- An IAM user and role – All examples will assume you already have already created a new IAM user and role created with EC2FullAccess and LambdaFullAccess privileges.
- An AWS S3 bucket – For instructions on how to create an S3 bucket, check out the AWS documentation. All examples in this article will use an S3 bucket called mynewbucket.
- The boto3 Python package – Install by opening up a terminal and running
pip install boto3
Starting an AWS EC2 Instance with Python
Regardless if you’re using Lambda or not, you must write some code to start an EC2 instance in this example. Let’s say you’ve got an EC2 instance that’s only used for development purposes. It doesn’t need to be on all of the time. Rather than having to start the instance manually, let’s build some code to start the instance.
In this section, you’re going to write all of the code necessary to start an EC2 instance using the Boto3 library so open up Visual Studio Code or your favorite editor and start coding!
Importing the Boto3 Library
First, import the Boto3 library. You’ll only need one library for this example.
import boto3
Creating the Boto3 Client
Next, Boto3 has to connect to the EC2 resource. You’ll do this by running the client()
method. The client()
method tells Boto3 which AWS service you want to interact with. In this example, you’ll connect to EC2.
Assign a variable to the client called ec2
. This object will represent the connection to EC2 where you can initiate starting the instance.
ec2 = boto3.client('ec2')
Creating the Python function
To run the Boto3 code, you need a Python function. This function consists of two parameters – event
and context
. Currently, the function you’re building is stored locally. But, this function will be sent up to AWS later and needs to adhere to what Lambda expects. The event
and context
parameters exist, by default, for all Lambda functions.
- The
event
parameter is an object which contains information from the Lambda invoker. The invoker is what kicks off the Lambda function. - The
context
parameter is an object that contains information about the invocation, function, and execution environment as well as the environment being created.
The following snippet shows the start of a function called start_ec2instance()
. This function can be called anything but all future examples will use this name.
def start_ec2instance(event, context):
Once you’ve defined the function, then fill in the code inside of the function. When the Lambda runs, this code actually starts the EC2 instance.
Note below you’ll see an
your_instance_id
placeholder. This is where you need to insert the ID of the EC2 instance the Lambda function will be starting. To learn more about retrieving an instance ID, please follow these instructions.
def start_ec2instance(event, context):
ec2.start_instances(InstanceIds= ['your_instance_id'])
Once you finish with the code, you’ll have a script that looks like the following:
import boto3
ec2 = boto3.client('ec2')
def start_ec2instance(event, context):
ec2.start_instances(InstanceIds= ['your_instance_id'])
Now that the code is written, save the script as start_ec2instance.py to your computer. You’ll need it in the next section.
Uploading the Python Function to S3
Once the Python script is created, Lambda needs a way to access it. A common place to store Lambda code is in AWS S3.
Before you can upload the script, it must first be archived or compressed into a ZIP file. First, create a ZIP archive of the Python script in your preferred manner. Once that’s done, upload the ZIP file to the S3 bucket you should have created in the Prerequisites section.
Creating a Lambda Build Function
In the previous sections, you learned how to create a Python script and upload it to an S3 bucket. In this section, you’ll put that Python to good use by creating the Lambda function that will use it.
Note that there’s a difference between the
start_ec2instance()
function created earlier, the function you’ll be building in this section and a AWS Lambda Function (uppercase).
In the previous section, you created the Python code the Lambda Function will invoke. In this section, you will create the Python code to create the Lambda Function. Once you write the code to create the Lambda Function, the Lambda Function will then invoke the start_ec2instance()
code.*
Assuming you’re still in Visual Studio Code, open up another tab and save it as lambda_build.py. Let’s now get down to writing the Lambda function itself.
If you’re not interested in the breakdown of how the code works, feel free to make a copy from the following snippet and save it to your lambda_build.py script. You can then skip down to the Testing the Lambda Function Locally section to continue.
Be sure to replace the placeholders
[s3_bucket_name]
and[zip_file_name]
with the appropriate values.
def lambda_build():
client = boto3.client('lambda')
create_lambda_function = client.create_function(
FunctionName=LambdafunctionName,
Runtime='python3.7',
Role=iamRole,
Handler='{}.lambda_handler'.format('lambda_build'),
Description='Start a virtual machine',
Code = {'S3Bucket':'[s3_bucket_name]', 'S3Key':'[zip_file_name]'}
)
Modules
The Lambda function you’re creating will need three Python modules:
- boto3 – The AWS Python SDK
- logging – A standard Python module to create log messages.
- sys – A standard Python module that will be used to pass parameters to the function at runtime. You’ll use this in exchange for many
input
functions.
import boto3
import logging
import sys
Writing the Code to Create the Lambda Function
Start by creating a Python function called lambda_build
. The function doesn’t have to be called this but all future examples will use this name. Inside, create a variable called client
using the client()
method again. This time, instead of ec2
, this the code is connecting to Lambda.
def lambda_build():
client = boto3.client('lambda')
Once the client
is created, run the create_function()
method. The create_function()
method will actually create the Lambda Function.
create_lambda_function = client.create_function()
The create_function()
method has a few required parameters. Those parameters are shown below:
FunctionName
– The name of the Lambda function. In this tutorial, since the initial Python function created earlier is calledstart_ec2instance
, be sure to use that name.Runtime
– The programming runtime for the Lambda function, which is Python.Role
– The ARN is needed for theRole
parameter. To find your ARN, please follow this link.Handler
– The Lambda handler function is what Lambda uses to invoke the function in code. The function name islambda_build()
.Code
– The code parameter is specifying where the code is located. In this tutorial, the start_ec2instance.zip file created earlier is stored in an S3 bucket.Description
– A metadata description name. For example, start a virtual machine.
Be sure to replace the placeholders
[s3_bucket_name]
and[zip_file_name]
with the appropriate values.
create_lambda_function = client.create_function(
FunctionName=LambdaFunctionName,
Runtime='python3.7',
Role=iamRole,
Handler='{}.lambda_handler'.format('lambda_build'),
Description='Start a virtual machine',
Code = {'S3Bucket':'s3_bucket_name', 'S3Key':'zip_file_name'}
)
You should now have a Python function called lambda_build()
that is capable of creating a Lambda function like below:
def lambda_build(LambdaFunctionName, iamRole):
client = boto3.client('lambda')
create_lambda_function = client.create_function(
FunctionName=LambdaFunctionName,
Runtime='python3.7',
Role=iamRole,
Handler='{}.lambda_handler'.format('lambda_build'),
Description='Start a virtual machine',
Code = {'S3Bucket':'name_of_your_s3_bucket', 'S3Key':'file_name_of_zipped_python_code'}
)
Executing the Lambda Build Function
Now that the build function is created, you can now create the code to invoke the function. This is the code that will actually invoke the build function to create the Lambda function.
To invoke the build function created earlier, create two runtime parameters called FunctionName
and Role
as seen in the following snippet.
def lambda_build(LambdaFunctionName, iamRole):
Next, assign values to those parameters via input from the sys
module. When the Lambda function eventually runs, you will pass parameters to the Lambda function. The values of these parameters will be held in sys.argv[1]
and sys.argv[2]
.
The
sys
library takes the parameter that you define and stores anargument
runtime in the parameter. This way Python knows which order the parameters should be ran in.
LambdaFunctionName = sys.argv[1]
iamRole = sys.argv[2]
Once you’ve assigned parameter values, the only thing left to do is invoke the Lambda build function to create the Lambda function itself.
lambda_build(LambdaFunctionName, iamRole)
You will eventually come up with script called lambda_build.py that is capable of creating the Lambda function.
import boto3
import logging
import sys
def lambda_build(LambdaFunctionName, iamRole):
client = boto3.client('lambda')
create_lambda_function = client.create_function(
FunctionName=LambdaFunctionName,
Runtime='python3.7',
Role=iamRole,
Handler='{}.lambda_handler'.format('lambda_build'),
Description='Start a virtual machine',
Code = {'S3Bucket':'name_of_your_s3_bucket', 'S3Key':'file_name_of_zipped_python_code'}
)
LambdaFunctionName = sys.argv[1]
iamRole = sys.argv[2]
lambda_build(LambdaFunctionName, iamRole)
Testing the Lambda Function Locally
You’ve now built the code that the Lambda function will invoke when executed. You’ve also built the code to create the Lambda function itself. Now, it’s time to run the Lambda build code to see if a new Lambda function is created.
Open a terminal and navigate to the directory that contains the lambda_build.py script created earlier. Run the following command to execute the Python script that will create the Lambda function.
Be sure to replace the
[lambda_role_arn]
placeholder with the IAM role ARN you should have created for this tutorial.
python .\lambda_build.py 'devlambda' '[lambda_role_arn]'
Once the Python script runs, navigate to the AWS console. In the Find Services search bar, type Lambda and click on the Lambda option.
You should now see the Lamba created. In the following screenshot, you can see a Lambda function called devlambda. This is the name of the Lambda function passed by running the lambda_build.py script created earlier.
python .\lambda_build.py 'devlambda' '[lambda_role_arn]'
Testing the Lambda Function on AWS
The Lambda function has been created in your AWS account. The hard part is over! Let’s now run the Lambda function for real.
Stop the Demo EC2 Instance
First, stop the EC2 instance the Lambda function is targeting. Remember that the start_ec2instance()
function created earlier starts an EC2 instance. It doesn’t first ensure that it’s stopped. You must stop the EC2 instance to confirm the Lambda function will start it.
Change Runtime Parameters
Navigate to your Lambda function and find Function code. There you will see the start_ec2instance()
code from the start_ec2instance.py script created earlier.
Change the Handler
information to lambda_function.start_ec2instance
. Changing the Handler tells Lambda to run the script name start_ec2instance.py
and the function name start_ectinstance()
.
The script name always comes first followed by the function name.
Configure the Test
Next, run a test of the Lambda function by clicking the Test button in the following screenshot.
If this is your first test, you will see a screen to create a new test. Since there are no inputs needed, keep the default
Hello World
template.
If this is not the first time testing the Lambda, you will be prompted to Configure test event. Keep all of the defaults and click the orange Create button as shown in the following screenshot.
Run the Test
Here it is! The moment you’ve been waiting for.
Now, click on the Test button. If successful, you will be notified of a successful execution as shown in the following screenshot.
To ensure the Lambda worked as intended, navigate to your EC2 instance. You should now see the EC2 instance you stopped earlier is now running!
Congrats! You have successfully started an EC2 instance with a Lambda function!
Summary
In this blog post, you saw first hand how to not only create a working Lambda function but how to write the Python code necessary to make the Lambda function work. Using a serverless function with no infrastructure, you were able to run code that changed your AWS environment.
Take this knowledge a step further. Use the same code provided in this tutorial to modify the Lambda function to trigger off an AWS event; try to start the EC2 instance based on a CloudWatch event.