はじめに
Amazon ECS(Elastic Container Service)でコンテナアプリケーションを運用している際、タスクの異常停止や状態変更を即座に把握することは運用上非常に重要です。本記事では、ECSタスクのステータス変更を自動監視し、メール通知を受け取る方法を、最新のAWSベストプラクティスに基づいて詳しく解説します。
この記事で学べること
- ECSタスク監視の重要性と基本概念
- EventBridgeとSNSを使った基本的な監視設定
- Lambdaを活用した高度な通知システム
- コスト効率的な監視システムの構築方法
- 実際の設定手順とトラブルシューティング
対象読者
- AWSでECSを運用している開発者・インフラエンジニア
- コンテナ監視システムを構築したい方
- ECS運用の自動化を検討している方
ECSタスク監視の重要性
なぜECSタスクの監視が必要なのか?
ECSで運用するコンテナアプリケーションでは、以下のような問題が発生する可能性があります:
- アプリケーションエラーによるタスク停止
- リソース不足によるタスク強制終了
- ヘルスチェック失敗による自動再起動
- スケーリングイベントによる状態変更
これらの問題を早期に検知し、適切に対応するためには、リアルタイムでの監視とアラート機能が不可欠です。
ECSタスクの主要なステータス
ECSタスクは以下のステータスを持ちます:
ステータス | 説明 | 監視の重要度 |
---|---|---|
PENDING | タスク起動準備中 | 中 |
RUNNING | タスク正常実行中 | 低 |
STOPPED | タスク停止済み | 高 |
DEPROVISIONING | リソース解放中 | 中 |
特にSTOPPED
ステータスは、予期しない停止を示す可能性があるため、最優先で監視すべきステータスです。
監視アーキテクチャの選択肢
1. 基本パターン:EventBridge + SNS
推奨度:★★★★★(初心者〜中級者向け)
ECS Task State Change → EventBridge Rule → SNS Topic → Email Notification
特徴:
- 設定が簡単
- 低コスト(多くの場合無料)
- 高い可用性
- メンテナンス不要
2. 高度なパターン:EventBridge + Lambda + 複数通知
推奨度:★★★★☆(中級者〜上級者向け)
ECS → EventBridge → Lambda Function → SNS/Slack/Teams/PagerDuty
└─→ CloudWatch Logs
└─→ DynamoDB (履歴保存)
特徴:
- 高いカスタマイズ性
- 複数の通知チャネル
- インテリジェントな通知制御
- 履歴データの保存・分析
基本パターンの実装手順
Step 1: SNSトピックの作成
まず、メール通知を送信するためのSNSトピックを作成します。
# SNSトピック作成
aws sns create-topic \
--name "ECS-TaskStateChange-Alert" \
--region ap-northeast-1
# 出力例
{
"TopicArn": "arn:aws:sns:ap-northeast-1:123456789012:ECS-TaskStateChange-Alert"
}
Step 2: メール購読の設定
作成したSNSトピックにメールアドレスを登録します。
# メール購読追加(管理者用)
aws sns subscribe \
--topic-arn "arn:aws:sns:ap-northeast-1:123456789012:ECS-TaskStateChange-Alert" \
--protocol email \
--notification-endpoint "admin@example.com"
# 開発チーム用
aws sns subscribe \
--topic-arn "arn:aws:sns:ap-northeast-1:123456789012:ECS-TaskStateChange-Alert" \
--protocol email \
--notification-endpoint "devops@example.com"
重要: 購読後、各メールアドレスに確認メールが送信されるため、必ず確認してください。
Step 3: EventBridge権限の設定
EventBridgeがSNSトピックに通知を送信できるよう権限を設定します。
# EventBridge用の権限ポリシー設定
aws sns set-topic-attributes \
--topic-arn "arn:aws:sns:ap-northeast-1:123456789012:ECS-TaskStateChange-Alert" \
--attribute-name Policy \
--attribute-value '{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowEventBridgePublish",
"Effect": "Allow",
"Principal": {
"Service": "events.amazonaws.com"
},
"Action": "sns:Publish",
"Resource": "arn:aws:sns:ap-northeast-1:123456789012:ECS-TaskStateChange-Alert"
}
]
}'
Step 4: EventBridgeルールの作成
4.1 タスク停止専用ルール(推奨)
最も重要な「タスク停止」イベントのみを監視するルールです。
# ルール作成
aws events put-rule \
--name "ECS-TaskStopped-Alert" \
--event-pattern '{
"source": ["aws.ecs"],
"detail-type": ["ECS Task State Change"],
"detail": {
"lastStatus": ["STOPPED"],
"stoppedReason": ["Essential container in task exited"]
}
}' \
--state ENABLED \
--description "ECS task stopped due to container exit"
# ターゲット追加
aws events put-targets \
--rule "ECS-TaskStopped-Alert" \
--targets "Id"="1","Arn"="arn:aws:sns:ap-northeast-1:123456789012:ECS-TaskStateChange-Alert"
4.2 包括的監視ルール(オプション)
全てのステータス変更を監視したい場合のルールです。
# 包括的ルール作成
aws events put-rule \
--name "ECS-AllStateChanges-Alert" \
--event-pattern '{
"source": ["aws.ecs"],
"detail-type": ["ECS Task State Change"],
"detail": {
"clusterArn": ["arn:aws:ecs:ap-northeast-1:123456789012:cluster/production-cluster"],
"lastStatus": ["PENDING", "RUNNING", "STOPPED"]
}
}' \
--state ENABLED \
--description "All ECS task state changes for production cluster"
# ターゲット追加
aws events put-targets \
--rule "ECS-AllStateChanges-Alert" \
--targets "Id"="1","Arn"="arn:aws:sns:ap-northeast-1:123456789012:ECS-TaskStateChange-Alert"
Step 5: 設定のテスト
設定が正しく動作するかテストしてみましょう。
テスト用タスク定義の作成
{
"family": "test-task-definition",
"networkMode": "awsvpc",
"requiresCompatibilities": ["FARGATE"],
"cpu": "256",
"memory": "512",
"executionRoleArn": "arn:aws:iam::123456789012:role/ecsTaskExecutionRole",
"containerDefinitions": [
{
"name": "test-container",
"image": "public.ecr.aws/amazonlinux/amazonlinux:latest",
"essential": true,
"command": ["sh", "-c", "echo 'Test started'; sleep 10; echo 'Test completed'; exit 0"]
}
]
}
テストタスクの実行
# タスク定義の登録
aws ecs register-task-definition \
--cli-input-json file://test-task-definition.json
# テストタスクの実行
aws ecs run-task \
--cluster "production-cluster" \
--task-definition "test-task-definition" \
--launch-type FARGATE \
--network-configuration "awsvpcConfiguration={subnets=[subnet-12345678],securityGroups=[sg-12345678],assignPublicIp=ENABLED}"
約10秒後にタスクが正常終了し、メール通知が届くはずです。
高度なパターンの実装
基本パターンで物足りない場合は、Lambdaを使った高度な監視システムを構築できます。
Lambda関数の作成
以下のPythonコードでより詳細な通知を実現できます:
import json
import boto3
import os
from datetime import datetime, timezone
def lambda_handler(event, context):
"""
ECSタスクステート変更イベントを処理し、
フォーマットされた通知を送信
"""
try:
# イベント詳細の抽出
detail = event['detail']
cluster_name = detail['clusterArn'].split('/')[-1]
task_arn = detail['taskArn']
task_id = task_arn.split('/')[-1][:8] # 短縮ID
last_status = detail['lastStatus']
# タスク定義情報の取得
task_def_arn = detail.get('taskDefinitionArn', '')
task_def_name = task_def_arn.split('/')[-1].split(':')[0] if task_def_arn else 'Unknown'
# 通知メッセージの作成
timestamp = datetime.now(timezone.utc).strftime('%Y-%m-%d %H:%M:%S UTC')
if last_status == 'STOPPED':
stopped_reason = detail.get('stoppedReason', 'Unknown')
exit_code = detail.get('containers', [{}])[0].get('exitCode', 'Unknown')
# 重要度の判定
is_critical = 'Essential container in task exited' in stopped_reason
priority = '🚨 CRITICAL' if is_critical else '⚠️ WARNING'
message = f"""{priority} ECS Task Stopped
📋 基本情報:
• クラスター: {cluster_name}
• タスク定義: {task_def_name}
• タスクID: {task_id}
• ステータス: {last_status}
🔍 詳細情報:
• 停止理由: {stopped_reason}
• 終了コード: {exit_code}
• 発生時刻: {timestamp}
🔗 リンク:
• AWS Console: https://console.aws.amazon.com/ecs/home?region=ap-northeast-1#/clusters/{cluster_name}/tasks
タスクARN: {task_arn}
"""
subject = f"{priority} ECS Task Stopped - {cluster_name}/{task_def_name}"
elif last_status == 'RUNNING':
message = f"""✅ ECS Task Started Successfully
📋 基本情報:
• クラスター: {cluster_name}
• タスク定義: {task_def_name}
• タスクID: {task_id}
• ステータス: {last_status}
• 開始時刻: {timestamp}
🔗 リンク:
• AWS Console: https://console.aws.amazon.com/ecs/home?region=ap-northeast-1#/clusters/{cluster_name}/tasks
タスクARN: {task_arn}
"""
subject = f"✅ ECS Task Started - {cluster_name}/{task_def_name}"
else:
message = f"""ℹ️ ECS Task State Change
📋 基本情報:
• クラスター: {cluster_name}
• タスク定義: {task_def_name}
• タスクID: {task_id}
• ステータス: {last_status}
• 更新時刻: {timestamp}
タスクARN: {task_arn}
"""
subject = f"ℹ️ ECS Task State Change - {cluster_name}/{task_def_name}"
# SNS通知送信
sns = boto3.client('sns')
response = sns.publish(
TopicArn=os.environ['SNS_TOPIC_ARN'],
Message=message,
Subject=subject
)
# CloudWatch Logsに記録
print(f"Notification sent successfully. MessageId: {response['MessageId']}")
print(f"Event details: {json.dumps(event, default=str)}")
return {
'statusCode': 200,
'body': json.dumps({
'message': 'Event processed successfully',
'messageId': response['MessageId']
})
}
except Exception as e:
print(f"Error processing event: {str(e)}")
print(f"Event: {json.dumps(event, default=str)}")
# エラー通知
sns = boto3.client('sns')
sns.publish(
TopicArn=os.environ['SNS_TOPIC_ARN'],
Message=f"ECS監視Lambda関数でエラーが発生しました:\n{str(e)}",
Subject="🚨 ECS監視システムエラー"
)
return {
'statusCode': 500,
'body': json.dumps({'error': str(e)})
}
Lambda関数のデプロイ
# Lambda関数用のIAMロール作成
aws iam create-role \
--role-name ECS-Monitor-Lambda-Role \
--assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}'
# 必要な権限をアタッチ
aws iam attach-role-policy \
--role-name ECS-Monitor-Lambda-Role \
--policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
aws iam attach-role-policy \
--role-name ECS-Monitor-Lambda-Role \
--policy-arn arn:aws:iam::aws:policy/AmazonSNSFullAccess
# Lambda関数作成(事前にfunction.zipを作成)
aws lambda create-function \
--function-name "ECS-StateChange-Processor" \
--runtime python3.9 \
--role "arn:aws:iam::123456789012:role/ECS-Monitor-Lambda-Role" \
--handler lambda_function.lambda_handler \
--zip-file fileb://function.zip \
--environment Variables='{SNS_TOPIC_ARN=arn:aws:sns:ap-northeast-1:123456789012:ECS-TaskStateChange-Alert}' \
--timeout 30 \
--description "ECS task state change processor with enhanced notifications"
コスト分析と最適化
料金体系の理解
基本パターンのコスト
サービス | 無料枠 | 超過料金 | 月間想定コスト |
---|---|---|---|
EventBridge | 100万イベント/月 | $1.00/100万イベント | $0 |
SNS (Email) | 1,000通/月 | $0.50/1,000通 | $0 |
合計 | – | – | $0 |
高度なパターンのコスト
サービス | 無料枠 | 超過料金 | 月間想定コスト |
---|---|---|---|
EventBridge | 100万イベント/月 | $1.00/100万イベント | $0 |
Lambda | 100万リクエスト/月 | $0.20/100万リクエスト | $0 |
SNS (Email) | 1,000通/月 | $0.50/1,000通 | $0 |
CloudWatch Logs | 5GB/月 | $0.50/GB | $0.05 |
合計 | – | – | $0.05 |
コスト最適化のポイント
イベントフィルタリングの活用
{
"detail": {
"lastStatus": ["STOPPED"],
"stoppedReason": ["Essential container in task exited"]
}
}
通知頻度の制御
重要度に応じた通知先の分離
重複通知の抑制
ログ保持期間の最適化
aws logs put-retention-policy \
--log-group-name "/aws/lambda/ECS-StateChange-Processor" \
--retention-in-days 7
セキュリティベストプラクティス
1. 最小権限の原則
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"sns:Publish"
],
"Resource": "arn:aws:sns:ap-northeast-1:123456789012:ECS-TaskStateChange-Alert"
},
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:ap-northeast-1:123456789012:*"
}
]
}
2. 暗号化の実装
# SNSトピック暗号化
aws sns set-topic-attributes \
--topic-arn "arn:aws:sns:ap-northeast-1:123456789012:ECS-TaskStateChange-Alert" \
--attribute-name KmsMasterKeyId \
--attribute-value "alias/aws/sns"
3. アクセス制御
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "RestrictToECSEvents",
"Effect": "Allow",
"Principal": {
"Service": "events.amazonaws.com"
},
"Action": "sns:Publish",
"Resource": "*",
"Condition": {
"StringEquals": {
"aws:SourceAccount": "123456789012"
}
}
}
]
}
監視・運用のベストプラクティス
1. システム自体の監視
監視システムが正常に動作しているかを監視することも重要です。
# EventBridge失敗アラーム
aws cloudwatch put-metric-alarm \
--alarm-name "EventBridge-ECS-Rule-Failures" \
--alarm-description "EventBridge ECS rule failures" \
--metric-name FailedInvocations \
--namespace AWS/Events \
--statistic Sum \
--period 300 \
--threshold 1 \
--comparison-operator GreaterThanOrEqualToThreshold \
--dimensions Name=RuleName,Value=ECS-TaskStopped-Alert
# SNS配信失敗アラーム
aws cloudwatch put-metric-alarm \
--alarm-name "SNS-ECS-Delivery-Failures" \
--alarm-description "SNS ECS notification delivery failures" \
--metric-name NumberOfNotificationsFailed \
--namespace AWS/SNS \
--statistic Sum \
--period 300 \
--threshold 1 \
--comparison-operator GreaterThanOrEqualToThreshold \
--dimensions Name=TopicName,Value=ECS-TaskStateChange-Alert
2. 定期的なテスト
#!/bin/bash
# 月次テストスクリプト
echo "ECS監視システムのテストを開始します..."
# テストタスクの実行
TASK_ARN=$(aws ecs run-task \
--cluster "production-cluster" \
--task-definition "test-task-definition" \
--launch-type FARGATE \
--network-configuration "awsvpcConfiguration={subnets=[subnet-12345678],securityGroups=[sg-12345678],assignPublicIp=ENABLED}" \
--query 'tasks[0].taskArn' \
--output text)
echo "テストタスクを実行しました: $TASK_ARN"
echo "10秒後にメール通知が届くことを確認してください。"
3. ログ分析
# 過去24時間のイベント確認
aws logs filter-log-events \
--log-group-name "/aws/lambda/ECS-StateChange-Processor" \
--start-time $(date -d '24 hours ago' +%s)000 \
--filter-pattern "ERROR"
# 通知統計の取得
aws cloudwatch get-metric-statistics \
--namespace AWS/SNS \
--metric-name NumberOfMessagesPublished \
--dimensions Name=TopicName,Value=ECS-TaskStateChange-Alert \
--statistics Sum \
--start-time $(date -d '7 days ago' --iso-8601) \
--end-time $(date --iso-8601) \
--period 86400
トラブルシューティング
よくある問題と解決策
1. 通知が届かない
症状: ECSタスクが停止してもメール通知が届かない
確認手順:
# 1. SNS購読状態の確認
aws sns list-subscriptions-by-topic \
--topic-arn "arn:aws:sns:ap-northeast-1:123456789012:ECS-TaskStateChange-Alert"
# 2. EventBridgeルールの確認
aws events describe-rule --name "ECS-TaskStopped-Alert"
# 3. ルールのターゲット確認
aws events list-targets-by-rule --rule "ECS-TaskStopped-Alert"
解決策:
- SNS購読が「Confirmed」状態であることを確認
- EventBridgeルールが「ENABLED」状態であることを確認
- IAM権限の再確認
2. 重複通知の発生
症状: 同じイベントで複数回通知が届く
原因と解決策:
# 重複ルールの確認
aws events list-rules --name-prefix "ECS-"
# 不要なルールの削除
aws events delete-rule --name "重複ルール名" --force
3. Lambda関数のエラー
症状: Lambda関数でエラーが発生している
デバッグ手順:
# エラーログの確認
aws logs tail /aws/lambda/ECS-StateChange-Processor --follow
# 関数の設定確認
aws lambda get-function --function-name "ECS-StateChange-Processor"
# 環境変数の確認
aws lambda get-function-configuration \
--function-name "ECS-StateChange-Processor" \
--query 'Environment.Variables'
デバッグ用コマンド集
# EventBridge関連
aws events list-rules --name-prefix "ECS-"
aws events describe-rule --name "ECS-TaskStopped-Alert"
aws events list-targets-by-rule --rule "ECS-TaskStopped-Alert"
# SNS関連
aws sns list-topics
aws sns get-topic-attributes --topic-arn "arn:aws:sns:ap-northeast-1:123456789012:ECS-TaskStateChange-Alert"
aws sns list-subscriptions-by-topic --topic-arn "arn:aws:sns:ap-northeast-1:123456789012:ECS-TaskStateChange-Alert"
# Lambda関連(高度なパターンの場合)
aws lambda list-functions --query 'Functions[?contains(FunctionName, `ECS`)]'
aws lambda get-function --function-name "ECS-StateChange-Processor"
aws logs describe-log-groups --log-group-name-prefix "/aws/lambda/ECS-"
まとめ
本記事では、Amazon ECSタスクのステータス変更を監視し、メール通知を受け取る方法について詳しく解説しました。
重要なポイント
- 基本パターンで十分な場合が多い
- EventBridge + SNSの組み合わせ
- 無料枠内で運用可能
- 設定が簡単で保守性が高い
- 段階的な機能拡張が可能
- まず基本パターンで開始
- 必要に応じてLambdaを追加
- 複数の通知チャネルに対応
- コスト効率が良い
- 多くの場合、月額$0-5程度
- AWSの無料枠を有効活用
- 必要な機能のみを実装
- セキュリティと運用性を重視
- 最小権限の原則
- 暗号化の実装
- 監視システム自体の監視
次のステップ
- 基本パターンの実装から始める
- テスト環境で動作確認
- 本番環境への適用
- 必要に応じて高度な機能を追加
ECSの運用において、適切な監視システムは障害の早期発見と迅速な対応を可能にします。本記事の手順を参考に、あなたの環境に最適な監視システムを構築してください。
参考リンク
著者情報
AWS認定ソリューションアーキテクト
コンテナ・マイクロサービス専門
最終更新: 2025年7月4日
記事カテゴリ: AWS, ECS, 監視, DevOps, インフラ自動化
コメント