[アップデート] Amazon S3 Tables の名前空間とテーブルも AWS CDK L2 Construct で構築可能になりました
こんにちは、製造ビジネステクノロジー部の若槻です。
Amazon S3 Tables は、S3 上で Apache Iceberg テーブルを簡単に管理できるフルマネージドサービスですが、最近の AWS CDK のアップデートにより、S3 Tables の テーブル(Table) および 名前空間(Namespace) リソースが L2 Construct(アルファ版)で構築できるようになりました。
今まで L2 Construct をサポートしていたのはテーブルバケット(Table Bucket) のみでしたが、これで S3 Tables のすべてのリソースを L2 Construct で実装可能になりました。
試してみた
CDK パッケージのアップデート
AWS CDK モジュールとアルファモジュール(@aws-cdk/aws-s3tables-alpha)を v2.209.0 以上にアップデートします。
npm i -D @aws-cdk/aws-s3tables-alpha@latest aws-cdk-lib@latest aws-cdk@latest
CDK で S3 Tables を構築する
以下のコードは、S3 Tables のテーブルバケット、名前空間、およびテーブルを CDK で構築する例です。
import * as cdk from "aws-cdk-lib";
import * as s3tables from "@aws-cdk/aws-s3tables-alpha";
import { Construct } from "constructs";
export class MainStack extends cdk.Stack {
constructor(scope: Construct, id: string) {
super(scope, id);
/**
* テーブルバケット
*/
const tableBucket = new s3tables.TableBucket(this, "TableBucket", {
tableBucketName: "table-bucket-1", // 指定必須
removalPolicy: cdk.RemovalPolicy.DESTROY, // デフォルトは Retain
});
/**
* テーブル名前空間
*/
const namespace = new s3tables.Namespace(this, "Namespace", {
namespaceName: "my_namespace_1", // 指定必須
tableBucket,
});
/**
* テーブル
*/
new s3tables.Table(this, "Table", {
tableName: "my_table_1", // 指定必須
removalPolicy: cdk.RemovalPolicy.DESTROY, // デフォルトは Retain
namespace,
openTableFormat: s3tables.OpenTableFormat.ICEBERG, // 指定必須。現在選択可能なのは ICEBERG のみ。
icebergMetadata: {
icebergSchema: {
schemaFieldList: [
{
name: "id",
type: "int",
required: true,
},
{
name: "name",
type: "string",
},
],
},
},
/**
* 圧縮戦略の設定。既定では、テーブルのソート順に基づいて最適なコンパクション戦略が選択される。
* @see https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-tables-maintenance.html#s3-tables-maintenance-compaction-strategies
*/
compaction: {
status: s3tables.Status.ENABLED,
targetFileSizeMb: 128, // 指定必須。
},
/**
* スナップショット管理の設定。デフォルトで有効。
* @see https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-tables-maintenance.html#s3-tables-maintenance-snapshot-management
*/
snapshotManagement: {
status: s3tables.Status.ENABLED,
maxSnapshotAgeHours: 48, // スナップショットの最大保持期間。 デフォルトは 120 時間(5 日)
minSnapshotsToKeep: 5, // 保持する最小スナップショット数。デフォルトは 1
},
});
}
}
上記をデプロイすると、CloudFormation で以下のようなリソースが作成されます。
作成されたテーブルバケット table-bucket-1
です。
作成されたテーブル my_table_1
です。名前空間 my_namespace_1
に属しています。
マネジメントコンソールから確認できる情報はここまでです。詳細な情報の確認や操作は相変わらず AWS CLI で行う必要があるんですね。
という訳で CLI でテーブルの情報を取得してみます。
$ aws s3tables get-table \
--table-bucket-arn "arn:aws:s3tables:ap-northeast-1:${ACCOUNT_ID}:bucket/table-bucket-1" \
--namespace "my_namespace_1" \
--name "my_table_1"
{
"name": "my_table_1",
"type": "customer",
"tableARN": "arn:aws:s3tables:ap-northeast-1:XXXXXXXXXXXX:bucket/table-bucket-1/table/171a89c4-777a-4dcb-b925-aef117030124",
"namespace": [
"my_namespace_1"
],
"versionToken": "218f1265852efc6123ae",
"metadataLocation": "s3://171a89c4-777a-4dcb-n6i8qfi7eepus8auwjqgnk97cxyqaapn1b--table-s3/metadata/00000-8c03be4d-345d-4589-bc34-b68135990c28.metadata.json",
"warehouseLocation": "s3://171a89c4-777a-4dcb-n6i8qfi7eepus8auwjqgnk97cxyqaapn1b--table-s3",
"createdAt": "2025-08-07T13:27:08.804433+00:00",
"createdBy": "XXXXXXXXXXXX",
"modifiedAt": "2025-08-07T13:29:36.541333+00:00",
"ownerAccountId": "XXXXXXXXXXXX",
"format": "ICEBERG"
}
メタデータは 171a89c4-777a-4dcb-n6i8qfi7eepus8auwjqgnk97cxyqaapn1b--table-s3
というシステムバケットに保存されています。ここからメタデータを取得してみます。
aws s3 cp "s3://171a89c4-777a-4dcb-n6i8qfi7eepus8auwjqgnk97cxyqaapn1b--table-s3/metadata/00000-8c03be4d-345d-4589-bc34-b68135990c28.metadata.json" ./metadata.json
メタデータの内容を確認してみます。CDK で指定したスキーマ設定が反映されていることがわかります。
$ cat metadata.json | jq .
{
"format-version": 2,
"table-uuid": "171a89c4-777a-4dcb-b925-aef117030124",
"location": "s3://171a89c4-777a-4dcb-n6i8qfi7eepus8auwjqgnk97cxyqaapn1b--table-s3",
"last-sequence-number": 0,
"last-updated-ms": 1754576866280,
"last-column-id": 2,
"current-schema-id": 0,
"schemas": [
{
"type": "struct",
"schema-id": 0,
"fields": [
{
"id": 1,
"name": "id",
"required": true,
"type": "int"
},
{
"id": 2,
"name": "name",
"required": false,
"type": "string"
}
]
}
],
"default-spec-id": 0,
"partition-specs": [
{
"spec-id": 0,
"fields": []
}
],
"last-partition-id": 999,
"default-sort-order-id": 0,
"sort-orders": [
{
"order-id": 0,
"fields": []
}
],
"properties": {
"write.parquet.compression-codec": "zstd"
},
"current-snapshot-id": -1,
"refs": {},
"snapshots": [],
"statistics": [],
"partition-statistics": [],
"snapshot-log": [],
"metadata-log": []
}
テーブルのメンテナンス設定を確認してみます。圧縮とスナップショットの管理が CDK で指定した通りに設定できています。
$ aws s3tables get-table-maintenance-configuration \
--table-bucket-arn "arn:aws:s3tables:ap-northeast-1:${ACCOUNT_ID}:bucket/table-bucket-1" \
--namespace "my_namespace_1" \
--name "my_table_1"
{
"tableARN": "arn:aws:s3tables:ap-northeast-1:XXXXXXXXXXXX:bucket/table-bucket-1/table/171a89c4-777a-4dcb-b925-aef117030124",
"configuration": {
"icebergCompaction": {
"status": "enabled",
"settings": {
"icebergCompaction": {
"targetFileSizeMB": 128
}
}
},
"icebergSnapshotManagement": {
"status": "enabled",
"settings": {
"icebergSnapshotManagement": {
"minSnapshotsToKeep": 1,
"maxSnapshotAgeHours": 120
}
}
}
}
}
CDK デプロイ時に遭遇したエラー
UnscopedValidationError エラー
名前空間を my-namespace-1
という名前で作成しようとしました。
new s3tables.Namespace(this, "Namespace", {
namespaceName: "my-namespace-1",
tableBucket,
});
すると、以下のようなエラーが発生しました。英数字以外はアンダースコア(_
) のみ使用可能なようです。
/Users/wakatsuki.ryuta/projects/cm-rwakatsuki/cdk_sample_app/node_modules/@aws-cdk/aws-s3tables-alpha/lib/namespace.ts:134
throw new UnscopedValidationError(
^
UnscopedValidationError: Invalid S3 Tables namespace name (value: my-namespace-1)
Namespace name must only contain lowercase characters, numbers, and underscores (_) (offset: 2)
at path [undefined]
テーブルを作成する際にも同様のエラーが発生しました。my-table-1
という名前で作成しようとしました。
new s3tables.Table(this, "Table", {
tableName: "my-table-1",
namespace,
openTableFormat: s3tables.OpenTableFormat.ICEBERG,
});
こちらも同様に、英数字以外はアンダースコア(_
) のみ使用可能なようです。
/Users/wakatsuki.ryuta/projects/cm-rwakatsuki/cdk_sample_app/node_modules/@aws-cdk/aws-s3tables-alpha/lib/table.ts:326
throw new UnscopedValidationError(
^
UnscopedValidationError: Invalid S3 table name (value: my-table-1)
Table name must only contain lowercase characters, numbers, and underscores (_) (offset: 2)
at path [undefined]
InvalidRequest エラー
テーブルを作成する際に、IcebergMetadata を指定しないでデプロイしようとしました。
new s3tables.Table(this, "Table", {
tableName: "my_table_1", // テーブル名の指定必須
namespace,
openTableFormat: s3tables.OpenTableFormat.ICEBERG, // OpenTableFormat の指定必須。現在選択可能なのは ICEBERG のみ。
});
すると、以下のようなエラーが発生しました。IcebergMetadata または WithoutMetadata のいずれかを指定する必要があるようです。
Resource handler returned message: "Invalid request provided: Either IcebergMetadata or WithoutMetadata must be specified" (RequestToken: 3b8a431b-d9ef-3076-0194-9751a75
8fb13, HandlerErrorCode: InvalidRequest)
AlreadyExists エラー
テーブルバケットをデプロイしようとしました。
const tableBucket = new s3tables.TableBucket(this, "TableBucket", {
tableBucketName: "my-table-bucket-1",
});
同名のテーブルバケットが存在しているという理由で、デプロイ時に AlreadyExists エラーが発生しました。
11:48:51 PM | CREATE_FAILED | AWS::S3Tables::TableBucket | TableBucket/TableBucket
Resource handler returned message: "The bucket that you tried to create already exists, and you own it. (Service: S3Tables, Status Code: 409, Request ID: 4614ca28-a2b8-4
31a-90ba-92faa163efaf) (SDK Attempt Count: 1)" (RequestToken: 00d6f3c1-48ed-6a7f-a7cb-8ad966f5e28b, HandlerErrorCode: AlreadyExists)
AWS CLI で該当のテーブルバケットを削除します。
aws s3tables delete-table-bucket \
--table-bucket-arn "arn:aws:s3tables:ap-northeast-1:${accountId}:bucket/my-table-bucket-1" \
--region ap-northeast-1
これで OK かと思いきや、テーブルバケット削除直後に再度デプロイをしようとすると、また AlreadyExists エラーが発生しました。
11:55:43 PM | CREATE_FAILED | AWS::S3Tables::TableBucket | TableBucket/TableBucket
Resource handler returned message: "The bucket is in a transitional state because of a previous deletion attempt. Try again later. (Service: S3Tables, Status Code: 409,
Request ID: bbad8cd1-d28c-4bbf-aebb-f822737506aa) (SDK Attempt Count: 1)" (RequestToken: 35fe9290-4458-8019-27b4-2f95a3921494, HandlerErrorCode: AlreadyExists)
今度は The bucket is in a transitional state because of a previous deletion attempt.
とあり、削除完了の状態になるるまで時間がかかるようでした。マネジメントコンソールからだと消えているように見えるんですけどね。仕方がないので別の名前のテーブルバケットを作成しました。
おわりに
Amazon S3 Tables の名前空間とテーブルも AWS CDK L2 Construct で構築可能になったので試してみました。
これで S3 Tables の実装のインフラのコード化がより捗りますね!S3 Tables の採用を検討している方は、ぜひ試してみてください。
以上