毎日AWS利用料金をSlackに通知する方法（AWS Lambda & EventBridge）


## はじめに
AWSのコスト管理はクラウド環境を運用する上で非常に重要です。特に、コストの増加をリアルタイムで把握することは予算オーバーを防ぐための鍵です。本記事では、AWS LambdaとEventBridgeを使って、毎日決まった時間にAWSの利用料金をSlackに通知する仕組みを構築する手順を詳しく解説します。

この設定により、毎日のAWSコスト情報をSlackで簡単に確認でき、予算管理が容易になります。以下の手順を進めるだけで、複雑なサーバー構築やSNSの利用なしで簡単に通知機能を設定できます。

## 前提条件
- **AWSアカウント**を持っていること。
- **SlackでIncoming Webhook URL**が作成済みであること（Slackの通知を設定するために必要です）。
- **AWS Cost Explorerが有効化**されていること（AWS Billing Management Consoleから有効化できます）。

## ステップ 1: Slack Webhookの取得
まず、通知を送信したいSlackチャンネルにIncoming Webhookを設定し、Webhook URLを取得します。

1. [Slack APIページ](https://api.slack.com/messaging/webhooks)にアクセス。
2. 通知を受信したいチャンネルを選択し、Incoming Webhookを有効にします。
3. Webhook URLが生成されるので、これをメモしておきます（例: `https://hooks.slack.com/services/XXXX/XXXX/XXXX`）。
![スクリーンショット 2024-11-14 18.32.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364428/3a08ca2c-a571-c4e2-92be-132c6c5ecc31.png)

## ステップ 2: IAMロールとポリシーの設定
AWS Lambda関数がAWS Cost Explorer APIにアクセスするための権限を持つIAMロールを作成します。

1. **AWS Management Console**で「IAM」に移動。
2. **ロール**を選択し、「ロールの作成」をクリック。
3. 「AWSサービス」を選択し、「Lambda」を選択して「次のステップ: アタッチするポリシー」をクリックします。
4. 「ポリシーの作成」をクリックし、以下のJSONを使ってカスタムポリシーを作成します：

   ```json
   {
       "Version": "2012-10-17",
       "Statement": [
           {
               "Effect": "Allow",
               "Action": [
                   "ce:GetCostAndUsage"
               ],
               "Resource": "*"
           }
       ]
   }
   ```

5. このポリシーに名前を付け（例: `CostExplorerAccessPolicy`）、ロールにアタッチします。
6. 「ロールの作成」をクリックして、Lambda関数で使用するIAMロールを完成させます。

## ステップ 3: Lambda関数の作成
1. **AWS Lambdaコンソール**に移動し、「関数の作成」を選択します。
   - **ランタイム**: Python 3.8以上
   - **実行ロール**: 先ほど作成したIAMロール（例: `CostExplorerLambdaRole`）

2. 以下のコードをLambda関数に貼り付けます。このコードは、AWS Cost Explorerからデータを取得し、SlackのWebhookに利用料金を通知します。

### Lambda関数のコード

```python
import json
import boto3
import os
import http.client
from datetime import datetime, timezone

# 環境変数からSlack Webhook URLと予算額を取得
SLACK_WEBHOOK_URL = os.environ['SLACK_WEBHOOK_URL']
BUDGET_AMOUNT = float(os.environ.get('BUDGET_AMOUNT', 50000.0))

def lambda_handler(event, context):
    # AWS Cost Explorerクライアントの初期化
    client = boto3.client('ce', region_name='us-east-1')
    
    # 本日の日付
    today = datetime.now(timezone.utc).strftime('%Y-%m-%d')
    start_date = today[:8] + "01"  # 月の初日

    # 月初から本日までの合計利用料金を取得
    response = client.get_cost_and_usage(
        TimePeriod={'Start': start_date, 'End': today},
        Granularity='DAILY',
        Metrics=['UnblendedCost']
    )

    # 利用料金の取得
    today_cost = float(response['ResultsByTime'][-1]['Total']['UnblendedCost']['Amount'])
    month_to_date_cost = sum(float(day['Total']['UnblendedCost']['Amount']) for day in response['ResultsByTime'])

    # 通知メッセージ
    message = f"""
    予算額: {BUDGET_AMOUNT:.2f} USD
    利用料金（本日）: {today_cost:.2f} USD
    利用開始日時: 2024-11-06T07:00:00Z
    今月の利用料金: {month_to_date_cost:.2f} USD
    """
    
    # Slack WebhookのURLからホストとパスを分割
    url_parts = SLACK_WEBHOOK_URL.replace("https://", "").split("/", 1)
    host = url_parts[0]
    path = "/" + url_parts[1]

    # Slackに通知を送信
    conn = http.client.HTTPSConnection(host)
    payload = json.dumps({"text": message})
    headers = {'Content-Type': 'application/json'}
    conn.request("POST", path, body=payload, headers=headers)
    response = conn.getresponse()
    conn.close()

    return {
        'statusCode': response.status,
        'body': response.read().decode()
    }
```

### Lambda関数の環境変数設定
- **SLACK_WEBHOOK_URL**: 取得したSlackのWebhook URL
- **BUDGET_AMOUNT**: 月の予算額（例: `50000.0`）
![スクリーンショット 2024-11-14 18.33.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364428/df9c8d31-c1cb-587a-f994-cf5ceca24d48.png)

## ステップ 4: タイムアウトとメモリの設定
このLambda関数が適切に動作するためには、以下の設定も変更します。

1. Lambdaの「設定」タブから、タイムアウトを「10秒」に設定します。
![スクリーンショット 2024-11-14 19.25.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364428/0748f207-d65a-35e6-b981-25d94df3a8ab.png)

2. メモリのサイズを「256 MB」に増やします。

## ステップ 5: EventBridgeでスケジュールを設定
次に、毎日19時にこのLambda関数を実行するために、EventBridgeでスケジュールを設定します。

1. **EventBridgeのコンソール**に移動。
2. 「ルール」をクリックし、「ルールの作成」を選択。
3. ルールの名前を入力（例: `DailyAWSCostNotification`）。
4. スケジュールパターンで「Cron式」を選び、以下の式を入力します：
   毎日19時の月曜日から金曜日
   ![スクリーンショット 2024-11-14 18.49.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364428/b3221d29-cc13-cbf9-8798-86fd2dba5ace.png)
5. ターゲットでLambda関数を選択し、「ルールの作成」をクリック。
![スクリーンショット 2024-11-14 18.51.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364428/3fe2b26d-8f9f-ab58-4f35-0ca88092f2b3.png)
### 完成したスケジュール
![スクリーンショット 2024-11-14 19.31.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364428/c9412825-b7b0-718a-1179-1816800b16e6.png)



## ステップ 6: 動作確認
設定が完了したら、Lambda関数を手動でテストして動作を確認します。

1. Lambda関数の「テスト」タブで「テストイベント」を作成します。
2. デフォルトの内容で構わないので「テスト」をクリック。
3. 「成功」と表示され、Slackに通知が届くか確認します。
![スクリーンショット 2024-11-14 19.27.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364428/deedd4b0-f196-8dd8-3b02-d158603511fd.png)

## トラブルシューティング
- **「リクエストのタイムアウト」エラー**: タイムアウト時間が足りない場合は、「タイムアウト」設定を増やします。
- **Slackに通知が届かない**: Webhook URLが正しいか確認してください。また、環境変数が設定されていることを確認してください。

## まとめ
以上の設定で、毎日決まった時間にAWSの利用料金をSlackに通知する仕組みが完成しました。この設定により、予算を超えないようにコストをリアルタイムで管理し、不要な出費を防ぐことが可能です。AWSのコスト管理は、プロジェクトの健全な運営に不可欠です。定期的な通知を活用し、コストが計画通りに推移しているかを確認しましょう。