ECSのCPU使用率が閾値を超えた時にCloudWatchアラームでメール通知する

ECSのCPU使用率が閾値を超えた時に、CloudWatchアラームでメール通知する

ECS(Fargate)のCPU使用率が閾値を超えた時に、CloudWatchアラームからSNSでメール通知する

FargateタイプのECSを作成すると、デフォルトでCPUとメモリ使用率がCloudWatchメトリクスに配信されます。
今回はCloudWatchアラームを使って、CPU使用率に閾値を設定し、上限を超えた時にメールで通知することを目指します。

構築する環境

Diagram of Email notification via CloudWatch Alarm when ECS CPU usage exceeds threshold.

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

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

CloudWatchアラームで、CPU使用率に関する閾値を設定します。
使用率が0.1%を超えた時に、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/070

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

ECS(Fargate)に関する基本的な事項は、以下のページをご確認ください。

あわせて読みたい
CloudFormationでFargate入門 【CloudFormationでFargateに入門するための構成】 AWS FargateはサーバーレスでDockerコンテナを実行することができるサービスです。今回はFargate入門ということで、C...

プライベートサブネットにFargateを配置する方法については、以下のページをご確認ください。

あわせて読みたい
プライベートサブネットにECS(Fargate)を作成する 【プライベートサブネットにECS(Fargate)を作成する】 以下のページでFargateタイプのECSコンテナを作成する方法をご紹介しました。 https://awstut.com/2022/01/25/int...

CloudFormationカスタムリソースを使用して、NATゲートウェイ等を自動的に削除する方法については、以下のページをご確認ください。

あわせて読みたい
初期構築の時だけ使用するNATゲートウェイをCFNカスタムリソースで削除する 【初期構築の時だけ使用するリソース(NATゲートウェイ)をCFNカスタムリソースで削除する】 例えばECSを作成する際に、Dockerhubからイメージをプルする場合、インターネ...

SNSトピック

Resources:
  Topic:
    Type: AWS::SNS::Topic
    Properties:
      Subscription:
        - Endpoint: !Ref MailAddress
          Protocol: email
      TopicName: !Ref Prefix
Code language: YAML (yaml)

Subscriptionプロパティがポイントです。
サブスクライバーとしてメールアドレスを指定する場合は、Protocolプロパティに「email」を、Endpointプロパティにメールアドレスを指定します。

メールアドレスをSNSサブスクライバーに指定する方法については、以下のページをご確認ください。

あわせて読みたい
CFNでSNS入門 – email版 【CFNでSNS入門 - email版】 AWS SNSはメッセージングサービスです。 今回は入門編ということで、通知先にEmailを指定する方法をご紹介します。 【構築する環境】 2種類...

VPCエンドポイント

Resources:
  CloudWatchMetricsEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      PrivateDnsEnabled: true
      SecurityGroupIds:
        - !Ref EndpointSecurityGroup2
      ServiceName: !Sub "com.amazonaws.${AWS::Region}.monitoring"
      SubnetIds:
        - !Ref ContainerSubnet
      VpcEndpointType: Interface
      VpcId: !Ref VPC
Code language: YAML (yaml)

プライベートサブネットに配置されたFargateのメトリクスをCloudWatchに配信するためには、メトリクス用VPCエンドポイントを作成します。

以下が本エンドポイントに適用するセキュリティグループです。

Resources:
  EndpointSecurityGroup2:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: !Sub "${Prefix}-EndpointSecurityGroup2"
      GroupDescription: Allow HTTPS from ContainerSecurityGroup.
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: !Ref HTTPSPort
          ToPort: !Ref HTTPSPort
          SourceSecurityGroupId: !Ref ContainerSecurityGroup
Code language: YAML (yaml)

Fargateに適用したセキュリティグループを送信元として、443/tcpのインバウンド通信を許可する内容です。

CloudWatchアラーム

Resources:
  Alarm:
    Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmActions:
        - !Ref TopicArn
      ComparisonOperator: GreaterThanThreshold
      Dimensions:
        - Name: ClusterName
          Value: !Ref ClusterName
        - Name: ServiceName
          Value: !Ref ServiceName
      EvaluationPeriods: 1
      MetricName: CPUUtilization
      Namespace: AWS/ECS
      Period: 60
      Statistic: Average
      Threshold: 0.1
