Automating AWS EC2 and RDS Instance Management with AWS Lambda

init_chandan

Chandan Singh

Posted on September 3, 2024

Automating AWS EC2 and RDS Instance Management with AWS Lambda

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:

  1. AWS Account: Access to an AWS account with permissions to manage EC2 and RDS instances.
  2. Node.js: Installed on your local machine.
  3. 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"
}
}
Enter fullscreen mode Exit fullscreen mode

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();
Enter fullscreen mode Exit fullscreen mode

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();
Enter fullscreen mode Exit fullscreen mode

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}`
        };
    }
};
Enter fullscreen mode Exit fullscreen mode

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}`);

};
Enter fullscreen mode Exit fullscreen mode

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}`);

};
Enter fullscreen mode Exit fullscreen mode

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.

  1. Create a Rule: Go to the Amazon EventBridge console and create a new rule.
  2. Define Schedule: Set the schedule expression (e.g., cron or rate expression) to specify when the Lambda function should be triggered.
  3. 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:

  1. 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.

  1. 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:

  1. Zip the Project: Create a zip file of your project directory.
  2. Upload to AWS Lambda: Go to the AWS Lambda console, create a new function, and upload the zip file.
  3. Set Environment Variables: Configure the environment variables (EC2_INSTANCE_ID, RDS_INSTANCE_ID, and ACTION) in the Lambda function settings.
  4. Attach the Layer: Attach the previously created Lambda layer to your function.
  5. 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.

💖 💪 🙅 🚩
init_chandan
Chandan Singh

Posted on September 3, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related