ECS(Fargate)のCPU使用率が閾値を超えた時に、CloudWatchアラームからSNSでメール通知する
FargateタイプのECSを作成すると、デフォルトでCPUとメモリ使用率がCloudWatchメトリクスに配信されます。
今回はCloudWatchアラームを使って、CPU使用率に閾値を設定し、上限を超えた時にメールで通知することを目指します。
構築する環境
プライベートサブネットに、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)に関する基本的な事項は、以下のページをご確認ください。
プライベートサブネットにFargateを配置する方法については、以下のページをご確認ください。
CloudFormationカスタムリソースを使用して、NATゲートウェイ等を自動的に削除する方法については、以下のページをご確認ください。
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サブスクライバーに指定する方法については、以下のページをご確認ください。
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をインストールするように記載します。
ユーザーデータに関する詳細につきましては、以下のページをご確認ください。
環境構築
CloudFormationを使用して、本環境を構築し、実際の挙動を確認します。
CloudFormationスタックを作成し、スタック内のリソースを確認する
CloudFormationスタックを作成します。
スタックの作成および各スタックの確認方法については、以下のページをご確認ください。
各スタックのリソースを確認した結果、今回作成された主要リソースの情報は以下の通りです。
- SNSトピック:fa-070
- ECSクラスター:fa-070-cluster
- ECSサービス:fa-070-service
- EC2インスタンス:i-02da326aa09a0a86c
メールアドレスの認証
SNSトピックのサブスクライバーとしてメールアドレスを指定した場合、そのメールアドレスを認証する必要があります。
詳細につきましては、以下のページをご確認ください。
リソース確認
AWS Management Consoleから各リソースを確認します。
SNSトピックを確認します。
正常にSNSトピックが作成されていることがわかります。
加えて、サブスクライバーとして登録したメールアドレスが登録されていることもわかります。
またこのメールアドレスのStatusの値を見ると「Confirmed」とあり、認証が完了していることもわかります。
続いてECS(Fargate)を確認します。
正常にECSクラスター・サービス・タスクが作成されています。
Dockerhubから最新版のNginxのイメージを取得し、そこからコンテナが作成されています。
タスクに割り当てられているプライベートアドレスが「10.0.3.221」ということもわかります。
CloudWatchアラームを確認します。
アラームが正常に作成されています。
ディメンジョン情報に基づいて、先ほど確認した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の詳細につきましては、以下のページをご確認ください。
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アラームを確認します。
CPU使用率が8%を超えました。
アラーム発生の閾値を超えましたので、状態が「OK」から「In alarm」に変更になりました。
履歴を見ると、アラーム状態になったことによって、Actionとして、SNSにメッセージを送信したことがわかります。
すぐさま登録したアドレスに、以下のメールが届きました。
メールの本文は、CloudWatchアラームの内容となっています。
このようにCloudWatchアラームを使用することによって、特定のメトリクスが閾値を超えた時に、SNSと連携してメールで通知することができました。
まとめ
CloudWatchアラームを使って、Fargateのメトリクスに閾値を設定し、上限を超えた時にメールで通知する方法を確認しました。