AWS Budgetsでアラート設定する～90年代の隠しサイト…？

AWS Budgets から Amazon SNSで通知を発砲するには、SNS トピックに AWS Budgets への許可アクセスポリシーを設定しないといけない。そのアクセスポリシーのコピー時に衝撃をうけたので、その部分を書きたいがために記事にする。

# 1.AWS Budgets
➤ Budgets 【意味】：予算(額), 経費

英単語の意味そのまま、予算管理サービス。
一定期間の予算を設定しておき、以下のような場合にE メールや SNS でアラート通知を受け取れるように設定できる。
- コストと使用状況が設定した予算のしきい値を超過あるいは超過しそうになった
- Reserved Instance や Savings Plans の使用率やカバレッジが設定したしきい値を下回った

AWS Budget Actions では、アラート発生時に以下のようなアクションを設定することが可能。
- IAM ポリシーの適用、
- サービスコントロールポリシー (SCP) のアタッチ、
- 特定の Amazon EC2 インスタンスまたは Amazon RDS インスタンスの停止


これにより、自動もしくは承認を受けてアクションを実行し、望まないコストの無駄を減らすことができる。 

# 2.予算作成と SNS トピックの関連付け

右上のIAMユーザ名をクリック⇒請求ダッシュボードから Budgets をクリックし、「予算を作成する」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/cd7d6c18-d1a1-f8c3-9188-0023039017ff.png)

予算タイプの選択では、一番上の「コスト予算 - 推奨」を選択して次へ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/77d0a631-2a75-921b-09c1-155340ffb814.png)

予算名：何か適当に名前を付ける
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/adb1334f-12d2-1972-2eb4-858220c86122.png)
「間隔」は以下から選択できる。
- 日別
- 月額
- 四半期単位
- 年単位

今回は月額を選択する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/d035614a-0032-c112-ae46-9de2ae2f3b14.png)
開始月は現在の日付が自動で選択されているのでそのままにする。
予算設定方法は以下から選択できる。
- 固定
- 計画済み
- 自動調整

今回は一番簡単な「固定」を選択する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/5d079277-31db-aa21-9734-7148bcbe13c1.png)
予算額は USD で設定する。
画面右のグラフを見ると私は月に多い時で\3,000ほど利用しているので、 USD に換算して35 USD くらいに予算を設定したらよさそうと判断し、35.00 USD にした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/b550bdbf-23a5-1f88-7c7a-71315ebed3b5.png)

Budgets scope を設定する。Scope オプションは以下から選択できる。
- All AWS services (Recommemded)
- Filter specific AWS cost dimensions

今回はAWS アカウント全体の利用料を管理したいので「All AWS services (Recommemded)」を選択する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/6960340b-5deb-4ea6-c7e3-a90afc40711b.png)

詳細オプションでは以下項目を選択できる。
- 非ブレンドコスト
  - 支払う金額そのまま表示する。例えば1年に一度 Reserved Instance を購入する際は一時的にドカンと請求額が大きくなるが、そのまま表示される。
- 償却コスト
  - 請求金額をならして表示する。例えば1年に一度 Reserved Instance を購入する際は一時的にドカンと請求額が大きくなるが、その請求額を年間の利用料で平均して日々のコストに分配して表示する。
- ブレンドコスト
  - Organizations の一括請求 (コンソリデーティッドビリング) 全体の平均使用コストを反映する。AWS Organizations の一括請求機能を使用する場合は、ブレンドコストを使用してコストを表示できる。

今回は「非ブレンドコスト」を選択する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/131f1ba2-a8cd-6d2f-afb2-ed40e2f5c0c3.png)

サポートされている請求タイプでは、以下項目が選択できる。デフォルトでチェックが入っているものは（default）と書いている。
- 返金
- クレジット
- 前払いの予約料金（default）
- 定期的な予約料金（default）
- そのほかのサブスクリプションコスト（default）
- 税金（default）
- サポートの料金（default）
- 割引（default）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/c778a5a9-7074-5c46-678c-4a294af4bbd9.png)

例えば私は AWS イベント参加時にクレジットをもらって自分の AWS アカウントに反映させているので、以下のように「クレジット」を選択すると、クレジットが消費されて実際には請求されなかった分は表示されなくなる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/9477d99a-f6ef-5584-5f26-7d956e69aa6c.png)
今回は、クレジットや割引がない状態でリソースを利用したらどれくらいの金額になっているのか知りたいと思ったので、以下のようにチェックして進める。
- 前払いの予約料金（default）
- 定期的な予約料金（default）
- そのほかのサブスクリプションコスト（default）
- 税金（default）
- サポートの料金（default）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/1d5a5de6-a445-51d3-258b-873c7a365000.png)

