Measure CPU idle time for Fargate container using CloudWatch Metric Math

Measure CPU idle time for Fargate container using CloudWatch Metric Math

The following page shows how to measure the CPU usage of Fargate containers and notify by email when the threshold is exceeded.

This time we will use Metric Math to generate new data from the above CPU utilization.

Metric math enables you to query multiple CloudWatch metrics and use math expressions to create new time series based on these metrics.

Using metric math

In this case, we aim to calculate CPU idle time based on CPU usage and email notifications when it falls below a threshold value.


Diagram of mesure CPU idle time of Fargate container using CloudFormation Metric Math

Create a Fargate type ECS on a private subnet.

Create a VPC endpoint for metrics in the container subnet to deliver metrics from the private subnet to CloudWatch.

In CloudWatch alarms, set thresholds for Fargate’s CPU idle time.
The idle time is calculated using the Metric Math formula expression.
Set a message to be published to SNS when idle time falls below 98%.

Set the SNS as a subscriber to the email address.

Create an EC2 instance.
Use it as a client to access the container.

Create a NAT gateway for two purposes.
The first is to get an official Nginx image from DockerHub in order to create an ECS container.
The second is to install Apache Bench on the EC2 instance, which will run against the ECS container and generate a large number of requests, which will increase CPU usage and raise alarms.

Once the above uses are completed, the NAT gateway is no longer needed.
In this case, we will use a CloudFormation custom resource and configure it to eventually remove the NAT gateway, etc.

CloudFormation template files

The above configuration is built using CloudFormation.
The CloudFormation template is located at the following URL

awstut-fa/073 at main · awstut-an-r/awstut-fa
Contribute to awstut-an-r/awstut-fa development by creating an account on GitHub.

Explanation of key points of the template files

The basic configuration is the same as the page introduced at the beginning of this document.
This page focuses on the description of Metric Math.

CloudWatch Metric Math

    Type: AWS::CloudWatch::Alarm
        - !Ref TopicArn
      ComparisonOperator: LessThanThreshold
      EvaluationPeriods: 1
        - Expression: 100 - m1
          Id: it1
          Label: cluster_idol_time
          ReturnData: true
        - Id: m1
          Label: cluster_cpu_utilization
              MetricName: CPUUtilization
                - Name: ClusterName
                  Value: !Ref ClusterName
                - Name: ServiceName
                  Value: !Ref ServiceName
              Namespace: AWS/ECS
            Period: 60
            Stat: Average
            Unit: Percent
          ReturnData: false
      Threshold: 98
Code language: YAML (yaml)

Metric Math is defined as one of the CloudWatch alarm settings.

Metric Math setting in the Metrics property.
Two metrics are configured.

The first metric is the CPU idle time.
Define a formula in the Expression property.
To calculate the idle time, define it as 1 minus the CPU utilization, which is the metric described below.
For a metric that defines a formula expression, set the ReturnData property to “true”.

When you create an alarm based on a metric math expression, specify True for this value for only the one math expression that the alarm is based on. You must specify False for ReturnData for all the other metrics and expressions used in the alarm.

AWS::CloudWatch::Alarm MetricDataQuery

The second is a metric that refers to CPU usage.
The MetricStat property specifies a metric (CPUUtilization) for Fargate’s CPU utilization.
The notation is similar to that used when setting alarms for the same metric.
The ReturnData property should be set to “false”.


Using CloudFormation, build this environment and check the actual behavior.

Create a CloudFormation stacks and check resources in stacks

Create a CloudFormation stack.
For information on how to create stacks and check each stack, please refer to the following page

After checking the resources in each stack, information on the main resources created this time is as follows

  • SNS topic: fa-073
  • ECS cluster: fa-073-cluster
  • ECS service: fa-073-service
  • EC2 instance: i-0b8bfd98d1ecb5a30

Authentication of email address

If you specify an email address as a subscriber to an SNS topic, you must authenticate that email address.

For more information, please refer to the following page

Resource Confirmation

Check each resource from the AWS Management Console.

Check the SNS topic.

Detail of SNS 1.

You can see that the SNS topic has been successfully created.

In addition, you can see that the email address registered as a subscriber is registered.
The Status value of the email address is “Confirmed,” indicating that the authentication has been completed.

Next, check ECS (Fargate).

Detail of Fargate 1.
Detail of Fargate 2.

