Per AWS documentation they say: "Fargate supports scheduling tasks in response to CloudWatch Events. You can easily launch and stop Fargate tasks that you only need to run at certain times"
Start of Fargate Tasks can easily be enabled from CloudWatch Events or ECS Task Scheduler.
But STOP of Fargate Tasks I cannot find. Is it possible that need to use Lambda and not native Fargate feature to stop tasks?
My goal is to run ECS Container between 8ap-5pm Only!
answer by @Francesco Grotta is right. By we can create the following resources, to trigger this action on schedule:
DesiredCount
.Lambda Function that will start or stop the ECS service based on the input from CloudWatch Events:
if(event.status == 'stop'){
var params = {
cluster: process.env.ECS_CLUSTER,
service: process.env.ECS_SERVICE_NAME,
desiredCount: 0
};
}
else{
var params = {
cluster: process.env.ECS_CLUSTER,
service: process.env.ECS_SERVICE_NAME,
desiredCount: 1
};
}
var ecs = new AWS.ECS();
ecs.updateService(params, function (err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
});
In Cloudformation template, create resources that will invoke the Lambda Function on a schedule:
StartEcsLambdaSchedule:
Type: AWS::Events::Rule
Properties:
Description: >
A schedule for the Lambda function to start ECS service during office hours.
ScheduleExpression: !Ref StartEcsLambdaScheduleExpression
State: ENABLED
Targets:
- Arn: !Sub ${EcsTaskScheduleLambdaFunction.Arn}
Id: StartEcsLambdaScheduleV1
Input: '{"status": "start"}'
StopEcsLambdaSchedule:
Type: AWS::Events::Rule
Properties:
Description: >
A schedule for the Lambda function to stop ECS service after office hours.
ScheduleExpression: !Ref StopEcsLambdaScheduleExpression
State: ENABLED
Targets:
- Arn: !Sub ${EcsTaskScheduleLambdaFunction.Arn}
Id: StopEcsLambdaScheduleV1
Input: '{"status": "stop"}'
I've taken the code @Mr3381 proposed and made some improvements:
interface EventLambda {
status: string,
services: string[]
}
interface UpdateServiceParams {
cluster: string
service: string
desiredCount: number
}
// Load AWS SDK for Node.js
import AWS from 'aws-sdk';
export const handler = async (event: EventLambda): Promise<string[]> => {
const ecs = new AWS.ECS({region: 'sa-east-1'});
const promises = new Array<Promise<any>>();
const desiredCount = event.status == 'start' ? 1 : 0
event.services.forEach(service => {
var params: UpdateServiceParams = {
cluster: process.env.ECS_CLUSTER!,
service,
desiredCount
};
promises.push(updateService(ecs, params, desiredCount))
}
)
return Promise.all(promises)
};
function updateService(ecs: AWS.ECS, params: UpdateServiceParams, desiredCount: number): Promise<string> {
return new Promise((resolve, reject) => {
ecs.updateService(params, function(err, data) {
if (err) {
console.log(err, err.stack); // An error occurred
resolve(`${params.service} not updated`);
}
else {
console.log(data); // Successful response
resolve(`${params.service} updated => Desired count: ${desiredCount}`)
}
});
})
}
It's now in TypeScript and supports an array of services as an input.
There's only the need to transpile it to JavaScript to be able to run on AWS.
Make sure to have the required permissions to execute the function and update your services. This can be achieved by attaching the policies describeServices and updateServices from ECS to your Lambda function IAM Role.
I believe this is the best solution for your office hours problem.
Just schedule a local cron job in the EC2 instance with the below command to update desired count according the timestamp and you are good to go.
$ aws ecs update-service --cluster <cluster-name> --service <service-name> --desired-count x
Do let me know in case this helped you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With