How to schedule ECS Services in AWS easily (start/stop)
Federico Navarrete

Federico Navarrete @fanmixco

About: 👨‍💻 Technovator, ✍️ Author and 🎤 Speaker

Location:
Luxembourg
Joined:
Jul 5, 2019

How to schedule ECS Services in AWS easily (start/stop)

Publish Date: Jul 28 '21
10 3

This is my solution which is highly based on a great AWS employee (Alfredo J).

Most likely if you are reading this article, you might know this is not something possible to do without a workaround in AWS. You might think of using a scheduled task or complex solutions but after a while, Alfredo from Mexico supported me to bring this solution to all of you.

First, create a Policy using the JSON option with the following config.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "logs:*"
            ],
            "Resource": "arn:aws:logs:*:*:*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "ecs:DescribeServices",
                "ecs:UpdateService"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}
Enter fullscreen mode Exit fullscreen mode

It can be called servicesscheduler.

After the policy is created, you need to create an IAM role using the new policy (servicesscheduler). It can be called ECSScheduler.

Next, you need to create a Lambda function that runs using the new IAM role ECSScheduler. After the function is created, add this Python (3.8) script:

import json
import boto3
import logging

logger = logging.getLogger()
logger.setLevel(logging.INFO)

client = boto3.client('ecs')

def lambda_handler(event, context):
    cluster = event["cluster"]
    service_names = event["service_names"]
    service_desired_count = int(event["service_desired_count"])

    for service_name in service_names.split(","):
        response = client.update_service(
            cluster=cluster,
            service=service_name,
            desiredCount=service_desired_count
            )

        logger.info("Updated {0} service in {1} cluster with desire count set to {2} tasks".format(service_name, cluster, service_desired_count))

    return {
        'statusCode': 200,
        'new_desired_count': service_desired_count
    }

The script expects the following variables in a JSON format:

{
  "cluster": "clusterName",
  "service_names": "service1,service2",
  "service_desired_count": "0"
}
Enter fullscreen mode Exit fullscreen mode

Where:

  • cluster is the name of the cluster you want to modify.
  • service_names is an array for the collection of services.
  • service_desired_count is the number of desired services. 0 is to stop the service/s, any other number is to start the service/s.

After everything is created you need to create some rules in Amazon EventBridge (formerly, CloudWatch Events). Here, you define the event you want to trigger based on the schedule that you expect. This is an example:

aws example

If something fails, you need to double-check that the created IAM role has the required policies like ecs:UpdateService. You can check this from the logs.

Can there be any variations using tags to make it more efficient? Yes, it's possible. I wrote a different version in my blog focused on this alternative approach.

Follow me on:

Personal LinkedIn YouTube Instagram Cyber Prophets Sharing Your Stories
Personal LinkedIn YouTube Instagram RedCircle Podcast RedCircle Podcast

sponsor me

Comments 3 total

  • Andriy Pyshchyk
    Andriy PyshchykJun 6, 2022

    Hi, great article. Used to do the same, end up creating tool for doing it across multiple accounts. Would be awesome if I can get your feedback about it

  • Dariusz
    DariuszMar 21, 2023

    Looks like now EventBridge can directly change desired tasks, so no need to write lambda anymore ?

    • rulo4
      rulo4Sep 7, 2023

      Do you know how? Could you please provide an example?
      Not able to find it so far.

Add comment