SMSがリソース不足で届かなくなる前に教えてくれるCloudWatch AlarmをCloudFormationで書いてみる

2019.03.15

今回作成するもの

Amazon SNSのSMSの”Account spend limit”がある一定の値(任意の値)を超えた時点でアラートを出すCloudWatch Alarmの設定をAWS CloudFormationテンプレートを用いて行います。

何で作ったのか

Amazon SNSのSMS通知を利用する機会があったのですが、Amazon SNSのSMSにはスパムなどで乱用されないように(またはできないように)Account spend limitの値を設定する必要があります。

この”Account spend limit”はデフォルトでは$1に設定されており、 上限の引き上げにはAWSサポートへ問い合わせる必要があります。

つまり、上限の引き上げに3日程かかるので、上限に引っかかる前に通知されるようにアラートを設定する必要がありました。

Account spend limitの上限に達すると、 エラーなども特に出すことなく静かにSMSが届かなくなります。 SNS送信ログを辿ればAccount spend limit achievedのメッセージが読み取れますが、上限引き上げに時間を要するので 届かなくなる前に知りたいですよね。

注意

Amazon SNSのSMSとややこしい書き方をしていますが、この”Account spend limit”はAmazon SNSのSMSのみに 対するリミットです。他の送信方法、例えばEmailなどはここには当てはまりません。

必要なもの

  • AWS CLI v1.16.87

作成するリソース

  • CloudWatch Alarm
  • 通知先のSNSトピック

テンプレート全文

シンプルに二つのリソースを定義しています。

AWSTemplateFormatVersion: '2010-09-09'
Description: Custom Cloudwatch Alarm
Parameters: 
  TestSNSSubscriber:
    Type: String
    Default: 'example@email.com'
Resources:
  TestAlarmTopic:
    Type: AWS::SNS::Topic
    Properties:
      Subscription:
      - Protocol: email
        Endpoint: !Ref TestSNSSubscriber

  Alarm:
    Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmDescription: "DEMO Custom Cloudwatch Alarm"
      AlarmActions:
        - !Ref TestAlarmTopic
      ComparisonOperator: GreaterThanOrEqualToThreshold
      EvaluationPeriods: 1
      MetricName: SMSMonthToDateSpentUSD
      Namespace: AWS/SNS
      Period: 300
      Statistic: Maximum
      Threshold: '0.7'

Parametersを設定

テンプレート内で利用できるグローバル変数のようなものです。 ステージ環境別にテンプレートの再利用をしたいときなど、便利です。

今回はアラートの通知先のメールアドレスを記述しています。

AWSTemplateFormatVersion: '2010-09-09'
Description: Custom Cloudwatch Alarm
Parameters: 
  TestSNSSubscriber:
    Type: String
    Default: 'example@email.com'

SNSトピックを設定

アラートを通知するのにAmazon SNSを利用するため、 通知先のトピックを作成します。 Protocolにはemailまたはsmsを設定します。

Resources:
  TestAlarmTopic:
    Type: AWS::SNS::Topic
    Properties:
      Subscription:
      - Protocol: email
        Endpoint: !Ref TestSNSSubscriber

通知

SMSを選択した場合

Emailを選択した場合

どちらも英語ですが、Emailのほうが詳細な情報が送られてくるのでより有用そうです。

カスタムアラームを設定

SMSの利用料がAccount spend limitのある一定の値に達した時点で教えてくれるようにアラートを設定します。 今回はAccout Spend Limit がデフォルトの$1の場合を想定しているので”0.7”(0.7USD)をThresholdに設定しました。

  • AlarmActions: 通知先のトピックを指定
  • ComparisonOperator: 条件式の演算子を表します。
  • MetricName: SMSMonthToDateSpentUSDを利用します。詳しくはこちらをご参照ください。
  • Period: 条件式の判定が行われる間隔を設定します。今回は5分に設定しています。
  • Statistic: SMSMonthToDateSpentUSDメトリクスの有効な統計はMaximumのみなので適応します。
  • Threshold: ComparisonOperatorで設定した条件式の値になります。今回は0.7としています。
Alarm:
    Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmDescription: "DEMO Custom Cloudwatch Alarm"
      AlarmActions:
        - !Ref TestAlarmTopic
      ComparisonOperator: GreaterThanOrEqualToThreshold
      EvaluationPeriods: 1
      MetricName: SMSMonthToDateSpentUSD
      Namespace: AWS/SNS
      Period: 300
      Statistic: Maximum
      Threshold: '0.7'

デプロイ手順

テンプレートがかけたらスタックを作成しましょう。

デプロイ

スタックを作成するので少し時間がかかります。

aws cloudformation deploy --template-file /path_to_template/template.json --stack-name my-new-stack 

成功した場合

成功した場合、以下のメッセージが表示されます。

Waiting for changeset to be created..
Waiting for stack create/update to complete
Successfully created/updated stack - <スタック名>

コンソールへログインしてリソースを確認しましょう。 思った通りにリソースが作成されていたらおめでとうございます。

失敗した場合

エラーになった場合は一度スタックを削除して、SAMテンプレートを修正してもう一度上げ直す流れになります。 ただし、一度でもスタックの作成に成功していればロールバックされるので、毎度スタックを削除する必要はありませんので、 一度空のテンプレートでスタックを作成して、そのスタックに対して更新をかけていく方法が便利です。

後片付け

以下のコマンドでスタックを削除します。

aws cloudformation delete-stack --stack-name <スタック名>

まとめ

Account spend limitを超過するとエラーなども特に出すことなく静かにSMSが届かなくなります。

思わずバグ・・?と思ってしまう挙動です。つい先ほどまで動いていたプログラムが急に動かなくなると焦りますよね。 心理的負荷を軽減するためにもSMSを利用する際にはアラームを設定しておくことをおすすめします。

参考リンク