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は作成済みとします)。
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へのアクセス権限がなく、追加が必要になります。
次に、Lambda関数にRDSへのアクセス権限を追加します。過去の「AWSチートシート」記事はたいてい、事前にロールを作成していますが、筆者のようなうっかりさんは先にコードを書き始めてロール設定を忘れるので、今回は後付けで設定します。
「設定」タブをクリック後、左のメニューの「アクセス権限」をクリックします。デフォルトで作成された実行ロールがあるので、クリックしてロール詳細画面に遷移します。
「許可を追加」「ポリシーをアタッチ」の順にクリックし、許可追加の画面に遷移します。
今回は、RDSの情報取得が必要なので、ポリシー名「AmazonRDSReadOnlyAccess」を検索して許可を追加します。
これでロールの詳細画面に戻るので、許可ポリシー欄に「AmazonRDSReadOnlyAccess」が追加されていれば、成功です。
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のように出力されていれば、関数の作成とテストは成功です。
最後に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関数 |
次はタグの設定なので、必要があれば設定して「次へ」をクリックします。最後に内容確認画面になるので、問題なければ「ルールの作成」をクリックし、ルールが追加されたら、構築は完了です。
構築は全て完了したので、RDSを起動してみます。テスト時と同様のログが出ていることを「Amazon CloudWatch Logs」で確認します。
これで動作確認は完了です。
後はLambda関数のコードを変更して、エラーログとして出力させてCloudWatchと連携させるもよし、SNSに連携してメールするもよし、直接Slackなどにメッセージ送信するもよし、自由自在です。
ここまでは、単独のRDSインスタンスに対して行いましたが、RDSクラスタの場合は勝手が違います。あくまでもRDSクラスタの起動イベントを検知する形になるので以下のように手順が変わります。適宜、組み替えて試してください。
特に注意が必要なのが、「インスタンスID」ではなく「クラスターID」が渡されることです。つまり、直接「describe_db_instances」関数を使えません。
コードの処理手順としては次のリストが妥当だと思います。
ライターインスタンスは必ず存在するはずなので、この処理手順でよいはずです。「IsClusterWriter」がtrueのものを探しましょう。
次のように変わります。
{
"source": ["aws.rds"],
"detail-type": ["RDS DB Cluster Event"],
"detail": {
"SourceIdentifier": ["【対象のRDSクラスターID】"],
"EventID": ["RDS-EVENT-0151"]
}
}
RDSクラスタのEventIDについては下記を参照してください。
EventBridgeを使って、RDS起動時にDBインスタンスクラスを確認する方法は、以上です。RDS以外のサービスのイベントをトリガーに処理できるので、試してみてはいかがでしょうか。
株式会社システムシェアード システム開発事業部所属。
Javaメインで10数年。お堅い企業からライトな企業までさまざまな案件に従事。ここ数年はクラウド環境のシステムで、負荷テストをしたり、運用してみたり、営業してみたりとマルチに活動。「取りあえず手を動かす」が信条
DatadogがAWS向け「クラウドコストマネジメント」を提供開始 支出の変化や原因を指標化可能に
「急激な円安で心の休まらない日々」――NewsPicksのSREが明かす、AWSコスト20%削減術
円安で無視できないAWSコスト増、AWSジャパンが説明する「こうすれば安くなります」Copyright © ITmedia, Inc. All Rights Reserved.