AWS DMS Serverlessはタスクを停止しても48時間はDCUを消費します
はじめに
データ事業本部ビッグデータチームのkasamaです。
今回はAWS DMS Serverlessについて検証し、表題の内容について学んだことをまとめたいと思います。
結論
公式ドキュメントにも記載がありますが、DMS Serverlessを停止しても48時間以内はProvisioning状態のため、DCU(DMS Capacity Units)消費による課金が発生します。48時間を経過するとDeprovisionedされ、課金も停止します。
そのため、EventBridge SchedulerでDMS ServerlessをStart, Stopして日次バッチスケジュールを組んだとしても48時間以内はProvisioning状態のため、コストがかかることになりますので注意しましょう。
You cannot restart a replication that has not started in 48 hours as AWS DMS deprovisions the resources.
前提
図のアーキテクチャで検証します。MySQLアカウントとDMSアカウントをVPC Peeringで接続し、MySQLからデータを取得しS3へ連携します。
実装
今回の実装コードは、Github上に格納してあるのでご確認いただければと思います。動作検証が目的のため、コードの説明は省略させていただきます。
@54_dms_serverless % tree
.
├── cdk
│ ├── bin
│ │ └── app.ts
│ ├── cdk.context.json
│ ├── cdk.json
│ ├── jest.config.js
│ ├── lib
│ │ └── dms-serverless-stack.ts
│ ├── package-lock.json
│ ├── package.json
│ └── tsconfig.json
├── cloudformation
│ ├── dms_account_iam.yml
│ ├── dms_account_vpc.yml
│ ├── mysql_account_rds.yml
│ └── mysql_account_vpc.yml
└── README.md
6 directories, 18 files
デプロイ
それでは実装リソースをデプロイしていきます。
基盤リソースのデプロイ
まずはMySQLアカウントでVPCとRDSを以下のymlを用いてCloudFormationからデプロイします。
- mysql_account_vpc.yml
- mysql_account_rds.yml
次にDMSアカウントでVPCとDMSで使用するIAM Roleを以下のymlを用いてCloudFormationからデプロイします。
- dms_account_vpc.yml
- dms_account_iam.yml
データベースの準備
次にCloudShellからRDSに接続し、データを作成します。RDSのエンドポイントはRDSの接続とセキュリティ
から確認でき、ユーザー名とパスワードは、今回はSecret Managerで保存しているのでそちらから取得します。
CloudShellは作成したVPC、Subnet、CloudShell用SGで作成します。
次にMySQLに接続し、Databaseを作成します。今回は必要ないかもしれませんが、CDC時に実行間隔が空いている場合に、binlogの保持期間が短いと失敗する可能性があるため、48時間に設定しています。
mysql -h <RDS インスタンスのエンドポイント> -u admin -p
CALL mysql.rds_set_configuration('binlog retention hours', 48);
CREATE DATABASE sample_db;
以下のsqlでデータを投入し、Select句でデータを確認します。
CREATE TABLE sample_db.products (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL,
`category` varchar(50) DEFAULT NULL,
`price` decimal(10,2) NOT NULL,
`stock` int NOT NULL DEFAULT '0',
`description` text,
`created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
);
INSERT INTO sample_db.products (name, category, price, stock, description) VALUES
('MacBook Pro', 'Electronics', 1999.99, 50, 'Apple MacBook Pro with M2 chip'),
('iPhone 15', 'Mobile', 999.99, 100, 'Latest iPhone model with 128GB storage'),
('AirPods Pro', 'Audio', 249.99, 200, 'Wireless noise-cancelling earbuds'),
('iPad Air', 'Tablet', 599.99, 75, '10.9-inch display with 64GB storage'),
('Apple Watch', 'Wearable', 399.99, 120, 'Series 8 with health monitoring features'),
('Magic Mouse', 'Accessories', 79.99, 150, 'Wireless mouse for Mac'),
('Magic Keyboard', 'Accessories', 99.99, 100, 'Wireless keyboard with numeric keypad'),
('HomePod Mini', 'Smart Home', 99.99, 80, 'Smart speaker with Siri'),
('AirTag', 'Accessories', 29.99, 300, 'Item tracker'),
('Apple TV 4K', 'Entertainment', 179.99, 60, 'Streaming device with 4K HDR support'),
('MacBook Air M3', 'Electronics', 1299.99, 75, 'Apple MacBook Air with M3 chip and 13-inch display'),
('MacBook Air M4', 'Electronics', 1299.99, 75, 'Apple MacBook Air with M4 chip and 13-inch display'),
('MacBook air 2028', 'Electronics', 2499.99, 30, 'Latest generation MacBook Pro with enhanced performance and display.');
ネットワーク接続の設定
次にDMSアカウントでVPC Peering接続を画面上から設定します。VPC Peeringの一連の設定は公式の手順を参考にしました。
リクエスタはDMSアカウントのVPC ID、アクセプタはMySQLアカウントのVPC IDを指定します。
MySQLアカウントでピアリング接続の承認待ち状態となるので、リクエストを承諾します。
次にMySQLアカウントでRDSが紐づけているサブネットのルートテーブルにルートを追加します。
- 宛先: DMSアカウントCIDR
- ターゲット: VPC peering ID
DMSアカウントも同様にDMSを紐づけるサブネットのルートテーブルにルートを追加します。
- 宛先: MySQLアカウントCIDR
- ターゲット: VPC peering ID
認証情報の設定
次にDMSアカウントでRDSのパスワードをSecret Managerを作成して保存します。
DMSリソースのデプロイ
54_dms_serverless/cdk/lib/dms-serverless-stack.ts
の以下の箇所をデプロイ実行する前に自身の環境用に設定します。
// デプロイ前に指定が必要な値はここでまとめて管理
const SUBNET_IDS = [
"subnet-xxxxxxxxxxxxxxxxx", // 1つ目のDMSサブネットID
"subnet-yyyyyyyyyyyyyyyyy", // 2つ目のDMSサブネットID
];
const S3_BUCKET_NAME = "S3-Bucket-Name"; // DMSターゲット用S3バケット名
const SECRET_ARN =
"arn:aws:secretsmanager:ap-northeast-1:xxxxxxxxxxxx:secret:ID"; // DMSアカウントのRDSシークレットのARN
const DMS_SECURITY_GROUP_PREFIX_LIST_ID = "pl-"; // S3 VPCエンドポイントのPrefixListId
const RDS_SERVER_NAME = "rds-arn"; // RDSのエンドポイント名
package.jsonがあるディレクトリで依存関係をインストールします。
npm install
cdk.jsonがあるディレクトリで、CDKで定義されたリソースのコードをAWS CloudFormationテンプレートに合成(変換)するプロセスを実行します。
npx cdk synth --profile <YOUR_AWS_PROFILE>
同じくcdk.jsonがあるディレクトリでデプロイコマンドを実行します。--all
はCDKアプリケーションに含まれる全てのスタックをデプロイするためのオプション、--require-approval never
はセキュリティ的に敏感な変更やIAMリソースの変更を含むデプロイメント時の承認を求めるダイアログ表示を完全にスキップします。never
は、どんな変更でも事前確認なしにデプロイすることを意味します。今回は検証用なので指定していますが、慎重にデプロイする場合は必要のないオプションになるかもしれません。
npx cdk deploy --all --require-approval never --profile <YOUR_AWS_PROFILE>
最終設定と接続確認
デプロイに成功したら、次はMySQLのSecurityGroupにインバウンドルールを追加します。
- タイプ: MYSQL
- Port: 3306
- ソース: DMSのSG ID
- 説明: Allow MySQL traffic from DMS
S3 BucketもCDKで指定した名前で手動作成しています。
DMSアカウントでも、作成したVPC、Subnet、DMS用のSGを用いてCloudShell上で接続確認を行いました。
VPCエンドポイントからS3への接続も問題なくできています。
以上でデプロイ作業は完了になります!
検証
それでは次にDMSを実行し、コスト消費を確認したいと思います。
DMS実行
2025/06/15 21時にDMS Serverlessを画面上から実行しました。
ロード処理が問題なく成功しました。
S3上にもデータがロードされていることを確認できています。
CloudWatch LogsでもフルロードとCDCモードになっていることを確認しています。
2025/06/16 07:12にDMSを手動停止しました。
DMS Serverlessの自動的なスケールダウンによりDCUは1になっています。この状態で何日間かのコスト推移を見てみたいと思います。
確認
日にちをあけて2025/6/21に確認しました。DMS Serverlessのプロビジョニングは解除されています。
コストを月次で確認しました。6/15 - 6/17の間でコストが掛かっています。
コストを毎時表示にしてみて詳細な推移を確認しました。
Cost ExplorerはUTC表記であるため、上記の結果をJST時刻の表にしました。
日時・時間帯(JST) | 時間単価 | 継続時間 | DCU |
---|---|---|---|
2025年6月15日 21:00 - 23:00 | $0.46/h | 2時間 | 4 DCU |
2025年6月15日 23:00 - 2025年6月16日 01:00 | $0.23/h | 2時間 | 2 DCU |
2025年6月16日 01:00 - 2025年6月18日 08:00 | $0.11/h | 55時間 | 1 DCU |
東京リージョンの時間単価とDCUの紐付けは公式ページを参考にしました。
DCU | 時間あたり料金 |
---|---|
1 | $0.114 |
2 | $0.229 |
4 | $0.458 |
DMS停止時刻 2025年6月16日 07:12(JST)- 課金終了時刻 2025年6月18日 08:00(JST)= 約48時間48分なので公式の「48時間」に近い数値になりました。Cost Explorerでは分単位でのコスト消費が確認できないため、おおよその時間での計算となります。
最後に
Serverlessという名前がついているので、停止したら課金されないものかと思っていましたが、Statusが停止状態でもProvisioned状態であれば課金されることに気づきませんでしたので、学びになりました。