レガシー・マイグレーションのノウハウ&ドゥハウ。 計画時サービスからメインサービスまでシステムズの業務をご案内。

システムズのマイグレーションコラム

Vol.25 AWS DBマイグレーション時のコスト削減アプローチ

2020.04.16

AWSで実践!DBマイグレーション時のRDS利用コスト削減

レガシーシステムのマイグレーションでは、移行先の本番環境の準備はもちろんのこと、開発環境用に、例えばオンプレミスの場合など、新たにサーバーを購入する場合があります。マイグレーションが完了した後、オンプレミスの場合は、開発環境用に購入したサーバーへの投資コストが、マイグレーション費用の中にかかってきています。

クラウド環境へのマイグレーションの場合も、本番環境と開発環境の準備までは同じですが、マイグレーションが完了した後、開発環境用に準備したクラウド基盤は利用契約を解除することで、オンプレミスのような、サーバーの保有コストによる圧迫から脱却することが可能となります。

さらに、AWSが提供するクラウドサービスでは、移行先の開発環境の利用中においても、従量課金型サービスであれば、使用しない時間帯を設定することで、コスト削減につなげることができるようになります。

今回の記事では、AWSのサービス「CloudWatch Events(イベントのスケジュール)」と、AWS Lambda(起動・停止処理)を組み合わせた、自動起動・停止の設定方法をご紹介します。

はじめに

AWSへのDBマイグレーションの際には、
本番環境以外にも、ステージング環境などに検証・テスト用のRDSインスタンスを構築する場合が多いので、利用コストがその分多くかかります。

EC2やRDSなどの従量課金のサービスでは、
開発環境や検証環境など、24時間稼働する必要がないインスタンスは、
夜間は自動的に停止する事で大幅にコストカット出来ます。

本記事では、RDSインスタンスの自動起動・停止の設定方法についてご紹介します。

概要

AWSでRDSインスタンスの起動・停止スケジュールを行うには、
以下のサービスを組み合わせて実現します。
・CloudWatch Events(イベントのスケジュール)
・Lambda(起動・停止処理)

概要

CloudWatch Eventsは、cronのようにスケジュールしたタイミングでイベントを発生させて、
Lambdaなど他のAWSサービスを任意のタイミングで呼び出す事ができます。

RDSインスタンスを「平日の8時に起動するイベント」と「起動用のLambda」、
「20時に停止するイベント」と「停止用のLambda」をそれぞれ作成します。

Lambdaは、JavaやPython、GO、NodeJSなどの言語で処理を記述できますが、
今回は、Pythonで作成していきます。

準備

LambdaがRDSを操作する権限を付与するために、IAMロールが必要になりますので、
先にそちらを準備していきます。

IAMポリシーの作成

まずは、IAMのポリシーを作成します。

IAMロールとIAMポリシーの用語の違いは以下です。

・IAMポリシー(Policy)
「AWSリソースにアクセスするための権限設定」で、ユーザやロールにアタッチされて使用される。
・IAMロール(Role)
「AWSリソースに付与するもの」で、いくつかのIAMポリシーをグルーピングできる。

ポリシーに「インスタンスの参照」「インスタンスの起動」「インスタンスの停止」という権限だけを
設定しておくことで、誤って他の操作(削除など)を行ったり、意図しない事故を防ぐ事ができます。

IAMの画面から、「ポリシー」を選択して、「ポリシーの作成」を押します。

IAMポリシーの作成

「JSON」タブを選択して、直接ポリシーをJSONで入力します。

IAMポリシーの作成
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditorStartStopDB",
            "Effect": "Allow",
            "Action": [
                "rds:DescribeDBInstances",
                "rds:StopDBInstance",
                "rds:StartDBInstance"
            ],
            "Resource": "arn:aws:rds:*:*:db:*"
        }
    ]
}

名前と説明を入力して、「ポリシーの作成」を押します。

IAMポリシーの作成
IAMロールの作成

次は、作成したポリシーをロールと関連づけます。
ロールのメニューから「ロールの作成」を押します。

IAMロールの作成

AWSサービスから、「Lambda」を選択して「次のステップ:アクセス権限」を押します。

IAMロールの作成

先ほど作成したポリシーを探してチェックし、次に進みます。

IAMロールの作成

タグは任意です。そのまま進めても大丈夫です。

IAMロールの作成

ロール名と説明を入力して、「ロールの作成」を押します。

IAMロールの作成

Lambdaとイベントの作成

次は、Lambdaの作成と、
同じ画面からCloudWatch Eventsも作成と関連づけを同時に行っていきます。

Lambdaのメニューから、「関数の作成」を押します。

Lambdaとイベントの作成
停止設定
関数作成

Lambdaを作成する際、ブループリントから雛形を作成できますが、
今回は事前にソースを用意しているので「一から作成」を選択します。

Runtimeは「Python 3.x」、「実行ロールの選択または作成」から、
このLambdaに付与するロールを選択します。

関数作成

「既存のロールを使用する」で、先ほど作成したロールを選択して、
「関数の作成」を押して進みます。

関数作成

