うっかりAWS過課金を防げ! EventBridgeとLambdaでDBインスタンス起動時自動クラスチェック&通知:AWSチートシート
AWS活用における便利な小技を簡潔に紹介する連載「AWSチートシート」。今回は「Amazon EventBridge」「AWS Lambda」を利用した、「Amazon Relational Database Service」(RDS)起動時にDBインスタンスクラスをチェックする方法を紹介します。
「Amazon Web Services」(AWS)活用における便利な小技を簡潔に紹介する本連載「AWSチートシート」。今回は、「Amazon EventBridge」「AWS Lambda」を使って「Amazon Relational Database Service」(RDS)の起動を検知し、DBインスタンスクラスをチェックする処理を作ります。
筆者の関わっているシステムでは、本番以外に複数環境が準備されており、適宜テスト時にDBインスタンスクラスを変更することがよくあります。先日、負荷テストのために本番相当に変更したインスタンスを元に戻さずに、そのまま利用し続けてしまい、びっくりする金額(数日だけ、普段の10倍……)になってしまいました。
そんな失敗から、「起動時に普段と違うDBインスタンスクラスかどうかを確認すればいいのでは?」となり、作ってみました(※チェックを起動時にしたのは、DBインスタンスタイプの変更が「利用可」の状態じゃないとできないからです)。
本稿で作成するサービス構成イメージは図1の通りです。
チェックする方法の解説は最小限にとどめておきます。後述しますが、チェックしてそれを通知する方法はいくらでもあるので、皆さんの環境に合った方法をお選びください。
手順
今回は次の手順で、環境を構築します(※対象のRDSは作成済みとします)。
- EventBridgeから実行されるLambda関数を作成する
- Lambda関数にアクセス権限を追加する
- Lambda関数をテストする
- RDSの起動を検知するEventBridgeルールを作成する
- 動作確認
1. EventBridgeから実行されるLambda関数を作成する
AWSにログインし、Lambdaコンソールにアクセスして「関数の作成」をクリックします。
関数の作成画面では、下記表の項目通りに設定して「関数の作成」をクリックします。なお、記載のない項目についてはデフォルトの設定のままで問題ありません。
設定項目 | 設定値 |
---|---|
オプション | 一から作成 |
関数名 | 任意(例では「checkDbInstanceClass」) |
ランタイム | Python 3.10 |
作成したLambda関数の詳細ページが表示されたら、ページの中央にある「コードソース」の欄に記載されているデフォルトのコードを下記のように書き換えて「Deploy」をクリックします。
import boto3 import os client = boto3.client('rds') #環境変数 default_instance_class = os.environ['DEFAULT_INSTANCE_CLASS'] def lambda_handler(event, context): # イベントが発生したインスタンスIDを取得する source_identifier = event['detail']['SourceIdentifier'] # インスタンスをチェックする instance_class = client.describe_db_instances(DBInstanceIdentifier=source_identifier)['DBInstances'][0]['DBInstanceClass'] if instance_class != default_instance_class: print('デフォルトのDBインスタンスクラスではありません') print(source_identifier + 'のDBインスタンスクラス:' + instance_class) print('デフォルトのDBインスタンスクラス:' + default_instance_class)
単純にデフォルトのDBインスタンスクラスじゃない場合にログを出力するだけです。
デフォルトのDBインスタンスクラスについては、デプロイが不要なLambda関数の環境変数に定義しています。よって、環境変数を追加します。「設定」タブをクリック後、左のメニューの「環境変数」をクリックします。環境変数が空なので、「編集」をクリックして追加します。
キー | 値 |
---|---|
DEFAULT_INSTANCE_CLASS | db.t3.medium |
※一番低い「db.t3.small」ではなく、あえて「db.t3.medium」にしている |
いったん、Lambda関数の作成そのものは完成です。しかし、この手順ではアクセス権限がデフォルトの状態なので、RDSへのアクセス権限がなく、追加が必要になります。
2. Lambda関数にアクセス権限を追加する
次に、Lambda関数にRDSへのアクセス権限を追加します。過去の「AWSチートシート」記事はたいてい、事前にロールを作成していますが、筆者のようなうっかりさんは先にコードを書き始めてロール設定を忘れるので、今回は後付けで設定します。
「設定」タブをクリック後、左のメニューの「アクセス権限」をクリックします。デフォルトで作成された実行ロールがあるので、クリックしてロール詳細画面に遷移します。
「許可を追加」「ポリシーをアタッチ」の順にクリックし、許可追加の画面に遷移します。
今回は、RDSの情報取得が必要なので、ポリシー名「AmazonRDSReadOnlyAccess」を検索して許可を追加します。
これでロールの詳細画面に戻るので、許可ポリシー欄に「AmazonRDSReadOnlyAccess」が追加されていれば、成功です。
3. Lambda関数をテストする
Lambda関数をテストするに当たり、EventBridge経由で実行される際の引数を使ってテストします。RDSの起動イベントを検知してLambda関数が呼ばれる場合、引数の「event」には次のような情報が渡ってきます。
{ "version": "0", "id": "12345678-9012-3456-7890-123456789012", "detail-type": "RDS DB Instance Event", "source": "aws.rds", "account": "123456789012", "time": "2023-06-01T04:40:19Z", "region": "ap-northeast-1", "resources": [ "【対象のRDSインスタンスのARN】" ], "detail": { "EventCategories": [ "notification" ], "SourceType": "DB_INSTANCE", "SourceArn": "【対象のRDSインスタンスのARN】", "Date": "2023-06-01T04:40:19.058Z", "Message": "DB instance started", "SourceIdentifier": "【対象のRDSインスタンスのID】", "EventID": "RDS-EVENT-0088", "Tags": { "AUTO_STOP": "true" } } }
「コードソース」画面に遷移し、「Test」ボタンをクリックして、下記表の通りにテストイベントを設定して「保存」をクリックします。
設定項目 | 設定値 |
---|---|
イベントアクションをテスト | 新しいイベントを作成 |
イベント名 | 任意(例では「instance」) |
イベントJSON | 上記JSON |
テストの作成が完了したら、再度「テスト」ボタンをクリックしてテストを実行します。Lambda関数が問題なく実行され、実行結果画面に図8のように出力されていれば、関数の作成とテストは成功です。
4. RDSの起動を検知するEventBridgeルールを作成する
最後にRDSの起動イベントを検知してLambdaを実行するEventBridgeルールを作成します。これまでも「AWSチートシート」の記事でEventBridgeルールは使っていました。しかし使っていたのは定期実行の「スケジュール」のみで、もう1つの「イベントパターンを持つルール」については取り扱っていません。今回はそちらを使います。
EventBridgeダッシュボードを開き「ルール」をクリック後に「ルールの作成」を押します。開いた画面で下記表のように設定し、「次へ」をクリック。
設定項目 | 設定値 |
---|---|
名前 | 任意(例では「DbInstanceClassCheckEvent」) |
説明 | 任意(例では「RDS起動イベント時にDBインスタンスクラスをチェックする」) |
イベントバス | default |
ルールタイプ | イベントパターンを持つルール |
次の画面では下記表のように設定し、イベントパターンを構築して「次へ」をクリックします。
設定項目 | 設定値 |
---|---|
イベントソース | AWSイベント、またはEventBridgeパートナーイベント |
サンプルイベント | 入力不要 |
作成のメソッド | カスタムパターン(JSONエディタ) |
イベントパターン | 下記JSON |
{ "source": ["aws.rds"], "detail-type": ["RDS DB Instance Event"], "detail": { "SourceIdentifier": ["【対象のRDSインスタンスID】"], "EventID": ["RDS-EVENT-0088"] } }
※EventIDについては下記リンク先を参照してください。
次の画面では実行するターゲットを選択するので、1〜3で作成したLambda関数を選び、「次へ」をクリックします。
設定項目 | 設定値 |
---|---|
ターゲットタイプ | AWSのサービス |
ターゲットを選択 | Lambda関数 |
機能 | 1〜3で作成したLambda関数 |
次はタグの設定なので、必要があれば設定して「次へ」をクリックします。最後に内容確認画面になるので、問題なければ「ルールの作成」をクリックし、ルールが追加されたら、構築は完了です。
5. 動作確認
構築は全て完了したので、RDSを起動してみます。テスト時と同様のログが出ていることを「Amazon CloudWatch Logs」で確認します。
これで動作確認は完了です。
後はLambda関数のコードを変更して、エラーログとして出力させてCloudWatchと連携させるもよし、SNSに連携してメールするもよし、直接Slackなどにメッセージ送信するもよし、自由自在です。
RDSクラスタの場合
ここまでは、単独のRDSインスタンスに対して行いましたが、RDSクラスタの場合は勝手が違います。あくまでもRDSクラスタの起動イベントを検知する形になるので以下のように手順が変わります。適宜、組み替えて試してください。
1. Lambda関数の引数に渡される情報が違う
特に注意が必要なのが、「インスタンスID」ではなく「クラスターID」が渡されることです。つまり、直接「describe_db_instances」関数を使えません。
コードの処理手順としては次のリストが妥当だと思います。
- 「describe_db_clusters」関数でクラスタに含まれるインスタンスを取得
- その中からライターインスタンスのインスタンスIDを取得
- 以降は本処理と同様
ライターインスタンスは必ず存在するはずなので、この処理手順でよいはずです。「IsClusterWriter」がtrueのものを探しましょう。
2. EventBridgeルールのイベントパターンが変わる
次のように変わります。
{ "source": ["aws.rds"], "detail-type": ["RDS DB Cluster Event"], "detail": { "SourceIdentifier": ["【対象のRDSクラスターID】"], "EventID": ["RDS-EVENT-0151"] } }
RDSクラスタのEventIDについては下記を参照してください。
RDS以外のサービスでも使える
EventBridgeを使って、RDS起動時にDBインスタンスクラスを確認する方法は、以上です。RDS以外のサービスのイベントをトリガーに処理できるので、試してみてはいかがでしょうか。
筆者紹介
櫻井 智仁(さくらい ともひと)
株式会社システムシェアード システム開発事業部所属。
Javaメインで10数年。お堅い企業からライトな企業までさまざまな案件に従事。ここ数年はクラウド環境のシステムで、負荷テストをしたり、運用してみたり、営業してみたりとマルチに活動。「取りあえず手を動かす」が信条
Copyright © ITmedia, Inc. All Rights Reserved.
関連記事
- DatadogがAWS向け「クラウドコストマネジメント」を提供開始 支出の変化や原因を指標化可能に
日本のユーザーにとって初めて触れることになる(と思われる)新ベンダーや新製品を紹介する本連載。第1回はクラウドコンピューティング向けの監視サービスを提供するDatadogが提供を開始した、クラウドの使用料と監視データを関連付けできる新製品「クラウドコストマネジメント」について紹介する。 - 「急激な円安で心の休まらない日々」――NewsPicksのSREが明かす、AWSコスト20%削減術
2022年10月8日、AWSユーザーグループ「JAWS-UG」が主催する勉強会「JAWS DAYS 2022」がオンラインと全国各地のリアル会場で開催された。本稿では、ニューズピックス SREチームの安藤裕紀氏による講演内容を要約してお伝えする。 - 円安で無視できないAWSコスト増、AWSジャパンが説明する「こうすれば安くなります」
2022年9月16日、AWSジャパンは「今だからこそ考える最適なクラウド活用」というテーマで記者説明会を開催した。円安で利用コスト増への対策として「Cloud Financial Management」や「Savings Plans」などの活用方法を説明した。