AWS DMS Serverlessはタスクを停止しても48時間はDCUを消費します

AWS DMS Serverlessはタスクを停止しても48時間はDCUを消費します

Clock Icon2025.06.21

はじめに

データ事業本部ビッグデータチームの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.

https://docs.aws.amazon.com/ja_jp/dms/latest/userguide/CHAP_Serverless.Components.html
https://aws.amazon.com/jp/dms/pricing/

前提

AWS DMS

図のアーキテクチャで検証します。MySQLアカウントとDMSアカウントをVPC Peeringで接続し、MySQLからデータを取得しS3へ連携します。

実装

今回の実装コードは、Github上に格納してあるのでご確認いただければと思います。動作検証が目的のため、コードの説明は省略させていただきます。

https://github.com/cm-yoshikikasama/blog_code/tree/main/54_dms_serverless

@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

Screenshot 2025-06-15 at 8.34.00

次にDMSアカウントでVPCとDMSで使用するIAM Roleを以下のymlを用いてCloudFormationからデプロイします。

  • dms_account_vpc.yml
  • dms_account_iam.yml

Screenshot 2025-06-15 at 8.34.19

データベースの準備

次にCloudShellからRDSに接続し、データを作成します。RDSのエンドポイントはRDSの接続とセキュリティから確認でき、ユーザー名とパスワードは、今回はSecret Managerで保存しているのでそちらから取得します。

CloudShellは作成したVPC、Subnet、CloudShell用SGで作成します。

Screenshot 2025-06-15 at 8.45.54

次にMySQLに接続し、Databaseを作成します。今回は必要ないかもしれませんが、CDC時に実行間隔が空いている場合に、binlogの保持期間が短いと失敗する可能性があるため、48時間に設定しています。

mysql -h <RDS インスタンスのエンドポイント> -u admin -p
CALL mysql.rds_set_configuration('binlog retention hours', 48);
CREATE DATABASE sample_db;

Screenshot 2025-06-15 at 8.54.41

以下の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.');

Screenshot 2025-06-15 at 8.55.28

ネットワーク接続の設定

次にDMSアカウントでVPC Peering接続を画面上から設定します。VPC Peeringの一連の設定は公式の手順を参考にしました。
https://docs.aws.amazon.com/ja_jp/vpc/latest/peering/create-vpc-peering-connection.html

リクエスタはDMSアカウントのVPC ID、アクセプタはMySQLアカウントのVPC IDを指定します。
Screenshot 2025-06-15 at 9.41.20

MySQLアカウントでピアリング接続の承認待ち状態となるので、リクエストを承諾します。

Screenshot 2025-06-15 at 9.44.35

次にMySQLアカウントでRDSが紐づけているサブネットのルートテーブルにルートを追加します。

  • 宛先: DMSアカウントCIDR
  • ターゲット: VPC peering ID

Screenshot 2025-06-15 at 10.59.24

Screenshot 2025-06-15 at 10.58.49

DMSアカウントも同様にDMSを紐づけるサブネットのルートテーブルにルートを追加します。

  • 宛先: MySQLアカウントCIDR
  • ターゲット: VPC peering ID

Screenshot 2025-06-15 at 11.07.56

認証情報の設定

次にDMSアカウントでRDSのパスワードをSecret Managerを作成して保存します。

Screenshot 2025-06-15 at 11.15.37

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

Screenshot 2025-06-15 at 11.59.25

S3 BucketもCDKで指定した名前で手動作成しています。

DMSアカウントでも、作成したVPC、Subnet、DMS用のSGを用いてCloudShell上で接続確認を行いました。

Screenshot 2025-06-15 at 21.27.18
Screenshot 2025-06-15 at 21.29.17
VPCエンドポイントからS3への接続も問題なくできています。
Screenshot 2025-06-15 at 21.29.27

以上でデプロイ作業は完了になります!

検証

それでは次にDMSを実行し、コスト消費を確認したいと思います。

DMS実行

2025/06/15 21時にDMS Serverlessを画面上から実行しました。
Screenshot 2025-06-15 at 21.34.25
ロード処理が問題なく成功しました。
Screenshot 2025-06-16 at 7.09.41
S3上にもデータがロードされていることを確認できています。
Screenshot 2025-06-21 at 13.48.46

CloudWatch LogsでもフルロードとCDCモードになっていることを確認しています。
Screenshot 2025-06-16 at 7.12.10

2025/06/16 07:12にDMSを手動停止しました。
Screenshot 2025-06-16 at 7.14.08

DMS Serverlessの自動的なスケールダウンによりDCUは1になっています。この状態で何日間かのコスト推移を見てみたいと思います。
Screenshot 2025-06-16 at 7.25.41

確認

日にちをあけて2025/6/21に確認しました。DMS Serverlessのプロビジョニングは解除されています。
Screenshot 2025-06-21 at 10.51.31

コストを月次で確認しました。6/15 - 6/17の間でコストが掛かっています。
Screenshot 2025-06-21 at 10.47.20

コストを毎時表示にしてみて詳細な推移を確認しました。

Screenshot 2025-06-21 at 10.48.40

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の紐付けは公式ページを参考にしました。

https://aws.amazon.com/jp/dms/pricing/

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状態であれば課金されることに気づきませんでしたので、学びになりました。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.