If your EC2 instances in AWS are managed through Auto Scaling Groups, it is easy to schedule startup and shutdown of those instances, e.g. to save money.
This tutorial walks you through setting up an AWS Lambda function that is triggered by CloudWatch Events and automatically changes the min, max and desired instances in your Auto Scaling Group(s).
The idea is to toggle between 0 (stop
) and a specifed min, max and desired amount of instances (start
), so you only need a single Lambda function. The premise is that you do not touch these Auto Scaling Group settings manually, or you might make your EC2 instances nocturnal.
- Open AWS Lambda in the console and click
Create a Lambda function
. - On the
Select blueprint
page, selectBlank function
. - On the
Configure Triggers
page, click the grey square and selectCloudWatch Events
. - From the
Rule
dropdown, selectCreate a new rule
. - Enter a
Rule name
andRule description
. - For
Rule type
, selectSchedule expression
. - For
Schedule expression
, enter a Cron expression to specify at which day(s) and time this event should trigger.
For now only specify the event to start servers (E.g. at the beginning of the weekday). We will confire the second event later in this tutorial.
E.g.cron(00 06 ? * MON-FRI *)
fires every weekday (Monday to Friday) at 6:00 AM UTC. See this website for a handy Cron calculator. - Enable the
Enable trigger
checkbox. - Click
Next
.
- On the
Configure function
page, enter aName
andDescription
for the function. - For
Runtime
, selectPython 2.7
. - For
Code entry type
make sureEdit code inline
is selected. - Delete the existing code and paste the following code into the code field:
import os
import boto3
client = boto3.client('autoscaling')
def get_env_variable(var_name):
msg = "Set the %s environment variable"
try:
return os.environ[var_name]
except KeyError:
error_msg = msg % var_name
def lambda_handler(event, context):
auto_scaling_groups = get_env_variable('NAMES').split()
for group in auto_scaling_groups:
if servers_need_to_be_started(group):
action = "Starting"
min_size = int(get_env_variable('MIN_SIZE'))
max_size = int(get_env_variable('MAX_SIZE'))
desired_capacity = int(get_env_variable('DESIRED_CAPACITY'))
else:
action = "Stopping"
min_size = 0
max_size = 0
desired_capacity = 0
print action + ": " + group
response = client.update_auto_scaling_group(
AutoScalingGroupName=group,
MinSize=min_size,
MaxSize=max_size,
DesiredCapacity=desired_capacity,
)
print response
def servers_need_to_be_started(group_name):
min_group_size = get_current_min_group_size(group_name)
if min_group_size == 0:
return True
else:
return False
def get_current_min_group_size(group_name):
response = client.describe_auto_scaling_groups(
AutoScalingGroupNames=[ group_name ],
)
return response["AutoScalingGroups"][0]["MinSize"]
-
For
Environment variables
add the following:
NAMES
- Space separated list of the Auto Scaling Groups you want to manage with this function
MIN_SIZE
- Minimum size of the Auto Scaling Group(s) when EC2 instances are started
MAX_SIZE
- Maximum size of the Auto Scaling Group(s) when EC2 instances are started
DESIRED_CAPACITY
- Desired capacity of the Auto Scaling Group(s) when EC2 instances are started -
For
Handler
, make sure the value islambda_function.lambda_handler
. -
For
Role
, selectCreate a custom role
. An IAM wizard will open in a new tab. -
For
IAM Role
, selectCreate a new IAM Role
. -
Enter a
Role Name
. -
Click on
View Policy Document
and clickEdit
. -
A warning popup will appear. Click
Ok
. -
Add the following statement right after the closing } of
"Resource": "arn:aws:logs:*:*:*" }
,
{
"Effect": "Allow",
"Action": "autoscaling:*",
"Resource": "*"
}
-
Click on
Allow
. -
Back on the
Configure function
screen, make sure your new Role is selected underExisting role
. -
Click on
Next
andCreate Function
.
- To configure the second event (to stop your servers at the end of the weekday), on the
Triggers
tab of your new Lambda function, click onAdd trigger
. - In the
Add trigger
popup, from theRule
dropdown, selectCreate a new rule
. - Enter a
Rule name
andRule description
. - For
Rule type
, selectSchedule expression
. - For
Schedule expression
, enter a Cron expression to specify at which day(s) and time this event should trigger.
E.g.cron(00 20 ? * MON-FRI *)
fires every weekday (Monday to Friday) at 20:00 PM UTC. See this website for a handy Cron calculator. - Enable the
Enable trigger
checkbox.
That's it, all done!
You can test the function by hitting the Test
button. The first time an Input test event
popup will appear.
For Sample event template
select Scheduled event
and click Save and test
.
This tutorial on Nick Todd's blog helped me setting up this tutorial.