The ECS cluster service task has been successfully created.
The latest version of Nginx image is obtained from Dockerhub and a container is created from it.
You can also see that the private address assigned to the task is “”.

Check the CloudWatch alarm.

Detail of CloudWatch Alarm 1.
Detail of CloudWatch Alarm 2.

The alarm has been successfully created.
The graph shows that idle time is calculated from CPU usage.
Currently, almost 100% of the time is idle time.
Therefore, since it is above the threshold value of 98%, the status is “OK” and not in an alarm state.

By the way, the following is the original CPU utilization.

Detail of CloudWatch Alarm 3.

It was slightly increased immediately after startup, but after that, we can see that the utilization is 0%.
This shows that idle time is calculated accurately.

Checking Action

Now that everything is ready, access the EC2 instance.
Use SSM Session Manager to access the instance.

% aws ssm start-session --target i-0b8bfd98d1ecb5a30

Starting session with SessionId: root-0dc7b12a7aabc453b
Code language: Bash (bash)

For more information on SSM Session Manager, please refer to the following page

Access the container in the task using the curl command.

sh-4.2$ curl
<!DOCTYPE html>
<title>Welcome to nginx!</title>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href=""></a>.<br/>
Commercial support is available at
<a href=""></a>.</p>

<p><em>Thank you for using nginx.</em></p>
Code language: Bash (bash)

I was able to access the site successfully.
We can see that the Nginx container is in action on Fargate.

We will now increase Fargate’s CPU utilization to trigger an action on the CloudWatch alarm.
To increase CPU utilization, we will use Apache Bench to generate and load a large number of requests.

First make sure Apache is installed.

sh-4.2$ sudo yum list installed | grep httpd
generic-logos-httpd.noarch            18.0.0-4.amzn2                 @amzn2-core
httpd.aarch64                         2.4.54-1.amzn2                 @amzn2-core
httpd-filesystem.noarch               2.4.54-1.amzn2                 @amzn2-core
httpd-tools.aarch64                   2.4.54-1.amzn2                 @amzn2-core
Code language: Bash (bash)

Apache appears to have been successfully installed by the user data.

Run Apache Bench.
Generate 100,000 requests for a container (task) on Fargate.

sh-4.2$ ab -n 100000
This is ApacheBench, Version 2.3 <$Revision: 1901567 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd,
Licensed to The Apache Software Foundation,

Benchmarking (be patient)
Completed 10000 requests
Completed 20000 requests
Completed 30000 requests
Completed 40000 requests
Completed 50000 requests
Completed 60000 requests
Completed 70000 requests
Completed 80000 requests
Completed 90000 requests
Completed 100000 requests
Finished 100000 requests

Server Software:        nginx/1.23.1
Server Hostname:
Server Port:            80

Document Path:          /
Document Length:        615 bytes

Concurrency Level:      1
Time taken for tests:   35.679 seconds
Complete requests:      100000
Failed requests:        0
Total transferred:      84800000 bytes
HTML transferred:       61500000 bytes
Requests per second:    2802.78 [#/sec] (mean)
Time per request:       0.357 [ms] (mean)
Time per request:       0.357 [ms] (mean, across all concurrent requests)
Transfer rate:          2321.05 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.1      0       7
Processing:     0    0   0.1      0       7
Waiting:        0    0   0.1      0       7
Total:          0    0   0.1      0       8

Percentage of the requests served within a certain time (ms)
  50%      0
  66%      0
  75%      0
  80%      0
  90%      0
  95%      1
  98%      1
  99%      1
 100%      8 (longest request)
Code language: Bash (bash)

The CPU utilization should have increased due to the load from the Apache Bench.

Check the CloudWatch alarm again.

Detail of CloudWatch Alarm 4.
Detail of CloudWatch Alarm 5.

CPU idle time is below 98%.
The alarm threshold has been exceeded, so the status changes from “OK” to “In alarm”.
The history shows that a message was sent to the SNS as an Action due to the alarm status.

The following email was immediately sent to the registered address.

Detail of SNS 2.

The body of the email is the contents of the CloudWatch alarm.
In this way, by using CloudWatch Metric Math, we were able to generate new data from a metric, and when the threshold value was exceeded, we were able to notify via email in conjunction with the SNS.


We have confirmed how to calculate CPU idle time from CPU usage and notify via email when it falls below the threshold value.