AWS

CloudWatch Metric MathでFargateコンテナのCPUアイドルタイムを計測する

CloudWatch Metric MathでFargateコンテナのCPUアイドルタイムを計測する

以下のページで、FargateコンテナのCPU使用率を測定し、閾値を上回った時にメール通知する方法をご紹介しました。

今回はMetric Mathを使用して、上記のCPU使用率から新しいデータを生成します。

Metric Math により複数の CloudWatch メトリクスをクエリし、数式を使用して、これらのメトリクスに基づく新しい時系列を作成できます。

Metric Math を使用する

今回はCPU使用率からCPUのアイドルタイムを計算し、閾値を下回った時にメール通知することを目指します。

構築する環境

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

プライベートサブネットに、FargateタイプのECSを作成します。

プライベートサブネットからCloudWatchにメトリクスを配信するために、コンテナ用サブネットに、メトリクス用VPCエンドポイントを作成します。

CloudWatchアラームで、FargateのCPUアイドルタイムに関する閾値を設定します。
アイドルタイムはMetric Mathの数式表現で計算して求めます。
アイドルタイムが98%を下回った時に、SNSにメッセージをパブリッシュするように設定します。

SNSはメールアドレスにサブスクライバーとして設定します。

EC2インスタンスを作成します。
コンテナにアクセスするためのクライアントして使用します。

2つの目的で、NATゲートウェイを作成します。
1つ目はECSコンテナを作成するために、DockerHubからNginxの公式イメージを取得するためです。
2つ目はEC2インスタンスにApache Benchをインストールするためです。Apache BenchはECSコンテナに対して実行し、大量のリクエストを生成することで、CPU使用率を高めてアラームを発生させます。

上記の用途での使用が済めば、NATゲートウェイは不要となります。
今回はCloudFormationカスタムリソースを使用して、最終的にNATゲートウェイ等を削除するように設定します。

CloudFormationテンプレートファイル

上記の構成をCloudFormationで構築します。
以下のURLにCloudFormationテンプレートを配置しています。

https://github.com/awstut-an-r/awstut-fa/tree/main/073

テンプレートファイルのポイント解説

基本的な構成は冒頭でご紹介したページと同様です。
本ページでは、Metric Mathに関する記述を中心に取り上げます。

CloudWatch Metric Math

Resources:
  Alarm:
    Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmActions:
        - !Ref TopicArn
      ComparisonOperator: LessThanThreshold
      EvaluationPeriods: 1
      Metrics:
        - Expression: 100 - m1
          Id: it1
          Label: cluster_idol_time
          ReturnData: true
        - Id: m1
          Label: cluster_cpu_utilization
          MetricStat:
            Metric:
              MetricName: CPUUtilization
              Dimensions:
                - 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はCloudWatchアラームの設定の1つとして定義します。

Metricsプロパティ内でMetric Math設定を行います。
2つのメトリックを設定します。

1つ目はCPUアイドルタイムとなるメトリックです。
Expressionプロパティで計算式を定義します。
アイドルタイムを計算するために、1から後述のメトリックであるCPU使用率を引き算するように定義します。
数式表現を定義したメトリックの場合、ReturnDataプロパティに「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

2つ目はCPU使用率を意味するメトリックです。
MetricStatプロパティで、FargateのCPU使用率に関するメトリック(CPUUtilization)を指定します。
記法は同メトリックに対してアラームを設定する際と概ね同様です。
こちらのReturnDataプロパティは「false」を設定します。

環境構築

CloudFormationを使用して、本環境を構築し、実際の挙動を確認します。

CloudFormationスタックを作成し、スタック内のリソースを確認する

CloudFormationスタックを作成します。
スタックの作成および各スタックの確認方法については、以下のページをご確認ください。

各スタックのリソースを確認した結果、今回作成された主要リソースの情報は以下の通りです。

  • SNSトピック:fa-073
  • ECSクラスター:fa-073-cluster
  • ECSサービス:fa-073-service
  • EC2インスタンス:i-0b8bfd98d1ecb5a30

メールアドレスの認証

SNSトピックのサブスクライバーとしてメールアドレスを指定した場合、そのメールアドレスを認証する必要があります。

詳細につきましては、以下のページをご確認ください。

リソース確認

AWS Management Consoleから各リソースを確認します。

SNSトピックを確認します。

Detail of SNS 1.

正常にSNSトピックが作成されていることがわかります。

加えて、サブスクライバーとして登録したメールアドレスが登録されていることもわかります。
またこのメールアドレスのStatusの値を見ると「Confirmed」とあり、認証が完了していることもわかります。

続いてECS(Fargate)を確認します。

Detail of Fargate 1.
Detail of Fargate 2.

正常にECSクラスター・サービス・タスクが作成されています。
Dockerhubから最新版のNginxのイメージを取得し、そこからコンテナが作成されています。
タスクに割り当てられているプライベートアドレスが「10.0.3.123」ということもわかります。

CloudWatchアラームを確認します。

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

アラームが正常に作成されています。
グラフを見ると、CPU使用率からアイドルタイムが計算されていることがわかります。
現在はほぼ100%がアイドルタイムです。
ですから閾値である98%以上であるため、状態は「OK」であり、アラーム状態にはなっていません。

ちなみに以下が元々のCPU使用率です。

Detail of CloudWatch Alarm 3.

起動直後は若干高まりましたが、以降は使用率が0%であることがわかります。
このことからも正確にアイドルタイムが計算されていることがわかります。

動作確認

準備が整いましたので、EC2インスタンスにアクセスします。
インスタンスへのアクセスはSSM Session Managerを使用します。

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

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

SSM Session Managerの詳細につきましては、以下のページをご確認ください。

curlコマンドを使って、タスク内のコンテナにアクセスします。

sh-4.2$ curl http://10.0.3.123
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<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="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

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

正常にアクセスできました。
Fargate上でNginxコンテナが動作していることがわかります。

これからFargateのCPU使用率を上昇させて、CloudWatchアラームにアクションを起こさせます。
CPU使用率を高めるために、Apache Benchを使用して、大量のリクエストを生成して負荷をかけます。

まずApacheがインストールされている確認します。

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がインストールされたようです。

Apache Benchを実行します。
Fargate上のコンテナ(タスク)に対して、10万回のリクエストを生成します。

sh-4.2$ ab -n 100000 http://10.0.3.123/
This is ApacheBench, Version 2.3 <$Revision: 1901567 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 10.0.3.123 (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:        10.0.3.123
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)

Apache Benchによる負荷によって、CPU使用率が高まったはずです。

改めてCloudWatchアラームを確認します。

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

CPUアイドルタイムが98%を下回りました。
アラーム発生の閾値を超えましたので、状態が「OK」から「In alarm」に変更になりました。
履歴を見ると、アラーム状態になったことによって、Actionとして、SNSにメッセージを送信したことがわかります。

すぐさま登録したアドレスに、以下のメールが届きました。

Detail of SNS 2.

メールの本文は、CloudWatchアラームの内容となっています。
このようにCloudWatch Metric Mathを使用することによって、あるメトリックから新たなデータを生成し、閾値を超えた時に、SNSと連携してメールで通知することができました。

まとめ

CPU使用率からCPUのアイドルタイムを計算し、閾値を下回った時にメール通知する方法を確認しました。

タイトルとURLをコピーしました