こんにちは!クラウドインフラ・SREの世界へようこそ。
今回は、モダンなインフラ構成管理(IaC)ツールである「Pulumi」を使って、AWSのNoSQLデータベースであるAmazon DynamoDBを極めて安全かつ堅牢に構築する方法を解説します。
「インフラをコードで管理したいけれど、CloudFormationやTerraformは記述が冗長でつらい……」
「TypeScriptなどの汎用プログラミング言語を使って、もっと直感的にインフラを書きたい!」
そんなあなたにこそ、Pulumiは最高の相棒となります。これをマスターすれば、マルチリージョン対応のデータベース構築も、手に取るように簡単かつ安全に行えるようになりますよ。
今日のゴールは、「グローバルテーブル(複数リージョン間での自動同期)」と「ポイントインタイムリカバリ(PITR:過去35日以内の任意の時点への復元)」、そして「自動スケーリング」を備えたプロダクション品質のDynamoDBを、TypeScriptで美しく構築することです。
一緒に一歩ずつ、その深淵を覗いていきましょう!
—
1. Pulumiとは何か? なぜ今、NoSQLのコード化に選ばれるのか?
ツールの役割と基礎知識
Pulumiは、JSONやYAML、あるいは専用のDSL(Domain Specific Language)ではなく、使い慣れたプログラミング言語(TypeScript, Python, Go, C#など)を使ってクラウドインフラを定義・プロビジョニングできるモダンなIaCツールです。
従来のツール(Terraformなど)との最大の違いは、「if文」や「ループ」、「関数」といったプログラミング言語の強力な表現力をそのままインフラ定義に持ち込める点にあります。
DynamoDB構築における課題とアプローチ
NoSQLであるDynamoDBは、RDBとは異なり「スキーマレス」ですが、本番環境で運用する際には以下の要件が不可欠になります。
1. 可用性の担保: 障害に備えるためのマルチリージョン展開(グローバルテーブル)。
2. データの保護: 誤操作やバグによるデータ破損から即座に復旧するためのPITR(Point-in-Time Recovery)。
3. 負荷への追従: トラフィックの変動に自動で耐えるAuto Scaling。
これらを従来のツールで手動、あるいは複雑な設定ファイルで管理しようとすると、リージョンごとのリソース依存関係の管理で頭が痛くなります。しかし、Pulumiを使えば、オブジェクト指向の美しさを活かして安全かつ宣言的に構築できます。
—
2. 環境構築とファーストステップ(Hello World)
まずは、手元のマシンの開発環境を整えましょう。
必要なツールのインストール
以下のツールがインストールされていることを前提に進めます。
- Node.js (v18以上推奨)
- AWS CLI (認証設定済みであること `aws configure`)
- Pulumi CLI
Pulumi CLIのインストールは、MacならHomebrewで一撃です。
brew install pulumi
プロジェクトの初期化
適当な作業ディレクトリを作成し、Pulumiプロジェクトを初期化します。今回はTypeScriptを使用します。
mkdir pulumi-dynamodb-demo
cd pulumi-dynamodb-demo
pulumi new aws-typescript
途中でプロジェクト名やパスワード(暗号化用)を聞かれますが、基本はデフォルト(Enter連打)で問題ありません。
完了すると、`index.ts` というファイルが生成されます。これがあなたのインフラの設計図となります。
—
3. 実践:マルチリージョン・グローバルテーブルとPITRの構築
ここからが本番です。
東京リージョン(`ap-northeast-1`)をプライマリ、オレゴンリージョン(`us-west-2`)をセカンダリとした、グローバルテーブルを構築するコードを記述します。
`index.ts` を以下のように書き換えてください。
import as pulumi from “@pulumi/pulumi”;
import as aws from “@pulumi/aws”;
// 1. プロバイダーの定義(マルチリージョン展開の要)
// デフォルトの東京リージョンに加え、オレゴンリージョンのプロバイダーを明示的に定義します。
const primaryRegion = “ap-northeast-1”;
const secondaryRegion = “us-west-2”;
const secondaryProvider = new aws.Provider(“us-west-2-provider”, {
region: secondaryRegion,
});
// 2. DynamoDBテーブルの基本設定(両リージョン共通のスキーマ)
const tableName = “users-production”;
// プライマリリージョン(東京)のテーブル作成
const primaryTable = new aws.dynamodb.Table(“primary-table”, {
name: tableName,
billingMode: “PROVISIONED”, // 本番運用を想定したプロビジョンドモード
readCapacity: 5,
writeCapacity: 5,
hashKey: “userId”, // パーティションキー
attributes: [
{ name: “userId”, type: “S” }, // S = String
],
// 【重要】ポイントインタイムリカバリ(PITR)の有効化
// これにより、過去35日間の任意の秒にデータを巻き戻すことが可能になります。
pointInTimeRecovery: {
enabled: true,
},
// サーバーサイド暗号化の有効化(AWS管理キーを使用)
serverSideEncryption: {
enabled: true,
},
// グローバルテーブルのレプリカ設定(オレゴンを指定)
replicas: [
{
regionName: secondaryRegion,
},
],
}, {
// グローバルテーブルの仕様上、リソース削除時の保護などを考慮
protect: false, // 本番環境では true を推奨
});
// 3. 自動スケーリング(Auto Scaling)の設定
// 読込・書込キャパシティをトラフィックに応じて自動増減させます。
// プライマリ(東京)の書込オートスケーリング
const writeTarget = new aws.appautoscaling.Target(“dynamo-write-target”, {
maxCapacity: 100,
minCapacity: 5,
resourceId: pulumi.interpolate`table/${primaryTable.name}`,
scalableDimension: “dynamodb:table:WriteCapacityUnits”,
serviceNamespace: “dynamodb”,
});
new aws.appautoscaling.Policy(“dynamo-write-policy”, {
policyType: “TargetTrackingScaling”,
resourceId: writeTarget.resourceId,
scalableDimension: writeTarget.scalableDimension,
serviceNamespace: writeTarget.serviceNamespace,
targetTrackingScalingPolicyConfiguration: {
predefinedMetricSpecification: {
predefinedMetricType: “DynamoDBWriteCapacityUtilization”,
},
targetValue: 70.0, // 使用率70%を維持するように自動調整
},
});
// 4. 出力の設定(デプロイ後にテーブル名を確認できるようにする)
export const primaryTableName = primaryTable.name;
export const primaryTableArn = primaryTable.arn;
—
4. コードの解説:なぜこの設計が「安全」なのか?
上記のコードには、SREとしての知見がいくつか詰め込まれています。
1. プロバイダーの分離によるマルチリージョン制御
`aws.Provider` を明示的に分けることで、単一のコードベースから複数のAWSリージョンへ安全にリソースをデプロイできます。Terraformでこれをやろうとするとモジュールのネストで複雑化しますが、TypeScriptなら直感的です。
2. PITR(Point-in-Time Recovery)の標準装備
`pointInTimeRecovery: { enabled: true }` を一行書くだけで、AWS側のバックアップ機構が完全に有効化されます。人間はミスをする生き物ですが、この設定がコードで強制されていれば「うっかりデータを消してしまった」という絶望的な状況から数秒で生還できます。
3. ターゲット追跡スケーリング(Target Tracking)
Auto Scalingのポリシーに `targetValue: 70.0` を指定しています。これにより、「CPU使用率やキャパシティ使用率が70%を超えたら自動でスケールアップ、落ち着けばスケールダウン」という理想的なオートメーションがコードベースで担保されます。
—
5. デプロイと動作確認
コードを書いたら、いよいよデプロイです。魔法のコマンドを叩きましょう。
pulumi up
実行すると、PulumiがAWSの現在の状態とコードの差分を計算し、以下のようなプレビュー画面を表示してくれます。
Type部に作成されるリソースのプレビューが表示されます…
Do you want to perform this update?
> yes
no
details
ここで `yes` を選択すると、AWS上にDynamoDBのグローバルテーブルとオートスケーリングが構築されます。数分で処理が完了し、ターミナルにエクスポートした変数(テーブル名など)が表示されます。
動作確認
AWSマネジメントコンソールを開き、東京リージョンとオレゴンリージョンを確認してみてください。
東京で作ったテーブルが、オレゴンリージョンにもレプリカとして自動的に同期されていることが確認できます。さらに、バックアップタブから「ポイントインタイムリカバリ」が有効になっていることも一目瞭然です。
—
まとめ
今回は、PulumiとTypeScriptを用いて、AWS DynamoDBのグローバルテーブル、PITR、そしてオートスケーリングを安全かつモダンに構築する方法を解説しました。
これをマスターすれば、面倒なインフラのポチポチ作業や、複雑怪奇なYAML地獄から解放され、「堅牢で可用性の高いデータベース基盤」を数分で再現できるようになります。毎日のインフラ運用が劇的に楽になりますよ。
さあ、次はあなた自身のプロジェクトで、このコードを動かしてみましょう。
ハッピー・コーディング!