関数コードの中に、下記ソースをコピーして上書きます。

import boto3

# RDSインスタンスDB識別子のリスト
rds_ids = [
    'instanceA',
    'instanceB'
    ]

def lambda_handler(event, context):
    rds = boto3.client('rds')
    # リストの要素が0の場合は何もしない
    if len(rds_ids) == 0:
        print('対象インスタンスがありません。')
    else:
        for i in rds_ids:
            response = rds.describe_db_instances(DBInstanceIdentifier=i)
            rds_status = response["DBInstances"][0]["DBInstanceStatus"]
            print(rds_status)
            # ステータスが「stopped」の場合
            if rds_status == "stopped":
                print('既にインスタンスが停止しています。:' + str(i))
            elif rds_status == "available":
                rds.stop_db_instance(DBInstanceIdentifier=i)
                print('インスタンスを停止しました。:' + str(i))
            else:
                # それ以外の場合
                print('ステータスが変更途中です。:' + str(i))
    return 'インスタンスの停止処理を終了します。'

例えば、下図のRDSインスタンスを停止したい場合。

関数作成

ソース上部のリストに、
停止したいインスタンスのDB識別子をカンマ区切りで入力します。

関数作成
関数のテスト

画面右上の「保存」を押してから、隣の「テスト」でファンクションを動かしてみます。

関数のテスト

イベント名を適当に入力して、「作成」を押します。

関数のテスト

その後、再度「テスト」を押します。
正常に実行できれば、下図のように緑色の画面で「実行結果:成功」と表示されます。

関数のテスト

RDSの画面で確認すると、2つとも停止中のステータスになっていました。

関数のテスト
実行のスケジューリング

次は、平日20時に実行してくれるようにスケジューリングの設定を行います。

Lambdaの画面で「トリガーを追加」を押します。

実行のスケジューリング

「CloudWatch Events/EventsBridge」を選択します。

実行のスケジューリング

「新規ルールの作成」を選択して、次のように入力します。
※平日 月₋金 20時に停止する場合

cron(0 11 ? * MON-FRI *)

CloudWatch Eventsのcron式は、協定世界時(UTC)で入力するため、
日本標準時(JST)との差は +9時間 になるため注意が必要です。

Eventをトリガーする時間は、適宜変更して利用してください。

実行のスケジューリング

全て入力したら「追加」を押します。

実行のスケジューリング

一番下の「CloudWatch Events/EventBridge」が
「有効」になっている事を確認して設定は完了です。

起動設定

起動設定も停止の時と基本的には同じ流れで作成していきます。
Lambdaのソースコードと、cron設定の2点が異なります。

関数作成
関数作成
関数作成
import boto3

# RDSインスタンスDB識別子のリスト
rds_ids = [
    'oracle11g',
    'postgres11'
    ]

def lambda_handler(event, context):
    rds = boto3.client('rds')
    # リストの要素が0の場合は何もしない
    if len(rds_ids) == 0:
        print('対象インスタンスがありません。')
    else:
        for i in rds_ids:
            response = rds.describe_db_instances(DBInstanceIdentifier=i)
            rds_status = response["DBInstances"][0]["DBInstanceStatus"]
            print(rds_status)

            # ステータスが「available」の場合
            if rds_status == "available":
                print('既にインスタンスが起動しています。:' + str(i))
            elif rds_status == "stopped":
                # string 形式で RDS 受け取る
                rds.start_db_instance(DBInstanceIdentifier=i)
                print('インスタンスを起動しました。:' + str(i))
            else:
                # available や stopped 以外の場合
                print('ステータスが変更途中です。:' + str(i))
    return 'インスタンスの起動処理を終了します。'
関数のテスト

テストしていきます。

関数のテスト

インスタンスが「起動中」になりました。

関数のテスト
実行のスケジューリング

トリガーを追加していきます。

実行のスケジューリング

※平日 月₋金 8時に起動する場合

日本標準時(JST)の月曜日 8:00 – 金曜日 8:00 は、
協定世界時(UTC)では、日曜日 23:00 – 木曜日 23:00 となるので、以下のように設定します。

cron(0 23 ? * SUN-THU *)
実行のスケジューリング

以上で、起動設定も完了です。

最後に

今回は、RDS利用コスト削減のため、自動起動・停止の設定を行いました。
DBマイグレーション時だけでなく、普段の開発・運用にもすぐに使えて便利です。

弊社では、EC2、RDS、Auroraなどのサービスは、社内環境は自動的に停止しています。
遅くまで作業していても、時間がきて開発環境が落ちたら「今日はもう切り上げよう」となるので、
仕事のメリハリもつきますし、環境の落とし忘れもなくなるのでコストにも優しいです。

今の設定では、平日か土日かしか判断していませんが、
祝日や会社の特別休暇もインスタンスを起動しないなど、
Lambdaに実装を追加することで、利用シーンにあった使い方が簡単にできます。

ぜひ、実際にお試しください。

↓↓ システムズのAWS DBマイグレーションに関する、Webページはこちらをご覧ください。 ↓↓

【 AWS DBマイグレーション 】

コラム一覧へ戻る
pagetop