API Gateway + Lambda で SNS にメッセージ投稿する

  • 38
    Like
  • 0
    Comment
More than 1 year has passed since last update.

以前からかなり欲しかった機能だった API Gateway が us-east-1 等いくつかの region で利用可能になったので、早速使ってみました。

Amazon SNS にメッセージ投稿を行うと、

までは作ってあるので、後は NewRelic 等の監視サービスや独自監視ツールから Amazon SNS にメッセージを投げられれば、Amazon SNS をハブにしていろいろ連携できるようになります。

これまでは、

  • 自前で SNS の API を叩く
    • Webhook しか対応していないサービスは連携不可
  • Zapier 等のハブサービスを利用
    • 品質や応答速度がやや心配(見えない)
  • サーバを立てて HTTP ラッパーを実装する
    • サーバの維持、メンテナンスコストが問題

ぐらいしか選択肢がなかったのですが、API Gateway の登場で、自前でサーバを作らずに HTTP から Lambda を呼び出せるようになったので、AWS のサービスだけで完結できます。

今回は、試しに NewRelic の channel 設定で Webhook を追加し、Alert を Amazon SNS に投げてみます。

Lambda から SNS へ投稿するための Role を作成する

Lambda から Amazon SNS へ Publish するため、Role を新たに作成しておきます。

lambda_basic_execution を作成しているのであれば、既存のものに追加しても OK ですが、分けておいたほうがいいと思います。

自分は lambda_sns_execution として作成しました。
通常の権限に加えて、sns:Publish を有効にしておきます。
resource も特定の Topic を指定してしまったほうが安全でしょう。

IAM_Management_Console.png

Lambda function を作成する

まずは Lambda function の作成です。
package.json や gulpfile.coffee は、これまでのものとほぼ同じなので省略します。

必要な package が aws-sdk になるだけです。

src/index.coffee
topicArn = 'YOUR_TOPIC_ARN'
snsRegion = 'ap-northeast-1'

AWS = require 'aws-sdk'
AWS.config.update region: snsRegion
sns = new AWS.SNS()

exports.handler = (event, context) ->
  params =
    Message: JSON.stringify(default: JSON.stringify(event))
    MessageStructure: 'json'
    Subject: event.condition_name
    TopicArn: topicArn

  sns.publish params, (err, data) ->
    if err
      context.done null, err
      return

    context.done null, 'Post succeeded.'
  return

gulp build でさくっと zip を作成、以下のコマンドで function を作成します。

aws --region us-east-1 lambda create-function \
  --function-name lambda-newrelic-sns \
  --runtime nodejs \
  --role arn:aws:iam::xxxxxxxx:role/lambda_sns_execution \
  --handler index.handler \
  --description 'Send message to Amazon SNS' \
  --timeout 3 \
  --memory-size 128 \
  --zip-file fileb://dist/lambda.zip

Amazon API Gateway から Lambda を呼び出す際、まだ東京リージョンの function は呼び出せませんので、us-east-1 で作成しておきます。

API Gateway を作成する

まずは、API Gateway に行き、必要であればリージョンを N.Virginia に変更しておきます。

API の作成

新規に API を作成します。

API_Gateway.png

API が作成されたので、「Create Resource」を押してリソースを作成します。

API_Gateway.png

/newrelic という endpoint が作成されたので、「Create Method」を押して、POST を選択。

API_Gateway.png

すると、POST メソッドの設定画面になります。
Lambda Function を選択し、region を us-east-1 に、作成した Lambda function 名を入力します。

自動的に function の候補が表示されます。

API_Gateway.png

最後に、以下の様な画面が表示されれば作成完了です。

API_Gateway.png

API のデプロイ

作成した API はデプロイしないと有効になりません。「Deploy API」をクリックし、

API_Gateway.png

適当に stage を作成します。
ここで作成した stage は、API のパスに含まれることになります。

「prod」と入力すると、ttps://xxxxxxxx.us-east-1.execute-api.com/prod/newrelic のようなパスになります。

API_Gateway.png

これで API の利用準備が整いました。
Stages をたどると、API の URL が確認できます。

Lambda function 側の管理画面でも、「API endpoints」を選択すれば確認できます。

API_Gateway.png

NewRelic の設定を行う

NewRelic にログインし、Alerts(beta) から、Notification Channels に行きます。
「New notification channel」から新規の通知チャネルを作成し、Webhook を選択、チャネルの名称及び、API の URL を入力します。

Alerts_by_New_Relic.png

これで、NewRelic からの Alert 情報が POST で API に送信され、それが Amazon SNS に流れるようになります。

補足

現状のままだと、SNS の Message 形式を JSON データにしているため、メールや Slack への投稿時にそのまま JSON データがベタで表示されます。
また、きちんと運用するには Basic 認証等の機構を追加すべきですね。API Gatewayにもその設定がありますので。

NewRelic から投稿されるデータのフォーマットに合わせて、メッセージ内容をうまくカスタマイズすることで、より柔軟な通知が実現できます。

NewRelic から投稿されるデータのフォーマットは、こちらになります。
Customize your webhook payload