API Gateway & Lambda Integration to Start and Stop EC2 Instances
Introduction:
The integration of Amazon API Gateway and AWS Lambda provides a powerful solution for building scalable and serverless APIs. By combining these services, developers can create dynamic and flexible APIs that respond to HTTP requests with custom logic, all without managing servers or infrastructure. One common use case for this integration is automating the control of Amazon Elastic Compute Cloud (EC2) instances, allowing users to start and stop instances programmatically via API calls.
API Gateway acts as the front door for APIs hosted on AWS, offering features such as request routing, authorization, and rate limiting. It enables developers to define RESTful APIs and expose them to clients over HTTP or HTTPS. With API Gateway, developers can create endpoints that trigger Lambda functions, enabling seamless integration between incoming requests and backend processing.
AWS Lambda is a serverless compute service that allows developers to run code in response to events without provisioning or managing servers. Lambda functions are lightweight, stateless, and can be written in various programming languages, making them ideal for executing short-lived tasks, such as starting and stopping EC2 instances. Lambda functions can be triggered by various events, including API Gateway requests, making them a natural fit for building APIs.
Integrating API Gateway with Lambda to start and stop EC2 instances provides a convenient and efficient way to manage compute resources programmatically. Users can make HTTP requests to predefined API endpoints, which in turn trigger Lambda functions responsible for initiating the desired EC2 instance actions. This approach offers scalability, flexibility, and cost-effectiveness, as resources are only consumed when the API is invoked.
In this guide, we’ll explore how to set up this integration, create API endpoints for starting and stopping EC2 instances, and implement the corresponding Lambda functions to execute these actions. We’ll also cover best practices for securing and monitoring the API, as well as tips for optimizing performance and minimizing costs. By the end of this guide, you’ll have a working API Gateway and Lambda integration that enables seamless control of EC2 instances via HTTP requests.
IAM
we need to create an IAM role for the Lambda function to access the EC2 service.
Go to the IAM service > Roles > Create role
- Select “Lambda” as use case.
- Attach “AmazonEC2FullAccess” policy to the role.
- Give a name for the role. Here, I’m going with “ec2stoprole”. You can choose any name of your wish.
- Finally, create the role
- Lambda
- We need to create three lambda functions to:
get instance id’s of running instances, start an instance & stop an instance.
Go to Lambda > Create function
- Select “Author from scratch”.
- Give a name for the function. Here, I’m using “startstop” (any name can be given).
- Select “Python 3.10” as Runtime.
- Select “x86_64” as Architecture.
Click on “Change default execution role” to expand the option.
- Select “Use an existing role” under Execution role option.
- Select the IAM role “ec2stoprole” we created earlier.
- Create the function.
- Once created, select the Function and scroll down to the “Code source” section.
- Paste the following code.
import json
import boto3
def lambda_handler(event, context):
# Initialize the EC2 client
ec2 = boto3.client('ec2', region_name='eu-west-2')
# Define the filters to get running instances
filters = [{
'Name': 'instance-state-name',
'Values': ['running']
}]
# Get the running instances
response = ec2.describe_instances(Filters=filters)
# Extract instance IDs from the response
instance_ids = []
for reservation in response['Reservations']:
for instance in reservation['Instances']:
instance_ids.append(instance['InstanceId'])
# Return the response
return {
'statusCode': 200,
'body': json.dumps('Fetch all running EC2 instance IDs!'),
'instance_ids': instance_ids
}
- Once the code is pasted, click on the “Deploy” button to deploy the code.
Explanation:
The lambda_handler
function is the entry point for the Lambda function. It takes two parameters: event
and context
. The event
parameter contains information about the triggering event that invoked the Lambda function, while the context
parameter provides runtime information.
Inside the lambda_handler
function, an EC2 resource object is created using boto3.resource('ec2')
. The region is set to 'eu-west-2'.
A filter condition is defined to filter instances based on their state. In this case, it filters for instances that are in the ‘running’ state.
The ec2.instances.filter
method is called with the filter condition to retrieve all the instances that match the filter. The resulting instances are then iterated over, and their IDs are appended to the instance_ids
list.
Finally, the function returns a response in JSON format. The statusCode
is set to 200 to indicate a successful response. The body
field contains a string message indicating the purpose of the function, and the instance_ids
field contains the list of instance IDs as a JSON string.
Repeat the above steps to create another function to “Start” the instance and paste the following code.
import boto3
import logging
# Initialize logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)
region = 'eu-west-2'
instances = ['i-07############']
ec2 = boto3.client('ec2', region_name=region)
def lambda_handler(event, context):
try:
# Start instances
ec2.start_instances(InstanceIds=instances)
logger.info('Starting instances: %s', instances)
return {
'statusCode': 200,
'body': 'Instances started successfully'
}
except Exception as e:
logger.error('An error occurred: %s', str(e))
return {
'statusCode': 500,
'body': 'Error starting instances: ' + str(e)
}
Similarly, create another function to “Stop” the instance and Paste the following code.
import boto3
import logging
# Initialize logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)
region = 'eu-west-2'
instances = ['i-07###########']
ec2 = boto3.client('ec2', region_name=region)
def lambda_handler(event, context):
try:
# Stop instances
ec2.stop_instances(InstanceIds=instances)
logger.info('Stopped instances: %s', instances)
return {
'statusCode': 200,
'body': 'Instances stopped successfully'
}
except Exception as e:
logger.error('An error occurred: %s', str(e))
return {
'statusCode': 500,
'body': 'Error stopping instances: ' + str(e)
}
API Gateway
We need to create an API gateway to trigger the lambda functions.
Go API Gateway service > Create API > Select REST API > Build
- Select “REST” from Choose the protocol.
- Select “New API” from Create new API.
- Give a name for the API. Here, I’m going with “myapi”(you can use any name).
- Now, create the API.
- we need to create Resources and Methods for the API.
- Click on / > Create Resource
- Give a name for the resource. I’m going with “ec2”.
- Create the resource.
- Once the ec2 resource is created, we need to create a sub-resource for the ec2 resource.
- Click on the “ec2” resource > Create Resource.
- sub-resource “running” as this resource is used to get the ID of running instances.
- This is what it looks like after creation.
now, we should create a method for the “running” resource.
- Click on the “running” resource > Create Method.
- Select “GET” from the drop-down menu
- Select “Lambda Function” as Integration type.
- Select the “region”(eu-west-2) where lambda function has been created.
- Select the “lambda function” to be integrated from the list.
We’ve integrated our first API with a lambda function. Now, we need to create new sub-resources as before to integrate with the other lambda functions.
- Click on “ec2” resource > Create Resource.
- Give a name for the new resource. I’m going with “Start”, as this API will be used to start the instance.
- Create the resource
- Now, we should create a method for the “Start” resource.
- Click on the “Start” resource > Create Method.
- Select “POST” from the drop-down menu
- Select “Lambda Function” as the Integration type.
- Select the “region”(eu-west-2) where the lambda function has been created.
- Select the “lambda function”(start) to be integrated from the list.
We’ve integrated the “Start” API with a lambda function. Now, we need to create the final sub-resource and integrate with lambda functions.
- Click on “ec2” resource > Create Resource.
- Give a name for the new resource. I’m going with “Stop”, as this API will be used to stop the instance.
- Create the resource.
- Now, we should create a method for the “Stop” resource.
- Click on the “Stop” resource > Create Method.
- Select “POST” from the drop-down menu
- Select “Lambda Function” as the Integration type.
- Select the “region”(ap-southeast-2) where the lambda function has been created.
- Select the “lambda function”(stop) to be integrated from the list.
We’ve created and integrated APIs with the lambda functions. Now, we deploy the API.
- Click on the “/” on top of the resource we’ve created > Deploy API.
- A new stage has to be created to deploy the API.
- Select “New Stage”.
- Give a new name for the stage. Here, I’m going with “test”. You can provide a description.
- Click on “Deploy”.
- Once deployed, you will get the URLs to trigger the corresponding lambdafunctions.
Now, we need to test it. For this, we need to use the Postman application.
POSTMAN
Let’s first check we could get the ID of the running instances.
- Copy the URL of the “running” resource and paste it into Postman.
- Now, let’s try to stop the instance with the Stop URL.
- Now, let’s try to start the instance with the Start URL.
Conclusion
In conclusion, the integration of API Gateway with Lambda functions offers an efficient and simplified approach to managing EC2 instances on AWS. By leveraging the power of serverless computing, businesses can streamline the process of starting and stopping EC2 instances, ultimately enhancing agility and cost optimization.
thank you for reading!!!