Having multiple environments is important to build a continuous integration/deployment pipeline and be able to reproduce bugs in production with ease but this comes at price. In order to reduce cost of AWS infrastructure, instances which are running 24/7 unnecessarily (sandbox & staging environments) must be shut down outside of regular business hours.
The figure below describes an automated process to schedule, stop and start instances to help cutting costs. The solution is a perfect example of using Serverless computing.
2 Lambda functions will be created, they will scan all environments looking for a specific tag. The tag we use is named ‘Environment’. Instances without an Environment tag will not be affected:
for _, reservation := range res.Reservations { for _, instance := range reservation.Instances { for _, tag := range instance.Tags { if *tag.Key == "Name" { instances = append(instances, Instance{ ID: *instance.InstanceId, Name: *tag.Value, }) } } } }
return instances, nil }
The StartEnvironment function will query the StartInstances method with the list of instance ids returned by the previous function:
Finally, create an IAM role for each function and attach the above policies:
1 2 3 4 5 6 7 8 9 10 11 12 13
#!/bin/bash
echo "IAM role for StartEnvironment" arn=$(aws iam create-policy --policy-name StartEnvironment --policy-document file://start/policy.json | jq -r '.Policy.Arn') result=$(aws iam create-role --role-name StartEnvironmentRole --assume-role-policy-document file://role.json | jq -r '.Role.Arn') aws iam attach-role-policy --role-name StartEnvironmentRole --policy-arn $arn echo "ARN: $result"
echo "IAM role for StopEnvironment" arn=$(aws iam create-policy --policy-name StopEnvironment --policy-document file://stop/policy.json | jq -r '.Policy.Arn') result=$(aws iam create-role --role-name StopEnvironmentRole --assume-role-policy-document file://role.json | jq -r '.Role.Arn') aws iam attach-role-policy --role-name StopEnvironmentRole --policy-arn $arn echo "ARN: $result"
The script will output the ARN for each IAM role:
Before jumping to deployment part, we need to create a Slack WebHook to be able to post messages to Slack channel:
Next, use the following script to deploy your functions to AWS Lambda (make sure to replace the IAM roles, Slack WebHook token & the target environment):
Once deployed, if you sign in to AWS Management Console, navigate to Lambda Console, you should see both functions has been deployed successfully:
StartEnvironment:
StopEnvironment:
To further automate the process of invoking the Lambda function at the right time. AWS CloudWatch Scheduled Events will be used.
Create a new CloudWatch rule with the below cron expression (It will be invoked everyday at 9 AM):
And another rule to stop the environment at 6 PM:
Note: All times are GMT time.
Testing:
a – Stop Environment
Result:
b – Start Environment
Result:
The solution is easy to deploy and can help reduce operational costs.
Full code can be found on my GitHub. Make sure to drop your comments, feedback, or suggestions below — or connect with me directly on Twitter @mlabouardy.