はじめに
この記事はAWS Community Builders Advent Calendar 2025の20日目の記事です
遅刻投稿です。すみません。。
ちょうど1年前ぐらいに当時まだプレビュー機能だったDataFirehoseからS3 Tablesへのデータ配信構成を検証しました。
その後しばらく触れる機会がなかったのですが、2025年3月14日にGAされていたことを今更ながらに知ったので、今度はマネジメントコンソールではなくコマンドでリソースを構築してみたいと思います。
※個人的になじみのあるTerraformで作ろうか迷いましたが、コマンドの方が作成するリソースや設定値を理解しやすいと思ったのでコマンドにしました
※S3 Tables自体については説明しませんので過去記事をご確認ください
前提
- wsl2インストール済み
- AWS CLI2インストール済み(version: 2.32.7)
Terraformコード
本記事で実施する手順は以下に置いています。
検証内容
詳細な手順は上記GitHubを見ていただければ書いてあるので、ここでは各手順毎の手順の補足説明や注意点などを書いていきます。
1. サンプル IoT データの作成
ここはFirehoseに配信するサンプルデータを作成しているだけなので、特筆する点はありません。
2. 環境変数の設定
ここではコマンド実行にあたって必要な値を環境変数として定義しています。
以下ではS3 Tablesのテーブルバケット名にランダム文字列を入れるようにしています。
理由としてはテーブルバケットが削除した際にしばらく名前を予約しているのか、同じ名前でテーブルバケットが作成できない事象が発生したため、複数回の実施でもエラーに起きないようにしました。
~省略~
# ランダム文字列を生成(8文字)
export RANDOM_SUFFIX=$(cat /dev/urandom | tr -dc 'a-z0-9' | fold -w 8 | head -n 1)
# リソース名の定義
export TABLE_BUCKET_NAME="iot-data-table-bucket-${RANDOM_SUFFIX}"
~省略~
3. S3 Table Bucket の作成
テーブルバケットを作成する際の必須パラメータは少なく、作成するテーブルバケット名のみになります。
create-table-bucket
--name <value>
[--encryption-configuration <value>]
[--tags <value>]
[--cli-input-json | --cli-input-yaml]
[--generate-cli-skeleton <value>]
[--debug]
[--endpoint-url <value>]
[--no-verify-ssl]
[--no-paginate]
[--output <value>]
[--query <value>]
[--profile <value>]
[--region <value>]
[--version <value>]
[--color <value>]
[--no-sign-request]
[--ca-bundle <value>]
[--cli-read-timeout <value>]
[--cli-connect-timeout <value>]
[--cli-binary-format <value>]
[--no-cli-pager]
[--cli-auto-prompt]
[--no-cli-auto-prompt]
命名規則は汎用バケットなどと同じような内容になっているので、よほど複雑にしようとしなければ問題ないかと思います。
バケット名は 3~63 文字の長さにする必要があります。
バケット名は、小文字、数字、およびハイフン (-) のみで構成できます。
バケット名は、文字または数字で開始および終了する必要があります。
バケット名にアンダースコア (_) またはピリオド (.) を含めることはできません。
https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/s3-tables-buckets-naming.html#table-buckets-naming-rules
また、汎用バケットとは異なりテーブルバケットはグローバルで一意である必要はありません。参考までに各S3種類毎の一意条件を記載します。
| バケット種類 | 条件 |
|---|---|
| 汎用バケット | パーティション内(※)のすべての AWS リージョンのすべての AWS アカウント全体で一意である必要がある |
| ディレクトリバケット | 選択したゾーン (AWS アベイラビリティーゾーンまたは AWS Local Zone) 内で一意である必要がある |
| テーブルバケット | アカウント内の各バケット名は現在の AWS リージョン内でのみ一意である必要がある |
※パーティションについて
AWS には、現在 aws (商用リージョン)、aws-cn (中国リージョン)、および aws-us-gov (AWS GovCloud (US) リージョン) の 3 つのパーティションがあります
4. ネームスペースの作成
テーブルバケットには名前空間という概念があります。
ドキュメントにも書いていますが、これはテーブルリソースを管理するための論理的なグループになります。
Amazon S3 テーブルバケット内にテーブルを作成するときは、名前空間と呼ばれる論理グループに整理します。S3 テーブルやテーブルバケットとは異なり、名前空間はリソースではありません。名前空間は、テーブルをスケーラブルに整理および管理するための構成概念です。例えば、会社の人事部門に属するすべてのテーブルを、共通の名前空間値 hr でグループ化できます。
名前空間とテーブル名にも命名規則が決まっているので、この条件は意識しておく必要があります。
名前の長さは 1〜255 文字にする必要があります。
名前には小文字、数字、下線 (_) のみを含めることができます。
名前の最初と最後は、文字または数字にしてください。
名前にハイフン (-) またはピリオド (.) を含めることはできません。
テーブル名は、名前空間内で一意である必要があります。
名前空間は、テーブルバケット内で一意である必要があります。
名前空間名は、予約済みプレフィックスの aws で始めることはできません。
また、後述しますが、S3 TablesはAWS GlueデータカタログやLake Formationと統合される関係で、大文字が利用できない点についても注意が必要です。
テーブルを作成するときは、テーブル名とテーブル定義にすべて小文字を使用してください。例えば、列名がすべて小文字であることを確認します。テーブル名またはテーブル定義に大文字が含まれている場合、テーブルは AWS Lake Formation または AWS Glue Data Catalog ではサポートされていません。
S3 Tablesのリソースに対してクエリなどの分析操作を行いたい場合、事前にS3 TablesのカタログをAWS Glueデータカタログに追加する必要があります。
その操作をすることによって、AthenaやRedshiftなどからアクセスできるようになります。
名前空間はAWS GlueデータカタログだとDatabase部分に該当します。
5. S3 Tables テーブルの作成(スキーマ定義含む)
名前空間が作成できたら、データを追加する箱となるテーブルを作っていきます。
前の図に表現されていたようにテーブルはテーブルバケット、名前空間の配下に配置されるため、コマンドの必須パラメータとしてその2つを指定する必要があります。
create-table
--table-bucket-arn <value>
--namespace <value>
--name <value>
テーブルバケットは名前ではなくARNなのでご注意ください
1年前に検証した際はSparkからSQLでテーブルを作成していましたが、現在ではAWS CLIコマンドのmetadataパラメータに指定することでテーブルを作成することができるようになっていました。
cat << EOF > table-definition.json
{
"tableBucketARN": "${TABLE_BUCKET_ARN}",
"namespace": "${NAMESPACE_NAME}",
"name": "${TABLE_NAME}",
"format": "ICEBERG",
"metadata": {
"iceberg": {
"schema": {
"fields": [
{"name": "device_id", "type": "string", "required": true},
{"name": "temperature", "type": "double", "required": false},
{"name": "humidity", "type": "double", "required": false},
{"name": "timestamp", "type": "string", "required": false}
]
}
}
}
}
EOF
aws s3tables create-table \
--region ${AWS_REGION} \
--cli-input-json file://table-definition.json
6. AWS 分析サービスとの統合を有効化
分析サービスなどからS3 Tablesにアクセスしたい場合、「AWS分析サービスとの統合を有効化」する必要があります。
S3 TablesのコンソールかLake Formationのコンソールから有効化することができます。
既に有効化済みの場合は実施不要です。
統合化されていると次のようにAthenaなどから確認ができるようになります。

