皆様、お世話になっております。鈴木と申します。
今回はAWS CloudFormationを使用して、EC2のCloudWatchアラームを設定し、SNS通知を行う構成を作成します。
1.目次
2.要件
- EC2のメモリ・ディスク・CPU使用率を監視して80%と90%にしきい値を設定。
超えた場合にSNSでアラート通知を行う。 - Apacheのエラーログを収集してエラーログの検出時にSNS通知するように設定する。
- EC2インスタンスにエージェントをインストールする際にユーザーデータを使用して設定するようにする。
3.使用サービスについて
3-1.CloudWatchについて
Amazon CloudWatchは、AWS(Amazon Web Services)が提供するモニタリングおよび管理サービスであり、AWSリソースとアプリケーションのパフォーマンスと運用データを収集し、視覚化するために使用されます。以下の表で、CloudWatchの主要な機能と利点を簡単にまとめます。
機能 | 説明 |
---|---|
モニタリング | AWSリソース(EC2インスタンス、RDSデータベース、S3バケットなど)のメトリクスをリアルタイムで監視。 |
ログ管理 | アプリケーションやシステムのログデータを収集、モニタリング、分析するためのCloudWatch Logs。 |
アラーム設定 | 特定の条件を満たした場合に通知を受け取るためのアラームを設定。閾値を超えるとアラートを送信。 |
ダッシュボード | カスタマイズ可能なダッシュボードでメトリクスを視覚化し、一目でシステムの状態を把握。 |
イベント管理 | CloudWatch Eventsを使用して、システム変更やスケジュールされたイベントに基づいてAWSリソースを自動化。 |
メトリクスのカスタマイズ | ユーザー定義メトリクスを収集して監視。アプリケーション固有のメトリクスもカスタムメトリクスとして取り扱い可能。 |
ログインサイトの統合 | Amazon Elasticsearch ServiceやAWS Lambdaと連携して、ログデータの検索やリアルタイム処理を実現。 |
アクティビティの追跡 | CloudTrailと連携してAWSアカウントのアクティビティを追跡し、セキュリティとコンプライアンスの向上。 |
コスト管理 | リソース使用状況を監視して、コスト最適化とリソース利用の効率化をサポート。 |
メトリクスの保存 | 長期間のメトリクスデータを保存して、履歴データを基にしたトレンド分析やキャパシティプランニングを可能に。 |
CloudWatchを活用することで、システムの可視性が向上し、問題の迅速な検出と対応が可能になります。また、リソースの効率的な利用とコスト削減にも貢献します。
3-2.Amazon SNSの概要
Amazon SNS(Simple Notification Service)は、AWSが提供するフルマネージドなメッセージングサービスで、アプリケーション間やデバイス間でメッセージを迅速かつ信頼性高く送信するために使用されます。以下の表で、SNSの主要な機能と利点を簡単にまとめます。
機能 | 説明 |
---|---|
メッセージ配信 | メッセージを複数の購読者(メール、SMS、HTTP/HTTPSエンドポイント、SQSキューなど)に配信。 |
トピックベースの送信 | トピックを使用して、複数の購読者に対して効率的にメッセージをブロードキャスト。 |
メッセージのフィルタリング | メッセージ属性を使用して、特定の条件に一致するメッセージのみを購読者に配信。 |
モバイルプッシュ通知 | iOS、Android、Kindleなどのモバイルデバイスにプッシュ通知を送信。 |
スケーラビリティ | 大量のメッセージを同時に送信可能。高スループットを持つシステムに対応。 |
信頼性と可用性 | メッセージの冗長保存と複数のデリバリ試行により、高い信頼性と可用性を提供。 |
セキュリティ | メッセージの暗号化とIAMポリシーによるアクセス制御で、データのセキュリティを確保。 |
統合の容易さ | AWS Lambda、Amazon S3、Amazon EC2など、他のAWSサービスと容易に統合可能。 |
コスト効率 | 実際に送信したメッセージの数に基づく課金モデルで、コストを最適化。 |
グローバルな配信 | 世界中のユーザーに対して迅速にメッセージを配信可能。AWSのグローバルインフラストラクチャを利用。 |
Amazon SNSを活用することで、リアルタイムな通知システムを構築し、ユーザーとのコミュニケーションやシステム間の連携を強化することができます。
4.構成図
5.EC2設定
CloudWatch・SNSの構築の前にEC2インスタンスにエージェントをインストールするところからスタートします。
構築の概要は下記の通りです。
5-1.前提
- IAMロール(CloudWatchAgentAdminPolicy/CloudWatchAgentServerPolicy)を付与
5-2.初期設定時
初回はウィザードを使用して設定すると間違いないです。
# CloudWatchエージェントのインストール
sudo yum install amazon-cloudwatch-agent
# ウィザードを使用して初期設定
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-config-wizard
こちらを使用して必要なものを選択して作成しましょう。
ウィザードの中でSSMパラメータストアに保存するかの質問があります。
Do you want to store the config in the SSM parameter store?
1. yes
2. no
default choice: [1]:
1
こちらがですが、今回はyesにしましょう。
私は今回デフォルトの「AmazonCloudWatch-linux」で設定しております。
ちなみに、私の設定ファイルは以下の通りで、メモリ・ディスク使用率の取得とエラーログの収集が含まれています。
※CPU使用率はエージェントをインストールすればデフォルトで収集できます。
{
"agent": {
"metrics_collection_interval": 60,
"run_as_user": "root"
},
"logs": {
"logs_collected": {
"files": {
"collect_list": [
{
"file_path": "/var/log/httpd/error_log",
"log_group_name": "ApacheErrorLogs_{instance_id}",
"log_stream_name": "{instance_id}",
"log_group_class": "STANDARD",
"retention_in_days": -1
}
]
}
}
},
"metrics": {
"aggregation_dimensions": [
["InstanceId"]
],
"append_dimensions": {
"AutoScalingGroupName": "${aws:AutoScalingGroupName}",
"ImageId": "${aws:ImageId}",
"InstanceId": "${aws:InstanceId}",
"InstanceType": "${aws:InstanceType}"
},
"metrics_collected": {
"disk": {
"measurement": ["used_percent"],
"metrics_collection_interval": 60,
"resources": ["*"]
},
"mem": {
"measurement": ["mem_used_percent"],
"metrics_collection_interval": 60
}
}
}
}
ここまでできたら、以下のコマンドでSSMパラメータストアの情報を読み取って起動します。
# パラメータストアに保存した設定を読み込んで起動
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -c ssm:AmazonCloudWatch-linux -s
これで一通りの流れが完了です。メモリ等読み取れるようになります。
5-2.EC2の2台目以降のユーザーデータ
一度作成してSSMパラメータストアに情報がある限りは2台目以降のインスタンスの立ち上げはもっと簡単にメトリクスを収集できるようになります。
# CloudWatchエージェントのインストール
sudo yum install amazon-cloudwatch-agent
# パラメータストアに保存した設定を読み込んで起動
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -c ssm:AmazonCloudWatch-linux -s
これだけでメトリクスを収集できるようになります。
6.CloudWatch.SNSソースコード(CPU・ディスク・メモリ使用率)
YAML形式にて記述しております。
AWSTemplateFormatVersion: '2010-09-09'
Description: >-
CloudFormation template to create SNS notifications for EC2 metrics (CPU, Memory, Disk) exceeding thresholds.
Resources:
NotificationTopic:
Type: "AWS::SNS::Topic"
Properties:
DisplayName: "EC2 Monitoring Notifications"
Subscription:
- Protocol: email
Endpoint: !Ref SNSEmail
CloudWatchAlarmCPUWarning:
Type: "AWS::CloudWatch::Alarm"
Properties:
AlarmName: "naoki-web01-CPUUtilization-Warning"
ComparisonOperator: "GreaterThanThreshold"
EvaluationPeriods: 1
MetricName: "CPUUtilization"
Namespace: "AWS/EC2"
Period: 300
Statistic: "Average"
Threshold: 80
AlarmDescription: "Alarm when CPU usage exceeds 80%"
AlarmActions:
- !Ref NotificationTopic
Dimensions:
- Name: "InstanceId"
Value: !Ref InstanceId
CloudWatchAlarmCPUCritical:
Type: "AWS::CloudWatch::Alarm"
Properties:
AlarmName: "naoki-web01-CPUUtilization-Critical"
ComparisonOperator: "GreaterThanThreshold"
EvaluationPeriods: 1
MetricName: "CPUUtilization"
Namespace: "AWS/EC2"
Period: 300
Statistic: "Average"
Threshold: 90
AlarmDescription: "Alarm when CPU usage exceeds 90%"
AlarmActions:
- !Ref NotificationTopic
Dimensions:
- Name: "InstanceId"
Value: !Ref InstanceId
CloudWatchAlarmMemoryWarning:
Type: "AWS::CloudWatch::Alarm"
Properties:
AlarmName: "naoki-web01-mem-used-percent-Warning"
ComparisonOperator: "GreaterThanThreshold"
EvaluationPeriods: 1
MetricName: "mem_used_percent"
Namespace: "CWAgent"
Period: 300
Statistic: "Average"
Threshold: 80
AlarmDescription: "Alarm when memory usage exceeds 80%"
AlarmActions:
- !Ref NotificationTopic
Dimensions:
- Name: "InstanceId"
Value: !Ref InstanceId
- Name: "ImageId"
Value: !Ref ImageId
- Name: "InstanceType"
Value: !Ref InstanceType
CloudWatchAlarmMemoryCritical:
Type: "AWS::CloudWatch::Alarm"
Properties:
AlarmName: "naoki-web01-mem-used-percent-Critical"
ComparisonOperator: "GreaterThanThreshold"
EvaluationPeriods: 1
MetricName: "mem_used_percent"
Namespace: "CWAgent"
Period: 300
Statistic: "Average"
Threshold: 90
AlarmDescription: "Alarm when memory usage exceeds 90%"
AlarmActions:
- !Ref NotificationTopic
Dimensions:
- Name: "InstanceId"
Value: !Ref InstanceId
- Name: "ImageId"
Value: !Ref ImageId
- Name: "InstanceType"
Value: !Ref InstanceType
CloudWatchAlarmDiskWarning:
Type: "AWS::CloudWatch::Alarm"
Properties:
AlarmName: "naoki-web01-Disk-80percent-used"
ComparisonOperator: "GreaterThanThreshold"
EvaluationPeriods: 1
MetricName: "disk_used_percent"
Namespace: "CWAgent"
Period: 300
Statistic: "Average"
Threshold: 80
AlarmDescription: "Alarm when disk usage exceeds 80%"
AlarmActions:
- !Ref NotificationTopic
Dimensions:
- Name: "path"
Value: "/"
- Name: "InstanceId"
Value: !Ref InstanceId
- Name: "ImageId"
Value: !Ref ImageId
- Name: "InstanceType"
Value: !Ref InstanceType
- Name: "device"
Value: !Ref Device
- Name: "fstype"
Value: !Ref FilesystemType
CloudWatchAlarmDiskCritical:
Type: "AWS::CloudWatch::Alarm"
Properties:
AlarmName: "naoki-web01-Disk-90percent-used"
ComparisonOperator: "GreaterThanThreshold"
EvaluationPeriods: 1
MetricName: "disk_used_percent"
Namespace: "CWAgent"
Period: 300
Statistic: "Average"
Threshold: 90
AlarmDescription: "Alarm when disk usage exceeds 90%"
AlarmActions:
- !Ref NotificationTopic
Dimensions:
- Name: "path"
Value: "/"
- Name: "InstanceId"
Value: !Ref InstanceId
- Name: "ImageId"
Value: !Ref ImageId
- Name: "InstanceType"
Value: !Ref InstanceType
- Name: "device"
Value: !Ref Device
- Name: "fstype"
Value: !Ref FilesystemType
Outputs:
NotificationTopicArn:
Description: "SNS Topic ARN"
Value: !Ref NotificationTopic
7.ソースコード詳細(CPU・ディスク・メモリ使用率)
このテンプレートは、EC2インスタンスのCPU、メモリ、およびディスク使用率が80%、90%の閾値を超えた場合にSNS通知を作成します。
7-1.SNS
プロパティ名 | 内容 | 説明 |
---|---|---|
Type |
AWS::SNS::Topic |
リソースのタイプ |
DisplayName |
EC2 Monitoring Notifications |
SNSトピックの表示名 |
Subscription |
SNSトピックに設定されるサブスクリプション | |
– Protocol |
email |
サブスクリプションのプロトコル(ここではメール) |
– Endpoint |
!Ref SNSEmail |
サブスクリプション先のメールアドレス |
7-2.アラート設定
プロパティ名 | 説明 |
---|---|
Type |
リソースの種類 |
AlarmName |
アラームの名前 |
ComparisonOperator |
比較演算子 |
EvaluationPeriods |
評価期間の数 |
MetricName |
監視するメトリクスの名前 |
Namespace |
メトリクスの名前空間 |
Period |
メトリクスを収集する期間(秒単位) |
Statistic |
統計方法 |
Threshold |
アラームをトリガーする閾値 |
AlarmDescription |
アラームの説明 |
AlarmActions |
アラームがトリガーされたときに実行されるアクション |
Dimensions |
メトリクスの次元 (パスやAMI IDなど) |
8.CloudWatch.SNSソースコード(エラーログ用)
AWSTemplateFormatVersion: '2010-09-09'
Description: >-
CloudFormation template to create SNS notifications for Apache error logs detected in CloudWatch Logs.
Resources:
# SNSトピックの作成
SNSTopic:
Type: 'AWS::SNS::Topic'
Properties:
TopicName: 'ApacheErrorLogsTopicweb01'
# SNSトピックにメールサブスクリプションの作成
SNSSubscription:
Type: 'AWS::SNS::Subscription'
Properties:
Protocol: 'email'
Endpoint: !Ref EmailAddress
TopicArn: !Ref SNSTopic
# CloudWatch Logs Metric Filterの作成
MetricFilter:
Type: 'AWS::Logs::MetricFilter'
Properties:
FilterPattern: '?error ?Error ?ERROR'
LogGroupName: !Ref LogGroupName
MetricTransformations:
- MetricValue: '1'
MetricNamespace: !Ref MetricNamespace
MetricName: !Ref MetricName
# CloudWatch アラームの作成
Alarm:
Type: 'AWS::CloudWatch::Alarm'
Properties:
AlarmDescription: 'Alarm when error logs are detected'
MetricName: !Ref MetricName
Namespace: !Ref MetricNamespace
Statistic: 'Sum'
Period: '300' # 5分間隔で集計
EvaluationPeriods: '1'
Threshold: '1'
ComparisonOperator: 'GreaterThanOrEqualToThreshold'
AlarmActions:
- Ref: 'SNSTopic'
OKActions:
- Ref: 'SNSTopic'
InsufficientDataActions:
- Ref: 'SNSTopic'
9.CloudWatch.SNSソースコード詳細(エラーログ用)
9-1.SNS
プロパティ名 | 内容 | 説明 |
---|---|---|
Type |
AWS::SNS::Topic |
リソースのタイプ |
TopicName |
ApacheErrorLogsTopicweb01 |
SNSトピックの名前 |
Type |
AWS::SNS::Subscription |
リソースのタイプ |
Protocol |
email |
サブスクリプションのプロトコル(メール) |
Endpoint |
!Ref EmailAddress |
メールサブスクリプション先のメールアドレス |
TopicArn |
!Ref SNSTopic |
SNSトピックのARN |
9-2.メトリクスフィルター設定
プロパティ名 | 内容 | 説明 |
---|---|---|
Type |
AWS::Logs::MetricFilter |
リソースのタイプ |
FilterPattern |
!Ref FilterPattern |
ログフィルタリングのパターン |
LogGroupName |
!Ref LogGroupName |
CloudWatchロググループの名前 |
MetricTransformations |
MetricValue: '1', MetricNamespace: !Ref MetricNamespace, MetricName: !Ref MetricName |
メトリクス変換の設定 |
9-3.アラート設定
プロパティ名 | 内容 | 説明 |
---|---|---|
Type |
AWS::CloudWatch::Alarm |
リソースのタイプ |
AlarmDescription |
‘Alarm when error logs are detected’ | アラームの説明 |
MetricName |
!Ref MetricName |
メトリクスの名前 |
Namespace |
!Ref MetricNamespace |
メトリクスの名前空間 |
Statistic |
‘Sum’ | 統計方法 |
Period |
‘300’ | メトリクスを収集する期間(秒単位) |
EvaluationPeriods |
‘1’ | 評価期間の数 |
Threshold |
‘1’ | アラームをトリガーする閾値 |
ComparisonOperator |
‘GreaterThanOrEqualToThreshold’ | 比較演算子 |
AlarmActions |
Ref: 'SNSTopic' |
アラームがトリガーされたときに実行されるアクション |
OKActions |
Ref: 'SNSTopic' |
アラームがOK状態になったときのアクション |
InsufficientDataActions |
Ref: 'SNSTopic' |
データ不足時のアクション |
10.検証
10-1.検証内容
- メモリ使用率を80%以上にしてアラート通知をする
- エラーログを入力してアラート通知をする
10-2.ディスク使用率
今回はディスク使用率80%の閾値を例にとって、アラート通知を行います。
まずはEC2(Amazon Linux2023)にてストレスコマンドをインストールします。
# stressコマンドのインストール
sudo yum install -y epel-release
sudo yum install -y stress
続いて現在のメモリ使用率を確認しつつ負荷をかけてメモリ使用率を上昇させます。
free -h
上記の情報から、約730Miの負荷をかけることでメモリ使用率が80%を超えることがわかります。
下記コマンドで負荷をかけていきます。
#バックグラウンドで500Mの負荷をかける
stress -m 1 --vm-bytes 500M --vm-hang 0 &
これで約83%のメモリ負荷をかけられていることがわかります。
CloudWatchダッシュボードでもメモリ負荷がかけられ、アラートが出ていることが確認できます。
さらにSNSでもアラートが発報されていることを確認できました。
最後に実行中のjobsを下記で停止しましょう。
#jobの確認
jobs
#jobの削除(数字は上記を参照)
kill %1
10-3.エラーログ
今回設定ファイルで参照しているファイルが/var/log/httpd/error_logになります。
メトリクスでerrorが出た際にSNS通知するようにしているのでこのファイルに直接的なエラーメッセージを追加してみます。
echo "error" | sudo tee -a /var/log/httpd/error_log
下記にerrorと書き込まれていることを確認できました。
ダッシュボードでも確認できました。
SNSでも約2分後あたりに発報されておりました。
11.感想
CloudWatchエージェントの設定にはかなり苦労しましたが、SSMパラメータストアを使用した方法を試したところ、すぐに成功しました。この経験から、まだまだ知識不足だと感じています。次回はこの構築の最終投稿として、Healthイベント通知についてお話しする予定です。よろしくお願いします。