Managing AWS EC2 and RDS instances can be a repetitive task, especially when you need to start or stop instances based on specific conditions or schedules. Automating these tasks using AWS Lambda can save time and reduce the risk of human error. In this blog post, we'll explore a simple Node.js-based AWS Lambda function that starts or stops EC2 and RDS instances based on environment variables. Additionally, we'll discuss how to use Amazon EventBridge to schedule the Lambda function and how to add a Lambda layer for Node.js dependencies.
You can find the complete code for this project on my GitHub repository.
Prerequisites
Before diving into the code, ensure you have the following:
- AWS Account: Access to an AWS account with permissions to manage EC2 and RDS instances.
- Node.js: Installed on your local machine.
- AWS SDK for JavaScript: Included in your project dependencies.
Project Setup
First, let's look at the package.json
file to understand the project dependencies and structure.
{
"name": "aws-lambda",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"aws-sdk": "^2.1678.0"
}
}
The key dependency here is the aws-sdk
, which allows us to interact with AWS services.
Lambda Function Code
The main logic of our Lambda function is in the index.js
file. This file initializes AWS clients, retrieves environment variables, and defines the Lambda handler function along with helper functions to start and stop instances.
Importing AWS SDK and Initializing Clients
import AWS from 'aws-sdk';
// Initialize AWS clients
const ec2 = new AWS.EC2();const rds = new AWS.RDS();
We import the AWS SDK and initialize the EC2 and RDS clients.
Retrieving Environment Variables
// Get environment variables
const EC2_INSTANCE_IDS = process.env.EC2_INSTANCE_ID;
const RDS_INSTANCE_IDS = process.env.RDS_INSTANCE_ID;
const ACTION = (process.env.ACTION || 'stop').toLowerCase();
We retrieve the instance IDs and the action (start or stop) from environment variables. The action defaults to 'stop' if not specified.
Lambda Handler Function
export const handler = async (event) => {
try {
if (ACTION === 'start') {
await startInstances();
} else if (ACTION === 'stop') {
await stopInstances();
} else {
return {
statusCode: 400,
body: `Invalid ACTION specified: ${ACTION}. Use "start" or "stop".`
};
}
return {
statusCode: 200,
body: `Successfully executed ${ACTION} action on specified instances.`
};
} catch (error) {
return {
statusCode: 500,
body: `Error executing ${ACTION} action: ${error.message}`
};
}
};
The handler
function is the entry point for the Lambda function. It checks the action and calls the appropriate helper function (startInstances
or stopInstances
). If the action is invalid, it returns a 400 status code with an error message. In case of any errors during execution, it returns a 500 status code with the error message.
Helper Functions
The startInstances
and stopInstances
functions handle the logic for starting and stopping the EC2 and RDS instances, respectively.
Starting Instances
const startInstances = async () => {
await ec2.startInstances({ InstanceIds: [EC2_INSTANCE_IDS] }).promise();
console.log(`Started EC2 instances: ${EC2_INSTANCE_IDS}`);
await rds.startDBInstance({ DBInstanceIdentifier: dbInstanceId }).promise();
console.log(`Started RDS instance: ${dbInstanceId}`);
};
The startInstances
function starts the specified EC2 and RDS instances and logs the actions.
Stopping Instances
const stopInstances = async () => {
await ec2.stopInstances({ InstanceIds: [EC2_INSTANCE_IDS] }).promise();
console.log(`Stopped EC2 instances: ${EC2_INSTANCE_IDS}`);
await rds.stopDBInstance({ DBInstanceIdentifier: RDS_INSTANCE_IDS }).promise();
console.log(`Stopped RDS instance: ${RDS_INSTANCE_IDS}`);
};
The stopInstances
function stops the specified EC2 and RDS instances and logs the actions.
Scheduling the Lambda Function with Amazon EventBridge
To automate the execution of the Lambda function, we can use Amazon EventBridge to create a scheduled rule that triggers the Lambda function at specified intervals.
- Create a Rule: Go to the Amazon EventBridge console and create a new rule.
- Define Schedule: Set the schedule expression (e.g., cron or rate expression) to specify when the Lambda function should be triggered.
- Add Target: Add the Lambda function as the target for the rule.
Adding a Lambda Layer for Node.js Dependencies
To reduce the size of your Lambda deployment package and manage dependencies more efficiently, you can use a Lambda layer. Here's how to create and use a Lambda layer for Node.js dependencies:
-
Create a Layer:
-
Create a directory for the layer and install the dependencies:
mkdir nodejs cd nodejs npm install aws-sdk cd .. zip -r layer.zip nodejs
-
Upload the layer.zip
file to the AWS Lambda console to create a new layer.
-
Attach the Layer:
- Go to your Lambda function configuration and add the created layer.
Deploying the Lambda Function
To deploy this Lambda function, follow these steps:
- Zip the Project: Create a zip file of your project directory.
- Upload to AWS Lambda: Go to the AWS Lambda console, create a new function, and upload the zip file.
-
Set Environment Variables: Configure the environment variables (
EC2_INSTANCE_ID
,RDS_INSTANCE_ID
, andACTION
) in the Lambda function settings. - Attach the Layer: Attach the previously created Lambda layer to your function.
- Test the Function: Use the AWS Lambda console to test the function with different actions (start and stop).
Conclusion
By automating the management of EC2 and RDS instances using AWS Lambda and Amazon EventBridge, you can streamline your operations and ensure that your instances are only running when needed. This not only saves costs but also reduces the manual effort involved in managing these resources. The provided code serves as a basic template that you can extend and customize based on your specific requirements. Additionally, using Lambda layers helps manage dependencies more efficiently and keeps your deployment package size small.
Top comments (0)