Recently, I have written an article about launching Instances on the AutoScaling Group in which I have configured CloudWatch alarms to trigger to launch EC2 instances based on aggregate CPU usage within the autoscaling group (used scaling policy).
find the previous article here
Then, I came across that if EC2 instances in AWS are managed through Auto Scaling Groups, it is easy to schedule startup and shutdown of those instances and It opens up a question that a cloud infrastructure always comes at a cost and how to Optimize the Cost of our AWS full Architecture?
Scenario: Developers working on a testing phase of their project and to reduce the cost. The manager decided to Shut down all the AWS Infrastructure services after office hours (shutting down the instances at nights and launch them back on the working mornings). So it becomes cumbersome for the cloud team to re-provision all the environment on a daily basis.
Though, I decided to automate this process using lambda and cloud watch rule.
Note: As usual, I used IaaC (terraform) to all the processes.
Let's dive in,
Steps:
1. Create AWS IAM Role and Policies for Lambda
2. Create AWS LAMBDA function to start and stop instances
3. Use Cron AWS Cloudwatch Rules to trigger Lambda function
Find the full code here
1. Create AWS IAM Role and Policies for Lambda
I created an IAM role for assuming lambda and then attached an inline policy to access autoscaling group
2. Create AWS LAMBDA function to start and stop instances
The below function creates AWS Lambda function and autoscaling.py lambda code has attached to the function.
Now lambda function has created and let's create both start and stop CloudWatch rules
Not please write down below scale-up-daown-lamda.tf file
To Stop the autoscaling EC2 Instance
As you can see from the above code, schedule_expression = "0 0 22 1/1 * ? *" is a Cron expression and which specify at which day(s) and time this event should trigger the event (in my case, 10 pm).
See this website for a handy Cron calculator.
To stop the instance, we have set the MinSize and DesiredSize to 0. So I passed min, desired value as 0 to my lambda function as Jason format below.
To Sart the autoscaling EC2 Instance
The code Exactly the same as the stop instances.schedule_expression = "0 0 7 1/1 * ? *" Cron expression specified to start the autoscaling group at 7am moring.
And MinSize and DesiredSize have given as we configured autoscaling from the beginning. Meaning that it brings back the EC2 instances as Exactly we created the autoscaling group earlier at launch first launch.
Now we can easily we can stop our EC2 instances at night to save money on our cloud bill and automate this process using lambda. To make sure your autoscaling is done properly, we should monitor the EC2 instance with Cloudwatch.
Find the full repo here
That's pretty much it guys! Thank you
Automation
,
Autoscaling
,
AWS
,
cloudwatch
,
cost optimization
,
EC2
,
Lambda
,
Optimize the Cost by Shutting down EC2 Instances using Lambda
find the previous article here
Then, I came across that if EC2 instances in AWS are managed through Auto Scaling Groups, it is easy to schedule startup and shutdown of those instances and It opens up a question that a cloud infrastructure always comes at a cost and how to Optimize the Cost of our AWS full Architecture?
Scenario: Developers working on a testing phase of their project and to reduce the cost. The manager decided to Shut down all the AWS Infrastructure services after office hours (shutting down the instances at nights and launch them back on the working mornings). So it becomes cumbersome for the cloud team to re-provision all the environment on a daily basis.
Though, I decided to automate this process using lambda and cloud watch rule.
Note: As usual, I used IaaC (terraform) to all the processes.
Let's dive in,
Steps:
1. Create AWS IAM Role and Policies for Lambda
2. Create AWS LAMBDA function to start and stop instances
3. Use Cron AWS Cloudwatch Rules to trigger Lambda function
Find the full code here
1. Create AWS IAM Role and Policies for Lambda
I created an IAM role for assuming lambda and then attached an inline policy to access autoscaling group
# /iam.tf
#create a role for lamda access aws resouces
resouce "aws_iam_role" "lamda-iam"{
#role name
name="lamda-asg"
#assume role to a services
assume_role_policy =<<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
# create policy for role to assume autoscaling
resource "aws_iam_role_policy" "autoscaling-lambda-policy"{
name = "autoscaling_lambda_policy"
role = "${aws_iam_role.lamda-iam.id}"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"autoscaling:*"
],
"Resource": "*"
}
]
}
EOF
}
2. Create AWS LAMBDA function to start and stop instances
The below function creates AWS Lambda function and autoscaling.py lambda code has attached to the function.
# /scale-up-daown-lamda.tf
# create lambda
# to invoke autoscaling group
resource "aws_lambda_function" "lambda_test"{
function_name = "lambda_stop_start_autoscaling_instances"
filename = "./autoscaling.zip/autoscaling.py"
role = "${aws_iam_role.lamda-iam.arn}"
handler = "autoscaling.handler"
runtime = "python2.7"
}
Lambda function# /autoscaling.py
import boto3
import os
# Boto Connection
# aws_region, autoscaling-group-name,min,max and desired capacity has to be passed
asg = boto3.client('autoscaling','os.environ[aws_region]')
def lambda_handler(event, context):
response = asg.update_auto_scaling_group(AutoScalingGroupName=os.environ['asg_name'],MinSize=os.environ['min'],DesiredCapacity=os.environ['desired'],MaxSize=os.environ['max'])
Not please write down below scale-up-daown-lamda.tf file
To Stop the autoscaling EC2 Instance
# /scale-up-daown-lamda.tf
#...
#_______stop instances at 10pm everyday_________________
resource "aws_cloudwatch_event_rule" "stop" {
name = "everyday-10"
description = "stop instances everyday 10 pm"
schedule_expression = "0 0 22 1/1 * ? *"
event_pattern = <<PATTERN
{
"aws_region" : "eu-west-1",
"asg_name" : "webapp",
"min" : "0",
"desired" : "0",
"max" : "10"
}
PATTERN
}
resource "aws_cloudwatch_event_target" "lambda-stop" {
rule = "${aws_cloudwatch_event_rule.stop.name}"
target_id = "lambda"
arn = "${aws_lambda_function.lambda_test.arn}"
}
resource "aws_lambda_permission" "lamda-permision" {
statement_id = "AllowExecutionbycloudwatchrule"
action = "lambda:InvokeFunction"
function_name = "${aws_lambda_function.lambda_test.function_name}"
principal = "events.amazonaws.com"
source_arn = "${aws_cloudwatch_event_rule.stop.arn}"
}
#_______end of stop instances at 10pm_________________
See this website for a handy Cron calculator.
To stop the instance, we have set the MinSize and DesiredSize to 0. So I passed min, desired value as 0 to my lambda function as Jason format below.
event_pattern = <<PATTERN
{
"aws_region" : "eu-west-1",
"asg_name" : "webapp",
"min" : "0",
"desired" : "0",
"max" : "10"
}
PATTERN
Now, the stop rule has been created. resource "aws_cloudwatch_event_target" "lambda-stop".. used to select a target to invoke when an event matches. (literally trigger the lambda function on cloud watch rule event).To Sart the autoscaling EC2 Instance
# /scale-up-daown-lamda.tf
#...
#_______start instances at 7am everyday_________________
resource "aws_cloudwatch_event_rule" "start" {
name = "everyday-7am"
description = "start instances everyday 7am"
schedule_expression = "0 0 7 1/1 * ? *"
event_pattern = <<PATTERN
{
"aws_region" : "eu-west-1",
"asg_name" : "webapp",
"min" : "2",
"desired" : "5",
"max" : "10"
}
PATTERN
}
resource "aws_cloudwatch_event_target" "lambda-start" {
rule = "${aws_cloudwatch_event_rule.start.name}"
target_id = "lambda1"
arn = "${aws_lambda_function.lambda_test.arn}"
}
resource "aws_lambda_permission" "lamda-permision" {
statement_id = "AllowExecutionbycloudwatchrule"
action = "lambda:InvokeFunction"
function_name = "${aws_lambda_function.lambda_test.function_name}"
principal = "events.amazonaws.com"
source_arn = "${aws_cloudwatch_event_rule.start.arn}"
}
And MinSize and DesiredSize have given as we configured autoscaling from the beginning. Meaning that it brings back the EC2 instances as Exactly we created the autoscaling group earlier at launch first launch.
#luanch instance as we configured autoscaling from the begining
event_pattern = <<PATTERN
{
"aws_region" : "eu-west-1",
"asg_name" : "webapp",
"min" : "2",
"desired" : "5",
"max" : "10"
}
PATTERN
Now we can easily we can stop our EC2 instances at night to save money on our cloud bill and automate this process using lambda. To make sure your autoscaling is done properly, we should monitor the EC2 instance with Cloudwatch.
Find the full repo here
That's pretty much it guys! Thank you
No comments:
Post a Comment