使ってなかったAWSアカウントを使い始めたので、まずはコスト管理

## はじめに（注意）
この投稿は（お試しで）AIちゃんに、
**作業内容をMD形式で出力してもらったもの**になります。

いけだの手によって、少しだけRvはされていますが、基本はそのままですので、
口調などが統一されていないなど、ある程度、ご容赦頂ければと思います。

## 🎯 目的
自分のAWSアカウントを久しぶりに使おうと思ったのですが、
アカウント作成から1年経過したため、[無料枠](https://aws.amazon.com/jp/free/?gclid=CjwKCAjw56DBBhAkEiwAaFsG-mgBTyzUWsOkBekBYUG2pI6wv-bD6W6VlEozJ49O2s_DL8KrsajlwRoCH1sQAvD_BwE&trk=58ef6015-6519-450b-96ea-258378c321895&sc_channel=ps&ef_id=CjwKCAjw56DBBhAkEiwAaFsG-mgBTyzUWsOkBekBYUG2pI6wv-bD6W6VlEozJ49O2s_DL8KrsajlwRoCH1sQAvD_BwE:G:s&s_kwcid=AL!4422!3!618145042463!p!!g!!aws!18137558856!140477907517&gad_campaignid=18137558856&all-free-tier.sort-by=item.additionalFields.SortRank&all-free-tier.sort-order=asc&awsf.Free%20Tier%20Types=tier%2312monthsfree&awsf.Free%20Tier%20Categories=*all)がないことに気づきました。
いきなり高額請求！って言うのが嫌だったので、

AWSの月間利用料金が 35ドル (日本円で5000円) を超えた際に、  
**Discordに自動通知**を送る仕組みを構築することにしました。

Discordを選択した理由は普段使いしているからであり、
皆さんに置かれましては、SMSやメール、LINEなど
お好きなサービスを利用してください。

**以下から、AIちゃんの代筆**

---

## 🛠 使用AWSサービス

- **AWS Budgets**：予算アラートの作成
- **Amazon SNS**：通知ルーティング
- **AWS Lambda**：通知処理（Webhook POST）
- **IAMロール・環境変数**：セキュリティ・保守性対応

---

## ✅ 全体構成イメージ

```
[ AWS Budgets（5000円超過） ]
              ↓ SNS通知
       [ SNSトピック：budget-alert ]
              ↓ 通知
       [ Lambda関数：NotifyAwsCostToDiscord ]
              ↓ Webhook POST
         [ Discordチャンネル ]
```

---

## ✅ 構築ステップ一覧

---

### 1. Budgetsで予算アラートを作成

1. AWSコンソール → 「請求ダッシュボード」 → 「予算」
2. 「予算を作成」→「コスト予算」を選択
3. 月額：**5000円**
4. 通知タイプ：**実際のコストが100%を超えたとき**
5. 通知先：**SNSトピックを作成（例: `budget-alert`）**

---

### 2. SNSトピックを作成

1. サービス：Amazon SNS
2. トピック名：`budget-alert`
3. タイプ：標準
4. ARNを控えておく（LambdaやIAMで使用）

---

### 3. Lambda関数を作成

- 名前：`NotifyAwsCostToDiscord`
- ランタイム：Python 3.x（例：Python 3.12）
- IAMロール：`AWSLambdaBasicExecutionRole` を付与

#### コード例：

```python
import json
import urllib.request
import os

def lambda_handler(event, context):
    message = event['Records'][0]['Sns']['Message']
    webhook_url = os.environ.get("WEBHOOK_URL")
    if not webhook_url:
        raise Exception("WEBHOOK_URLが環境変数に設定されていません")

    data = {
        "content": f"💸 AWS月額コストが5000円を超えました！\n詳細: {message}"
    }

    headers = {
        "Content-Type": "application/json",
        "User-Agent": "Mozilla/5.0"
    }

    req = urllib.request.Request(
        webhook_url,
        data=json.dumps(data).encode("utf-8"),
        headers=headers,
        method="POST"
    )

    try:
        with urllib.request.urlopen(req) as res:
            print("送信成功:", res.read().decode())
    except Exception as e:
        print("送信失敗:", e)
```

---

### 4. Lambdaに環境変数を設定

- Lambdaの「構成」→「環境変数」→ 「編集」
- 以下を追加：

| キー名         | 値（例）                              |
|----------------|---------------------------------------|
| `WEBHOOK_URL`  | `https://discord.com/api/webhooks/...` |

> Webhook URLのハードコーディングを避け、セキュアに管理！

---

### 5. SNSとLambdaを連携（サブスクリプション）

1. SNSトピック `budget-alert` → 「サブスクリプションを作成」
2. プロトコル：`AWS Lambda`
3. エンドポイント：Lambda関数名を選択

> Lambdaの「アクセス権限」タブで、SNSからの `lambda:InvokeFunction` 許可を確認（自動付与されることもあり）

---

### 6. テスト方法

#### ✅ Lambda単体テスト（コード確認用）

```json
{
  "Records": [
    {
      "Sns": {
        "Message": "テスト送信メッセージです"
      }
    }
  ]
}
```

#### ✅ SNSからのテスト

- SNSトピック → 「メッセージを発行」
- 任意メッセージを入力 → Lambda経由でDiscordに通知されれば成功！

---

いけだコメント：
ここまでが通知機能作成の流れですが、
いけだはテスト通知してみる際に、下記エラーと遭遇したので、対策を実施。
(4. のコードには反映済み）

---
### 7. Cloudflareによる403対策

- DiscordのWebhookはCloudflareのWAFに守られている
- Pythonの `urllib` では `User-Agent` がないと403 + code 1010 に！

```python
headers = {
    "Content-Type": "application/json",
    "User-Agent": "Mozilla/5.0"
}
```
---

いけだコメント：
下記は任意項目です。
所属PJではよくやっていますし、今後改造して失敗したとき、サッと元に戻したかったので。

---

### 8. Lambdaのバージョン管理とエイリアス（任意）

| 操作 | 説明 | 料金 |
|------|------|------|
| バージョン発行 | 関数のスナップショット作成 | 無料 |
| エイリアス作成 | `prod` など名前付きポインタ | 無料 |
| 実行 | 通常通り課金される | 通常のLambda料金 |

---

いけだコメント：
SNSを使って通知を送るとき、
Lambdaなどでコケた場合の再送方法とかを知らなかったので、追加で質問、確認しました。
何も設定しなくても勝手に再送/リトライしてくれるみたいです。

---
### 9. SNSの自動リトライ仕様

| 内容 | 詳細 |
|------|------|
| 最大回数 | 100回 |
| 最大期間 | 23日間 |
| バックオフ | 指数バックオフ（時間ごとに遅くなる） |
| 手動再送 | 不要、自動で再送される |
| 課金 | **再送分もLambda/SNSの実行料金が発生** |

---

いけだコメント：
今は高額になりえるサービスを使っていませんが、
EC2とか、起動しっぱなしで超えた場合、止めるとか、
起動させないことってできるのか、調べてもらいました。

---
### 10. コスト制御と自動制限について（補足）

| やりたいこと | 可能か？ | 方法例 |
|--------------|----------|---------|
| 5000円超過時に通知 | ✅ | Budgets + SNS |
| 自動でリソースを停止 | ✅ | Lambdaで EC2/BATCH などを stop |
| IAM操作を制限する | ✅（自作） | Lambdaで IAM Policy を detach |
| AWSが強制ブロックする | ❌ | 仕様上不可能（通知まで） |

> 個人利用かつ低額なら、**通知だけで十分現実的＆安全！**

---

いけだコメント：
総評として、今回の対応についてと、今後の改造プランまで、まとめてもらってます。
AIちゃんはいい子いい子してくれるので、~~ほめられて伸びたいタイプには~~おすすめです。

---
## ✅ 今回の構成は個人利用でも本番級！

- 安全：Webhookを環境変数で管理
- 安価：Lambda/SNS/Budgetは月額ほぼ無料枠範囲
- 柔軟：通知先（Discord → LINEなど）拡張可能
- 拡張性：月末レポート、週次アラートも可能

---

## 📌 今後の拡張アイデア

- LINE Notify対応
- 月末自動集計レポート
- 通知の装飾（emoji, embed形式など）
- AWS Cost Explorerからサービスごとの内訳取得

**AIちゃん代筆終わり**

## 終わりに
作業はAIちゃん(ChatGPT-4o)と二人三脚しました。
コードやエラーについてはサクッと作れる感じですね。

ただ（当たり前ですが）テキストベースでのやり取りである以上、この記事のようにAWS側のGUIベースの設定がし辛いですね。
いけだは作業イメージを補完するために、参考になるサイトをピックしてもらったりしました。

色々やってみたいこととかあるんですけど、一人だとやる気が出なかったりしたので、引き続きAIちゃんと勉強しながらモノづくりしようかなと思いました。

おわり