こんにちは、ENECHANGEの石橋です。
AWSのコストを管理することは、企業にとって非常に重要です。
本ブログでは、AWS Budgets, SNS, Chatbot, Event Bridge, Lambda, Slackを統合したコスト監視システムの開発について解説します。
TerraformやLambdaの実装例も提供しますので、ご参考になれば幸いです。
システム機能概要
- 全体および環境別の予算を設定し、超過時にアラートをSlack通知します。
- 設定した予算に対して月次コストレポートを作成し、Slack通知します。
システムアーキテクチャ概要
以下は、AWSコスト監視システムのアーキテクチャ図です:
主要コンポーネント
AWS Budgets:
- 全体および環境別の予算を設定。
- 予算超過時に通知をトリガーします。
Amazon SNS:
- 通知のハブとして機能し、アラートをAWS Chatbotに転送します。
AWS Chatbot:
- アラートをリアルタイムでSlackチャンネルに送信します。
AWS Event Bridge:
- 月次の定期トリガーを設定し、Lambdaを起動することでレポートの自動化を実現します。
AWS Lambda:
- 月次コストレポートを処理し、AWS Cost Explorerにクエリを投げてコストの詳細を取得します。
Slack:
- 予算アラートや月次レポートの通知を一元化します。
実装の詳細
0. タグの設定
- コスト監視したいサービスの全てにServiceタグをつけてください。
- コスト監視したいサービスの全てにEnvironmentタグをつけてください。
- 共通部分:Common
- 個別部分:Production, Staging, Development 等
1. AWS Budgetsの設定
AWS Budgetsを使用してコストの閾値を設定します。 以下はServiceタグとEnvironmentタグでフィルタリングした実装例です。
AWS BudgetsのTerraformコード例
resource "aws_budgets_budget" "monthly_cost_budget_development" { name = "Monthly-Cost-Budget-Common" budget_type = "COST" limit_amount = "1000" # USD limit_unit = "USD" time_unit = "MONTHLY" cost_filter { name = "TagKeyValue" values = [ "user:Service$your-service-name", "user:Environment$development" ] } notification { comparison_operator = "GREATER_THAN" threshold = 100 threshold_type = "PERCENTAGE" notification_type = "FORECASTED" subscriber { address = aws_sns_topic.cost_alert_topic.arn type = "SNS" } } }
2. SNSとChatbotの統合
SNSは予算アラートをAWS Chatbotに送信し、それをSlackに転送します。
SNSのTerraformコード例
resource "aws_sns_topic" "cost_alert_topic" { name = "cost-alert-topic" } resource "aws_sns_topic_policy" "cost_alert_policy" { arn = aws_sns_topic.cost_alert_topic.arn policy = jsonencode({ Version = "2008-10-17", Statement = [ { Sid = "AllowBudgetsToPublish", Effect = "Allow", Principal = { Service = "budgets.amazonaws.com" }, Action = "SNS:Publish", Resource = aws_sns_topic.cost_alert_topic.arn }, { Sid = "DefaultPermissions", Effect = "Allow", Principal = { AWS = "*" }, Action = [ "SNS:GetTopicAttributes", "SNS:SetTopicAttributes", "SNS:AddPermission", "SNS:RemovePermission", "SNS:DeleteTopic", "SNS:Subscribe", "SNS:ListSubscriptionsByTopic", "SNS:Publish" ], Condition = { StringEquals = { "AWS:SourceOwner": data.aws_caller_identity.current.account_id } }, Resource = aws_sns_topic.cost_alert_topic.arn ] }) }
3. AWS Cost Explorerへのクエリ処理
月次で前月の詳細なコストデータを取得するために、Lambdaを使用してAWS Cost Explorerにクエリを投げます。
Cost ExplorerクエリのLambda関数例
import boto3 import datetime import json import requests # Cost Explorerクライアント ce = boto3.client('ce') def lambda_handler(event, context): today = datetime.date.today() start_of_month = today.replace(day=1) end_of_month = today response = ce.get_cost_and_usage( TimePeriod={ 'Start': start_of_month.strftime('%Y-%m-%d'), 'End': end_of_month.strftime('%Y-%m-%d') }, Granularity='MONTHLY', Metrics=['UnblendedCost'], Filter={ 'And': [ { 'Tags': { 'Key': 'Service', 'Values': 'your-service-name' } }, { 'Tags': { 'Key': 'Environment', 'Values': 'development' } } ] } ) dev_cost = float(response['ResultsByTime'][0]['Total'].get('UnblendedCost', {}).get('Amount', 0.0))
4. 月次レポートの自動化
月次コストレポートはEventBridgeを使用してトリガーされ、Slackに送信されます。
月次トリガーのEventBridgeルール
resource "aws_cloudwatch_event_rule" "monthly_trigger" { name = "monthly-cost-report" schedule_expression = "cron(0 0 1 * ? *)" # 毎月1日に実行 } resource "aws_cloudwatch_event_target" "lambda_target" { rule = aws_cloudwatch_event_rule.monthly_trigger.name arn = aws_lambda_function.report_lambda.arn } resource "aws_lambda_permission" "allow_cloudwatch_to_invoke_lambda" { statement_id = "AllowExecutionFromCloudWatch" action = "lambda:InvokeFunction" function_name = aws_lambda_function.report_lambda.function_name principal = "events.amazonaws.com" source_arn = aws_cloudwatch_event_rule.monthly_trigger.arn }
Slack通知のLambda関数例
url = "https://slack.com/api/chat.postMessage" headers = { "Authorization": f"Bearer your-slack-token", "Content-Type": "application/json" } payload = { "channel": "your-slack-channel", "text": f"development cost: {dev_cost}" } response = requests.post(url, headers=headers, json=payload) if not response.json().get("ok"): raise Exception(f"Slack API Error: {response.json()}")
今後の拡張
将来的には以下の機能を追加予定です:
Cost Explorerレポート:
- 詳細なレポートを生成してエクスポート。
カスタムダッシュボード:
- Quicksightや外部ツールと統合して高度な可視化を実現。
結論
AWS Budgets, SNS, Chatbot, Event Bridge, Lambda, Slackを統合したこのシステムにより、リアルタイムのコスト監視、及び月次レポートのSlack通知が可能になります。
このシステムをご参考にしていただき、AWSコスト管理の最適化にお役立てください。