AWS LambdaのパラメータをDynamoDBで管理する

こんにちは、AWS担当のwakです。前回に続きAWS Lambdaの話をします。

f:id:nurenezumi:20160127153847j:plain

【インデックス(予定)】

  1. CloudWatchの監視結果をSlackに流す(AWS Lambdaバージョン)
  2. AWS LambdaでWebサイトの死活監視を行ってSlackに結果を流す
  3. AWS LambdaのパラメータをDynamoDBで管理する(今回)
  4. CloudWatchの監視結果をTwilioに流して電話をかける
  5. SlackからEC2インスタンスを起動・停止するコマンドを作る

パラメーターをDynamoDBに入れて管理する

前回までの記事でCloudWatchの監視結果やWebサイトの死活監視の結果をSlackへ通知するようなコードを書きましたが、これらで使っているパラメーターはコードの中に直接埋め込んでいました。この改善を図るためDynamoDBを使いたいと思います。レコード数が十分少ない場合は検索は単純な処理で可能ですので、詳しくは補足記事を参照してください。DynamoDBでは課金が発生しますが、後述する通り通常は無料利用枠におさまるため、無料~極めて安価に利用できます。

登録するパラメーターを決める

パラメーターを用意します。Slack連携を行うために必要な情報を書いてみました。

  • incoming webhooksのエンドポイント
  • 通知先チャンネル(正常時/エラー時)
  • botの名前
  • アイコン

これらをまとめたものに一意の名前(ID)を振ってDynamoDBで管理することにします。

DynamoDBの準備

テーブルを作成する

適当な名前でDynamoDBにテーブルを作ります。プライマリキー名は文字列型のrecordkeyとしました。keyのような予約語を使うこともできますが、コードが少しだけ面倒になります。

レコードを入れる

コンソールから手動でレコードを投入します。直接JSON形式で書いて保存してしまいます。

{
  "recordkey": "slack",
  "type": "slack",
  "channel": {
    "error": "@notification_error",
    "ok": "notification_ok"
  },
  "emoji": ":ghost:",
  "endpoint": "/services/xxxxxxxxx/xxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxxx",
  "name": "MYSLACKBOT"
}

このテーブルからrecordkeyslackのレコードを検索すればSlack通知を行うためのパラメーターを取得することができるようになるわけです。もちろんslack2GoogleAPIのようなレコードがあっても構いません。

Lambdaの準備

以降の操作はLamndaで行います。

ロールを作成する

Lambda関数はそれぞれの関数に割り当てられたIAMロール*1の権限で実行されます。これにより、APIキーの管理やローテーションといった面倒な作業は必要なくなります。

今回のLambda関数はDynamoDBを読み込むため、DynamoDBへのアクセス権限を持ったロールを作成して割り当てる必要があります。幸いテンプレートが用意されているので、コンソールから選択して作成するだけで済みます。

目的のレコードを検索する

Slackのパラメーターを読み出すには、recordkey = 'slack'で検索をすれば良かったのでした。これで成功時には必ず1件のレコードが取得できるはずです。

var param = {
    TableName : "helloLambda2",
    KeyConditionExpression : "recordkey = :val",
    ExpressionAttributeValues : {":val" : "slack"}
};
dynamo.query(param, function(err, data) { ... }

読み込みが失敗(権限が足りない、テーブルが見つからない、期待したレコードが見つからないなど)した場合はその場でエラーを返し、成功した場合は続けて任意の処理を行ってSlackへ通知するようにすれば終わりです。

dynamo.query(param, function(err, data) {
    if (err) { context.fail(err); }
    else if (data.Count === 0) { context.fail("record not found"); }
    else {
        var slackParameter = data.Items[0]; // 登録したのと同じ形のオブジェクト
        // do something
        context.succeed({result : "ok", message : "..."});
    }
});

料金見積もり

DynamoDBではいくつかの名目で料金が発生しますが、無料利用枠として、1アカウントあたり

  • ストレージ……25GB
  • プロビジョニングした読み込み/書き込み容量……25ユニット

が用意されています。EC2やRDSの無料利用枠はサインアップ(アカウント作成)後から1年間限定の特典なのですが、DynamoDBではその後もずっと継続して与えられます。この程度(レコード数100未満、1件のレコードは1KB未満)であれば、この無料利用枠に十分おさまる、すなわち完全に無料で使えると見て良いでしょう。また、読み込み/書き込み容量が無料枠を超過したとしても、それぞれ1ユニット(つまり秒間1回ずつの読み込みと書き込みが可能)で十分ですから、料金は最低額の約$0.67/月となります。

*1:IAMユーザーとIAMロールはそれぞれ別物です。IAMユーザーは人間がブラウザ経由で操作する・アプリケーションがAPIキーを使って操作するためのユーザーアカウントです。IAMロールはAWS内部のサービスが他サービスを利用するための権限のセットです