7. Firehose 用エラー出力 S3 バケットの作成
ここではFirehose用にS3バケットを作成しているのみです。
8. Athena 用 IAM ロール・ポリシーの作成
手順8、及び手順9ではデータ投入確認のためのAthenaを用意する手順です。
コマンド実行のためにヘルパー関数定義がされていますが、Athenaコンソールから直接SQL実行する方法でも問題ないです。
その際は手順9.3と9.4のSQLをAthenaコンソールでご実施ください。(変数は置換してあげる必要があります)
10. Firehose 用 IAM ロール・ポリシーの作成
ここでは、Data Firehoseストリームに設定するIAMリソースを作成します。
私がこの部分でハマったところとして、権限にLakeFormationDataAccessを入れ忘れてしまったことで、想定外の権限エラーが複数回発生したことです。
{
"Sid": "LakeFormationDataAccess",
"Effect": "Allow",
"Action": [
"lakeformation:GetDataAccess"
],
"Resource": "*"
},
よくよく考えると分かるのですが、先ほど説明したとおりS3 TablesはLake Formationと統合されるため、データアクセスにはLake Formationの権限制御が利用されます。
その場合、GlueやS3Tablesの権限が付与されていたとしても、Lake Formationに登録されているデータにアクセスする場合はLake Formation(lakeformation:GetDataAccess)の権限が必要なようです。
Role arn:aws:iam::123456789123:role/FirehoseS3TablesDeliveryRole is not authorized to perform: glue:GetTable for the given table or the table does not exist.
ちゃんとドキュメントを読めば書いてあるのですが、エラーメッセージに glue:GetTable とあったので、しばらくの間、ずっとGlueの権限周りをトラブルシュートしてしまっていました。
Lake Formationを普段使っていない方はアクセスを許可したユーザー/ロールに lakeformation:GetDataAccess が不足していないかを見てもらうと良いかと思います。
データが含まれる Amazon S3 ロケーションを Lake Formation に登録します。
基盤となるデータのロケーションをポイントする Data Catalog テーブルを作成するプリンシパルにデータロケーション許可があること。
基盤となるデータに対する読み取りと書き込みを実行するプリンシパルに、基盤となるデータのロケーションをポイントする Data Catalog テーブルに対する Lake Formation データアクセス許可があること。
基礎となるデータロケーションが Lake Formation に登録されているとき、基礎となるデータを読み書きするプリンシパルには lakeformation:GetDataAccess IAM アクセス許可が必要です。
11. Lake Formation での権限付与
Lake Formationに統合すると、DBやテーブル毎の権限付与もLake Formation側で行う必要があります。
その際、コンソールから実施しても良いのですが、複数のページを遷移する必要があるので、手順のようにコマンドで実施する方が簡単かと思います。
12. Amazon Data Firehose の作成
ここでは、コマンド手順と手動設定時の設定項目を記載しているので、コンソール上の設定値がどのパラメータで定義されているかを確認してもらうと、よりわかりやすいかと思います。
バッファ感覚は仮で60秒にしているので、必要に応じて修正してください。
13. Firehose へのサンプルデータ投入
Firehoseが作成できたらサンプルデータを投入します。
ここでは最初の手順1で作成したJSONを利用して投入します。
14. Athena からのデータ確認
無事データ配信が完了していればAthenaからS3 Tablesテーブル内のデータがクエリできるはずです。
もしクエリに失敗する場合、AthenaロールがLake Formationに登録されているか確認してみると良いと思います。
リソースのクリーンアップ
今回はコマンドで構築を行ったので、リソース毎に削除操作をする必要があります。
ここでは削除コマンドを用意しているので、上から順次実行していただければ全て削除できると思います。
※S3 TablesのAWS分析サービス統合の有効化は無効化されません
おわりに
タイトルの「(ほぼ)」と付けていたのは、「AWS分析サービス統合の有効化」操作だけはマネジメントコンソールから実施する手順があったからでした。
昨年コンソールからS3 Tablesリソースの構築をした際は、複数のサービスコンソールを移動したり、ローカルのSparkやGlue Jobも必要になったりでかなり煩雑なイメージがあったのですが、かなり手順としてシンプルになった気がします。
手順が確立できたので、次はTerraformで実装できないか検証してみようと思います。
この記事がどなたかの参考になれば幸いです。