Code language: YAML (yaml)

AlarmActionsプロパティで、アラーム条件を満たした時に実行するアクションを設定します。
先述のSNSトピックを指定し、SNSのパブリッシャーに登録します。

Namespaceプロパティで、メトリクスを収集する対象サービスを設定します。
ECS/Fargateのメトリクスを収集する場合は、「AWS/ECS」を指定します。

MetricNameプロパティで収集するメトリクスを設定します。
CPU使用率を収集したいので、「CPUUtilization」を指定します。

Dimensionsプロパティで、対象のECS/Fargateリソースを特定するための特徴を指定します。
ECS/Fargateの場合、2つの特徴を設定できます。

  • ClusterName:ECSクラスターの名前
  • ServiceName:ECSサービスの名前

ComparisonOperator、EvaluationPeriods、Period、Statistic、Thresholdプロパティでアラーム条件を設定します。
これらをまとめますと、60秒ごとにCPU使用率を評価し、過去1回分のメトリクスの平均値が0.1%を超えた場合は、アラーム条件を満たすということになります。

(参考)EC2インスタンス

Resources:
  Instance:
    Type: AWS::EC2::Instance
    Properties:
      IamInstanceProfile: !Ref InstanceProfile
      ImageId: !Ref ImageId
      InstanceType: !Ref InstanceType
      NetworkInterfaces:
        - DeviceIndex: 0
          SubnetId: !Ref InstanceSubnet
          GroupSet:
            - !Ref InstanceSecurityGroup
      UserData: !Base64 |
        #!/bin/bash -xe
        yum update -y
        yum install httpd -y
Code language: YAML (yaml)

特別な設定は不要です。
UserDataプロパティで、インスタンスの初期化時にApacheをインストールするように記載します。

ユーザーデータに関する詳細につきましては、以下のページをご確認ください。

あわせて読みたい
Linuxインスタンスの初期化方法4選 【Linuxインスタンスを初期化する4つの方法】 EC2インスタンスの起動時に初期化処理を実行する方法を考えます。 EC2インスタンスを構築時に初期化する以下の4つの手法を...

環境構築

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

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

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

あわせて読みたい
CloudFormationのネストされたスタックで環境を構築する 【CloudFormationのネストされたスタックで環境を構築する方法】 CloudFormationにおけるネストされたスタックを検証します。 CloudFormationでは、スタックをネストす...

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

  • SNSトピック:fa-070
  • ECSクラスター:fa-070-cluster
  • ECSサービス:fa-070-service
  • EC2インスタンス:i-02da326aa09a0a86c

メールアドレスの認証

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

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

あわせて読みたい
CFNでSNS入門 – email版 【CFNでSNS入門 - email版】 AWS SNSはメッセージングサービスです。 今回は入門編ということで、通知先にEmailを指定する方法をご紹介します。 【構築する環境】 2種類...

リソース確認

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

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

Detail of SNS.

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

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

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

Detail of ECS 1.
Detail of ECS 2.

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

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

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

アラームが正常に作成されています。
ディメンジョン情報に基づいて、先ほど確認したFargateのCPU使用率が収集できています。
現在は閾値である0.1%未満であるため、状態は「OK」であり、アラーム状態にはなっていません。

動作確認

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

% aws ssm start-session --target i-02da326aa09a0a86c

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

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

あわせて読みたい
LinuxインスタンスにSSM Session Manager経由でアクセスする 【LinuxインスタンスにSSM Session Manager経由でアクセスする】 EC2インスタンスにSSM Session Manager経由でアクセスする構成を確認します。 Session Manager は完全...

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

sh-4.2$ curl http://10.0.3.221/
<!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.221/
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.221 (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.221
Server Port:            80

Document Path:          /
Document Length:        615 bytes

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

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

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

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

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

Detail of CloudWatch Alarm 3.
Detail of CloudWatch Alarm 4.

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

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

Email from SNS.

メールの本文は、CloudWatchアラームの内容となっています。
このようにCloudWatchアラームを使用することによって、特定のメトリクスが閾値を超えた時に、SNSと連携してメールで通知することができました。

まとめ

CloudWatchアラームを使って、Fargateのメトリクスに閾値を設定し、上限を超えた時にメールで通知する方法を確認しました。