Creating a Lambda function to start and stop an EC2 instance at scheduled times is a common and efficient way to achieve this using AWS services. However, there are alternative methods to consider based on specific requirements, such as AWS Step Functions for complex workflows or AWS EventBridge Scheduler for more flexible scheduling.
Lambda Function with EventBridge (CloudWatch Events) Scheduler
Here’s a step-by-step guide to create a Lambda function to start and stop an EC2 instance:
Step 1: Create IAM Role for Lambda
- Go to the IAM console.
- Create a new role with the following policies:
AWSLambdaBasicExecutionRole
AmazonEC2FullAccess
Step 2: Create the Lambda Function
- Go to the Lambda console.
- Create a new Lambda function.
- Choose Python or Node.js as the runtime (Python example shown here).
- Attach the IAM role created in Step 1.
Python Code:
import boto3
ec2 = boto3.client('ec2')
region = 'us-west-2' # Update to your region
instance_id = 'i-0abcd1234efgh5678' # Update to your instance ID
def lambda_handler(event, context):
action = event.get('action')
if action == 'start':
ec2.start_instances(InstanceIds=[instance_id])
print(f'Started instance: {instance_id}')
elif action == 'stop':
ec2.stop_instances(InstanceIds=[instance_id])
print(f'Stopped instance: {instance_id}')
else:
print('No valid action provided')
return {
'statusCode': 200,
'body': 'Instance action executed successfully'
}
Step 3: Create EventBridge Rules
- Go to the EventBridge (CloudWatch Events) console.
- Create a new rule for starting the instance.
- Event Source: Schedule
- Fixed rate of 1 hour or Cron expression (e.g.,
cron(0 8 * * ? *)
for 8 AM daily) - Target: Lambda function
- Configure input as a constant (JSON text):
{"action": "start"}
- Create another rule for stopping the instance.
- Event Source: Schedule
- Fixed rate of 1 hour or Cron expression (e.g.,
cron(0 20 * * ? *)
for 8 PM daily) - Target: Lambda function
- Configure input as a constant (JSON text):
{"action": "stop"}
Alternatives to Lambda
1. AWS Step Functions
- Use Case: For more complex workflows involving multiple services.
- Benefits: Visual workflow design, integration with many AWS services, state tracking.
2. AWS Systems Manager Automation
- Use Case: When managing multiple instances with predefined automation documents.
- Benefits: Built-in automation documents, approval workflow integration.
3. AWS EventBridge Scheduler (formerly CloudWatch Events)
- Use Case: Directly schedules start/stop actions without using Lambda.
- Benefits: Direct scheduling, simplified setup.
Example for EventBridge Scheduler without Lambda:
- Go to EventBridge console.
- Create a new rule.
- Set the event source to "Schedule".
- Use Cron expressions to define start and stop times.
- For the target, select "EC2" and configure the action (StartInstances or StopInstances).
This approach can be suitable for simpler use cases, reducing the need for custom Lambda functions.
Conclusion
Using AWS Lambda in combination with EventBridge (CloudWatch Events) is a straightforward and common approach for scheduling EC2 instance start/stop actions. For more complex scenarios, AWS Step Functions or Systems Manager Automation might be better suited. For very simple use cases, directly using EventBridge Scheduler can be an effective solution.
The error message "Unable to import module 'lambda_function': No module named 'lambda_function'" indicates that AWS Lambda cannot find the specified module. This error typically occurs when the function handler is not correctly defined or there is a mismatch in the file name and handler name.
Here are the steps to resolve this issue:
Step 1: Verify the File and Handler Name
- File Name: Ensure your file is named
lambda_function.py
. - Handler Name: Ensure the handler is correctly defined in the Lambda configuration. For example, if your file is
lambda_function.py
and the function inside it islambda_handler
, the handler should be specified aslambda_function.lambda_handler
.
Step 2: Verify Lambda Function Configuration
- Go to the AWS Lambda console.
- Select your function.
- In the Configuration tab, check the "Handler" field. It should be
lambda_function.lambda_handler
.
Example Python Code
Ensure your lambda_function.py
looks like this:
import boto3
ec2 = boto3.client('ec2')
region = 'us-west-2' # Update to your region
instance_id = 'i-0abcd1234efgh5678' # Update to your instance ID
def lambda_handler(event, context):
action = event.get('action')
if action == 'start':
ec2.start_instances(InstanceIds=[instance_id])
print(f'Started instance: {instance_id}')
elif action == 'stop':
ec2.stop_instances(InstanceIds=[instance_id])
print(f'Stopped instance: {instance_id}')
else:
print('No valid action provided')
return {
'statusCode': 200,
'body': 'Instance action executed successfully'
}
Step 3: Upload the Code
- Inline Editor: Copy the code directly into the Lambda inline code editor.
- Zip File: If you are uploading a zip file, ensure
lambda_function.py
is at the root level of the zip file.
Step 4: Test the Function
Create a test event in the Lambda console with the following JSON to test the start action:
{
"action": "start"
}
And another for the stop action:
{
"action": "stop"
}
Additional Notes
- Dependencies: If your Lambda function has additional dependencies, ensure they are included in the deployment package.
- IAM Role: Ensure the IAM role attached to your Lambda function has the necessary permissions to start and stop EC2 instances (
AmazonEC2FullAccess
).
Following these steps should resolve the Runtime.ImportModuleError
. If you encounter further issues, please provide more details about your Lambda configuration and deployment process.
To run a command inside an EC2 instance every time it starts, you can use AWS Systems Manager (SSM) Run Command. This allows you to execute scripts or commands on your EC2 instances without needing to SSH into them.
Here’s how you can achieve this:
Prerequisites
- SSM Agent: Ensure the SSM Agent is installed and running on your EC2 instance. Most modern AMIs have it pre-installed.
- IAM Role: Attach an IAM role to your EC2 instance that has the
AmazonSSMManagedInstanceCore
policy.
Step-by-Step Guide
Step 1: Create an IAM Role for EC2
- Go to the IAM console.
- Create a new role.
- Select
EC2
as the trusted entity. - Attach the
AmazonSSMManagedInstanceCore
policy. - Attach this role to your EC2 instance.
Step 2: Modify the Lambda Function to Trigger SSM Run Command
-
Add permissions to your Lambda execution role to allow it to use SSM. Attach the
AmazonSSMFullAccess
policy to the Lambda execution role. -
Modify your Lambda function to use the SSM Run Command to execute the desired command on the EC2 instance when it starts.
Example Lambda Code
Here's an example of how you can modify the Lambda function to run a command via SSM Run Command:
import boto3
ec2 = boto3.client('ec2')
ssm = boto3.client('ssm')
region = 'us-west-2' # Update to your region
instance_id = 'i-0abcd1234efgh5678' # Update to your instance ID
def lambda_handler(event, context):
action = event.get('action')
if action == 'start':
ec2.start_instances(InstanceIds=[instance_id])
print(f'Started instance: {instance_id}')
waiter = ec2.get_waiter('instance_running')
waiter.wait(InstanceIds=[instance_id])
response = ssm.send_command(
InstanceIds=[instance_id],
DocumentName="AWS-RunShellScript", # Use AWS-RunPowerShellScript for Windows
Parameters={
'commands': [
'your-command-here' # Replace with your actual command
]
},
TimeoutSeconds=60
)
print(f'Command executed: {response}')
elif action == 'stop':
ec2.stop_instances(InstanceIds=[instance_id])
print(f'Stopped instance: {instance_id}')
else:
print('No valid action provided')
return {
'statusCode': 200,
'body': 'Instance action executed successfully'
}
Step 3: Create EventBridge Rules
- Go to the EventBridge console.
- Create a new rule for starting the instance.
- Event Source: Schedule
- Fixed rate of 1 hour or Cron expression (e.g.,
cron(0 8 * * ? *)
for 8 AM daily) - Target: Lambda function
- Configure input as a constant (JSON text):
{"action": "start"}
- Create another rule for stopping the instance.
- Event Source: Schedule
- Fixed rate of 1 hour or Cron expression (e.g.,
cron(0 20 * * ? *)
for 8 PM daily) - Target: Lambda function
- Configure input as a constant (JSON text):
{"action": "stop"}
Testing
- Start the EC2 instance manually and verify if the Lambda function triggers the SSM command and executes it.
- Check the SSM Run Command history to verify that the command was executed successfully.
- Ensure that the command runs correctly on the EC2 instance.
By following these steps, you can automate the execution of commands on your EC2 instance every time it starts using AWS Lambda and SSM Run Command.