アラートの設定画面になる。「アラートのしきい値を追加」をクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/857bab93-fade-c764-6db4-bee33998b05c.png)

今回は実際にアラート通知されることを確認したいので、1つ目のアラートのしきい値は「絶対値」の「実績」ですごく少なめに 0.5 USD にする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/59b7b767-3c87-7b18-9149-e264432a52d8.png)

「Eメールの受信者」にメールアドレスを入力すれば、Amazon SNS と連携しなくてもメール通知が可能だが、今回は Amazon SNS を使ってメール通知をおこなう手順を記載する。
「Amazon SNS アラート」を展開すると以下のように「Amazon SNS ARN を選択」という項目がある。この空欄の下に「アクセス許可」というリンクがあるので、ここをクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/3230ecb4-3afb-956f-e9e7-9aa559d00241.png)

### ここが書きたかっただけ
以下のように黒い画面が表示されるが、黒い部分を選択すると…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/cf3a56db-e28e-4f19-d6ff-07bc1d5eeec2.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/91d5e663-a8ff-079a-33c6-6210af3fa640.png)
90年代の隠しサイトのように、ポリシーステートメントが書かれているのがわかる。

コピーすると以下の内容になっている。`"Resource"` の `"<insert-ARN-here>"` に、メール通知をさせる SNS のARN を入れて、SNSのアクセスポリシーに設定する必要がある。このステートメントはコピーしておく。

```json
{
  "Sid": "AWSBudgets-notification-1",
  "Effect": "Allow",
  "Principal": {
    "Service": "budgets.amazonaws.com"
  },
  "Action": "SNS:Publish",
  "Resource": "<insert-ARN-here>"
}
```

Budgets のブラウザタブは開いたままで、Amazon SNS の設定画面を別タブで開く。

# 3.ここからいったん Amazon SNS の設定
「トピックの作成」をクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/75aa0c10-92f8-f5bb-bac0-a451e6dcf74e.png)

タイプは「スタンダード」を選択し、適当にトピックの名前と表示名をつけ、あとはデフォルト値でトピックを作成する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/8082c10c-bc5b-c67d-da42-4bd04a527fda.png)

トピックが作成できた。次に「サブスクリプションの作成」をクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/08f03df6-9a36-374b-56fe-24f3ad8249d8.png)

プロトコルは「Eメール」、エンドポイントに通知を受信したいメールアドレスを入力して「サブスクリプションの作成」をクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/ea8d823b-6b41-5850-94e2-a4b2f9186786.png)

以下のようにサブスクリプションが作成できた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/77e1cc84-43c4-7d9b-6305-328f66365b97.png)

メールが届いているはずなので、メールボックスを確認する。
**ここで、「Confirm Subscription」はクリックしない！！！
右クリックし、リンクをコピーする。** ※理由は後述
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/fd5ed676-d334-853d-7090-22ae54f68269.png)

保留中の SNS サブスクリプションを選択し、「サブスクリプションの確認」をクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/2d920614-27d2-efcf-5d95-861647c7d5c9.png)

先ほど「Confirm Subscription」を右クリックしてコピーしたURLを貼り付け、「サブスクリプションの確認」をクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/47aaf9f9-f6c4-a659-3d10-d07423c9c909.png)

サブスクリプションのステータスが「確認済み」になればOK。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/e08a3082-65c9-a495-8f32-bb4df4ee613f.png)

### ※「Confirm Subscription」をクリックしてはいけない理由
理由は、ここで「Confirm Subscription」をクリックしてしまうと、今後アラートメールが届いたときのメール本文中にある「Unsbscribe」のリンク先に飛ぶことでいとも簡単にメール通知を止めてしまうことができてしまうから。うっかりメール通知を止めてしまうのは（特に本番運用では）避けたい。
上記のようにURLをコピーして貼り付ける方法でサブスクリプションの確認をすると、アラートメールが届いたときのメール本文中にある「Unsbscribe」のリンクをクリックしてもメール通知が止まらないようにできる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/d5266d32-8cdd-0363-7be4-4b5b42f3fb40.png)
「Unsbscribe」のリンクを間違ってクリックしても↑↑↑こうなる。

