ForgeVision Engineer Blog

フォージビジョン エンジニア ブログ

RDS のメンテナンスウィンドウの戻し忘れを防ぐ

こんにちは。どこかへ出張をすると何か忘れたり無くして帰宅する、うっかり者の尾谷です。
よくあるのはモバイルバッテリーとか充電ケーブルですが、大きなものだとパーカーとか鞄を丸ごと忘れたこともあります。

本ブログは、伊丹空港のラウンジで書きました
今回も会社から re:Invent に参加させていただけることになりました。
大変ありがとうございます。素晴らしい体験の代償として、いくつか物理的なものを失うだろうことに覚悟を決めて、渡米して参ります!  

おかげさまで RDS 関連の投稿が好評です!

これまで寄稿した RDS 関係の記事をたくさんの方にご覧いただいているようで、たいへん感謝しております。
味をしめて、もう一本 RDS をテーマに書こうと思います。

techblog.forgevision.com

techblog.forgevision.com

RDS メンテナンスウィンドウ

上記ブログでも記載をしましたが、Amazon RDS は Amazon EC2 と異なり、AWS がデータベースのアプリケーション動作まで補償をしますので、アップデートが強制されます。
アップデートが突然行われると、提供サービスがダウンしたりデータの不整合が起きたりと不具合があるため、RDS にはメンテナンスウインドウが用意されています。

メンテナンスウィンドウは、すべての RDS インスタンスに必須の設定です。週次で設定し、その期間内に AWS によってシステムの変更が適用されます。
メンテナンスウィンドウを使うと、変更やソフトウェアのパッチなどが実行されるタイミングをコントロールできます。  

ユースケース

例えば、CM プロモーションでサイトへのリクエスト増加が見込まれるため、一時的に DB インスタンスのサイズを大きくしたい。という要望があったとします。
 
サイズを変更するときは、EC2 インスタンスの場合だと一度仮想マシンを停止する必要があります。

  1. インスタンスを停止する
  2. インスタンスのサイズを変更する
  3. インスタンスを起動する

サイトが平日日中帯に利用される場合や、社員が利用しているなどの理由で「夜間にやって欲しい。」とリクエストされた場合は、夜間作業を計画するか、Step Functions などを使って自動変更処理を作り込む必要があります。
 
これが EC2 でなく RDS であればメンテナンスウインドウを使って自動で実施させることができますので、日中帯にスケジューリングしておくことができます。

  • メンテナンスウィンドウ:日曜日の夜中 3 時
  • 現在のインスタンスサイズ:db.m6i.large
  • 要望:水曜日から翌週の火曜日まで db.m6i.2xlarge に 1 週間スケールアップ

スケールアップ

上記のケースだと、月曜日か火曜日の日中帯に RDS インスタンスの変更ボタンをクリックし

ページ最下部にある DB インスタンスのメンテナンス期間 を「土曜日」から「火曜日」に変更します。

UTC 時刻で指定するため、日本時間の午前 3 時を指定しています

すぐに適用 のラジオボタンを選択し、[ DB インスタンスを変更 ] ボタンをクリックすると、ダウンタイムなくメンテナンスウィンドウの時間だけが変更されます。

上記設定を行った後で、再度 [変更] ボタンをクリックし、db.m6i.2xlarge を選択したあと

今度は ○ 次回の定期メンテナンス期間中に適用 を選択します。
すると、メンテナンスウィンドウの時間 (水曜日の午前 3 時) のうちに自動でインスタンスサイズが変わります。

ここまでが、RDS メンテナンスウィンドウを利用したインスタンスサイズの変更方法です。 アプリケーションで設定が変更できるのであればスナップショットからもう一台 DB インスタンスを作成してアプリケーションにてエンドポイントを変更する提案も可能ですが、今日のテーマから外れてしまうので、割愛させていただきます。

スケールダウン

スケールダウンをするときも、メンテナンスウィンドウが利用できます。 前述と同じ操作にて、月曜日の営業時間中にスケールダウンをスケジューリング設定します。

翌朝、火曜日の営業時間にインスタンスサイズを確認すると、インスタンスが db.m6i.large に戻っているはずです。  
夜間作業は回避できましたが、残念ながらメンテナンスウィンドウの時刻が「火曜日 午前 03:00」に変わってしまいました。
本作業を行う前はメンテナンスウィンドウの曜日が「日曜日」でしたので、本来なら再度戻さないといけないのですが、この作業はインスタンスのスケールアップ・スケールダウン作業のフローから外れており、戻し漏れる可能性が高いと感じます。  
少なくとも、うっかり者の僕はいつか作業漏れすると思います。

RDS メンテナンスウィンドウの設定を戻す

前置きが長くなりましたが、今日は、このメンテナンスウィンドウがデフォルトの設定から変更されていたら通知する仕組みを実装してみたいと思います。 Lambda を使います。コードは以下の通りです。

import os
import boto3

rds = boto3.client('rds')

def lambda_handler(event, context):

    # 環境変数から DB 一覧の初期値を生成    
    maintenance_db = {}
    num = 1
    while num > 0:
        try:
            maintenance_db.update(
                {
                    os.environ['DB' + str(num)]: os.environ['DB' + str(num) + "_TIME"]
                }
            )
        except:
            break
        num += 1
    print(maintenance_db)
    
    # RDS の一覧を取得
    response = rds.describe_db_instances()
    response = response.get('DBInstances')
    
    for r in response:
        print(r['DBInstanceIdentifier'])
        try:
            if maintenance_db.get(r['DBInstanceIdentifier'],'') == r['PreferredMaintenanceWindow']:
                print('ok')
            else:
                print('ng')
        except:
            print('exception')
    }

環境変数には DB 識別子とデフォルトのメンテナンスウィンドウの時間を入れておきます。

IAM ロールには、AWSLambdaBasicExecutionRole と、RDS の DescribeInstances を登録します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "statement01",
            "Effect": "Allow",
            "Action": "rds:DescribeDBInstances",
            "Resource": "arn:aws:rds:ap-northeast-1:XXXXXXXXXXXXX:db:*"
        }
    ]
}

ng 部分に SNS publish などを指定すれば通知ができます。 この Lambda を EventBridge で日次などで実行します。

使用感

メンテナンスウィンドウが変更されている間は、以下のようなメールが届きます。

件名:

RDS メンテナンスウインドウチェック

本文:

メンテナンスウインドウの時間がデフォルトから変更されております。
prod-otani-rds-01

デフォルト時間: sun:18:00-sun:19:00
現在の設定: tue:18:00-tue:19:30

如何でしたのでしょうか。
忘れっぽい僕には必須のお助け機能のご紹介でした。
今回は E メールの通知を設定しましたが、Chatbot を利用して Slack に通知するのも良いかと思います。
 
最後になりますが、re:Invent は日本からオンラインで参加ができます。
先ほど AWS の CEO である Adam Selipsky の基調講演が終わりましたが、まだ Amazon の CTO Werner Vogels の基調講演がありますので、是非一緒に AWS のアップデートに興奮しましょう!