Using AWS Lambda Function for AutoScaling of ECS Containers
AWS Lambda is an event-driven compute service using which you can perform actions by executing some set of code on any event. We are using a lambda function to trigger AWS ECS container auto-scaling that is executed on the SNS event.
Below is the AWS Lambda code in node.js that will get Cluster Name, Service Name & Operator from the SNS JSON format and then on the basis of the operator, it will decide whether it needs to increase or decrease the container count. It has a max & min limit too for the container.
Below is how we use AWS Lambda function: (I have divided the whole process into smaller chunks for better understanding)
SNS Notification passes a JSON input that we get in event object and retrieve all inputs (ServiceName, ClusterName, ComparisonOperator) from that JSON input.
[js]’use strict’;
console.log(‘Loading function’);
var aws = require(‘aws-sdk’);
exports.handler = (event, context, callback) {
var message = event.Records[0].Sns.Message;
var ecsService = JSON.parse(message).Trigger.Dimensions[1].value;
var ecsCluster = JSON.parse(message).Trigger.Dimensions[0].value;
var comparisonOperator = JSON.parse(message).Trigger.ComparisonOperator;
console.log("Comparison Operator= ", comparisonOperator)
var ecsRegion = ‘ap-southeast-1’;
console.log("ECSService=", ecsService )
console.log("ECSCluster=", ecsCluster )[/js]
Here we are setting Max & Min limit for container autoscaling (Note that the container number always have to be under this limit). Just add your set of variables in the following block in your function. In case it reaches max or min limit while autoscaling the containers, just print a message in logs and exit:
[js]
var maxCount = 6;
var minCount = 2;
[/js]
Here, we create the ECS object and get the current count of containers of that service:
[js]
var ecs = new aws.ECS({region: ecsRegion});
ecs.describeServices({services:[ecsService],cluster: ecsCluster}, function(err, data) {
if (err) {
console.log(err, err.stack);
}
else {
var desiredCount = data.services[0].desiredCount;
console.log("desiredCount=", desiredCount )
[/js]
Check if comparison operator is GreaterThanOrEqualToThreshold and the desired count is less than Max, increase the count and update service and same for downscale:
[js]
if(comparisonOperator == "GreaterThanOrEqualToThreshold"){
if (desiredCount < maxCount) {
desiredCount++;
}
else {
console.log(‘Service count is already max.’);
context.succeed();
}
}
else if (comparisonOperator == "LessThanOrEqualToThreshold") {
if (desiredCount > minCount) {
desiredCount–;
}
else {
console.log(‘Service count is already min.’);
context.succeed();
}
}
else {
console.log("Unknown comparison operator");
context.fail();
}
}
var params = {
service: ecsService,
desiredCount: desiredCount,
cluster: ecsCluster
};
ecs.updateService(params, function(err, data) {
if (err) {
console.log(err, err.stack);
}
else {
console.log(data);
context.succeed();
}
});
};[/js]
This is how AWS Lambda can trigger an event on high/low CPU/Memory utilization of any service through SNS Notification.
PS: Please be careful about the indentation while using the above function.