SNS トピックの ARN をここでコピーしてメモしておく。メモしたら、トピックを編集するので「編集」をクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/947309b0-4179-eb68-853e-f6c2bd349de6.png)

アクセスポリシーを編集する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/5a6ec046-2d96-4099-ad17-70da705969bb.png)

ここで、~~90年代の隠しサイト~~ Budgets の Amazon SNS アラートの「アクセス許可」をクリックして黒い画面でコピーしたポリシーステートメントの出番。

```json:もとのアクセスポリシー
{
  "Version": "2008-10-17",
  "Id": "__default_policy_ID",
  "Statement": [
    {  """""""""""""""""""""この行から"""""""""""""""""""""
      "Sid": "__default_statement_ID",
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Action": [
        "SNS:GetTopicAttributes",
        "SNS:SetTopicAttributes",
        "SNS:AddPermission",
        "SNS:RemovePermission",
        "SNS:DeleteTopic",
        "SNS:Subscribe",
        "SNS:ListSubscriptionsByTopic",
        "SNS:Publish"
      ],
      "Resource": "arn:aws:sns:ap-northeast-1:xxxxxxxxxxxx:Emi_BudgetsAlert",
      "Condition": {
        "StringEquals": {
          "AWS:SourceOwner": "xxxxxxxxxxxx"
        }
      }
    } """""この行まで削除して、コピーしたステートメントに置き換える"""""""""
  ]
}
```

↓↓↓

```json:修正後
{
  "Version": "2008-10-17",
  "Id": "__default_policy_ID",
  "Statement": [
    { """""""""""""""""""""この行から"""""""""""""""""""""
  "Sid": "AWSBudgets-notification-1",
  "Effect": "Allow",
  "Principal": {
    "Service": "budgets.amazonaws.com"
  },
  "Action": "SNS:Publish",
  "Resource": "arn:aws:sns:ap-northeast-1:xxxxxxxxxxxx:Emi_BudgetsAlert"
} """""""この行まで置換した。"Resource"にはコピーしておいたSNSトピックのARNを入れる"""""""

  ]
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/d8991887-6e41-137b-984f-71e82d3f29cd.png)
インデントはずれていてもいいので、「変更の保存」をクリックする。
保存すると、インデントは直っている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/c8fd4930-dbdd-5a36-d30e-5940ad7281cb.png)

# 4.ここからBudgets の設定に戻る

開いていた Budgets のブラウザタブに戻り、Amazon SNS ARN を選択の空欄に、作成した SNSトピックのARN を入力する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/cf5a5212-e796-f99a-e2c0-c67efe596272.png)

アラートの確認をするだけならアラート一つでもいいが、私はいくつかアラートのしきい値を設定したいので「アラートのしきい値を追加」をクリックしてアラートを追加する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/49bafc93-c16e-c7ce-7a52-f8e44e87327d.png)
アラートは7個追加した。次へ。

ここで、しきい値を超えた時のアクションを設定できる。EC2 インスタンスの停止など設定したい場合はここで設定すればよいが、今回は SNS アラートだけでよいのでこのまま次へ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/9845f68d-8ddc-2ea2-1d15-7f26746f9650.png)

設定値の確認画面になる。「予算を作成」をクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/ffba7d19-7490-8a54-d5f3-4e542bdba32f.png)

予算が作成できた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/812dfd71-e64f-a37c-328e-f42b2f7f6b5d.png)

今回は予算作成時点でしきい値をいくつか超過しているので、超過している分だけアラートメールが来ている。
※「SNS Topic Verified!」メールは、設定したしきい値の分だけSNS トピックを設定したので、その分の登録完了メールが来ている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/98a73ac8-ec7b-253d-9c91-0a643bdd809e.png)

Budgets の画面からも、超過しているしきい値で警告状態になっているのがわかる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/bd56baa5-ef90-a6eb-405b-c69ba09225a0.png)


# 参考

https://aws.amazon.com/jp/aws-cost-management/aws-budgets/

https://blog.serverworks.co.jp/sns-remove-unsubscribe-link

https://blog.serverworks.co.jp/aws-budgets-actions

https://blog.serverworks.co.jp/aws-budgets-actions2

https://blog.serverworks.co.jp/aws-budgets-new-console-failed-to-load