[アップデート] S3 Express One Zone が S3 インベントリに対応したので試してみた
はじめに
2026 年 4 月、Amazon S3 Express One Zone(ディレクトリバケット)が S3 インベントリに対応しました。これまでディレクトリバケット内のオブジェクト棚卸しは、ListObjectsV2 による全件走査しかありませんでした。大規模なバケットではコストと時間が無視できません。今回のアップデートで、汎用バケットと同様に定期的なインベントリレポートを取得できるようになりました。
設定は API / CLI / SDK のみで、マネジメントコンソールは非対応です。AWS CLI で設定からレポート出力、Athena から確認までを一通り試した内容を紹介します。
確認結果
- S3 Express One Zone のディレクトリバケットに S3 インベントリを設定できるようになった
- 設定は CLI / SDK のみ。マネジメントコンソールのディレクトリバケット画面にインベントリタブは存在しない
- IAM アクションは
s3express:PutInventoryConfiguration/s3express:GetInventoryConfiguration(s3:ではない) - 出力先バケットポリシーの Principal は
s3express.amazonaws.com(s3.amazonaws.comではない) - 初回レポートの配信まで最大 48 時間かかる(S3 インベントリ共通仕様)
これまで
S3 Express One Zone はミリ秒オーダーの低レイテンシを持つディレクトリバケットを提供しますが、S3 インベントリは長らく未対応でした。オブジェクト数が数百万件を超えると ListObjectsV2 の走査コストと時間が無視できなくなります。
アップデートのポイント
ディレクトリバケットの S3 インベントリを汎用バケットへ書き出せるようになるアップデートです。制限事項を以下に整理します。
| 項目 | 内容 |
|---|---|
| 設定方法 | API / CLI / SDK のみ(マネジメントコンソール非対応) |
| 出力先バケット | 同一リージョンの汎用バケット(クロスリージョン不可) |
| 暗号化 | SSE-S3 / SSE-KMS(カスタマー管理キーのみ。AWS マネージドキー aws/s3 は不可。これは S3 インベントリ全般の制約) |
| 出力形式 | CSV / ORC / Parquet |
| スケジュール | Daily / Weekly |
やってみた
検証環境は ap-northeast-1 リージョン、AZ ID apne1-az4 です。AZ ID はアカウントやリージョンにより異なるため、aws ec2 describe-availability-zones --region ap-northeast-1 で事前に確認してください。
検証で使う変数を定義します。
SRC_BUCKET=devio-express-inv-src--apne1-az4--x-s3
DST_BUCKET=devio-express-inv-dst-20260421
ACCOUNT_ID=123456789012
ディレクトリバケットを作成する
ディレクトリバケットを作成しました。
aws s3api create-bucket \
--bucket "$SRC_BUCKET" \
--region ap-northeast-1 \
--create-bucket-configuration \
'Location={Type=AvailabilityZone,Name=apne1-az4},Bucket={Type=Directory,DataRedundancy=SingleAvailabilityZone}'
出力先の汎用バケットを作成する
受け取り先には同一リージョンの汎用バケットを使います。クロスリージョンは非対応です。
aws s3 mb s3://$DST_BUCKET --region ap-northeast-1
出力先バケットにポリシーを設定する
S3 インベントリのサービスが DST_BUCKET にレポートを書き込めるよう、バケットポリシーを設定します。Principal には s3express.amazonaws.com を指定します。s3.amazonaws.com を指定すると PutObject が拒否されます。
aws:SourceARN は arn:aws:s3express:<region>:<account>:bucket/<name--azid--x-s3> の形式で指定します。末尾の --azid--x-s3 サフィックスまで含める必要があります。
以下を dst-policy.json として保存します。
{
"Version": "2012-10-17",
"Statement": [{
"Sid": "InventoryDeliveryFromExpress",
"Effect": "Allow",
"Principal": { "Service": "s3express.amazonaws.com" },
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::devio-express-inv-dst-20260421/*",
"Condition": {
"ArnLike": {
"aws:SourceARN": "arn:aws:s3express:ap-northeast-1:123456789012:bucket/devio-express-inv-src--apne1-az4--x-s3"
},
"StringEquals": {
"aws:SourceAccount": "123456789012",
"s3:x-amz-acl": "bucket-owner-full-control"
}
}
}]
}
ポリシーを適用します。
aws s3api put-bucket-policy --bucket "$DST_BUCKET" --policy file://dst-policy.json
適用後の状態はコンソールのアクセス許可タブから確認できます。

テスト用オブジェクトをアップロードする
レポートに何件か表示されるよう、サイズの異なるオブジェクトを 2 つアップロードします。
dd if=/dev/urandom of=/tmp/small.bin bs=1024 count=10
dd if=/dev/urandom of=/tmp/large.bin bs=1048576 count=20
aws s3 cp /tmp/small.bin s3://$SRC_BUCKET/small.bin
aws s3 cp /tmp/large.bin s3://$SRC_BUCKET/large.bin
アップロードしたオブジェクトはディレクトリバケットの画面で確認できました。

インベントリ設定を投入する
以下を inv.json として保存します。フォーマットは Parquet、スケジュールは Daily を選択しました。LifecycleExpirationDate は OptionalFields から除外しています(ライフサイクルルール未設定のため空欄になります)。
バケット名、アカウント名は環境に合わせて修正してください。
{
"Id": "daily-full-report",
"IsEnabled": true,
"Destination": {
"S3BucketDestination": {
"AccountId": "123456789012",
"Bucket": "arn:aws:s3:::devio-express-inv-dst-20260421",
"Format": "Parquet",
"Prefix": "inventory"
}
},
"Schedule": { "Frequency": "Daily" },
"IncludedObjectVersions": "Current",
"OptionalFields": [
"Size", "LastModifiedDate", "StorageClass", "ETag",
"IsMultipartUploaded", "EncryptionStatus", "BucketKeyStatus",
"ChecksumAlgorithm"
]
}
設定を投入します。
aws s3api put-bucket-inventory-configuration \
--bucket "$SRC_BUCKET" \
--id daily-full-report \
--inventory-configuration file://inv.json
成功すると空レスポンスが返ります。
$ aws s3api put-bucket-inventory-configuration \
> --bucket "$SRC_BUCKET" \
> --id daily-full-report \
> --inventory-configuration file://inv.json
$
設定を確認する
投入した設定を取得して内容を確認します。
aws s3api get-bucket-inventory-configuration \
--bucket "$SRC_BUCKET" \
--id daily-full-report
IsEnabled: true や Schedule.Frequency: Daily などが返ってきます。
{
"InventoryConfiguration": {
"Destination": {
"S3BucketDestination": {
"AccountId": "123456789012",
"Bucket": "arn:aws:s3:::devio-express-inv-dst-20260421",
"Format": "Parquet",
"Prefix": "inventory"
}
},
"IsEnabled": true,
"Id": "daily-full-report",
"IncludedObjectVersions": "Current",
"OptionalFields": [
"Size",
"LastModifiedDate",
"StorageClass",
"ETag",
"IsMultipartUploaded",
"EncryptionStatus",
"BucketKeyStatus",
"ChecksumAlgorithm"
],
"Schedule": {
"Frequency": "Daily"
}
}
}
翌日以降にレポートの配信を確認する

私の検証では設定を投入してから約 33 時間後(2026-04-23 22:20 JST)に初回レポートが配信されました。丸 2 日待つつもりで計画しておくと安全です。
DST_BUCKET の中身を再帰的に確認します。
aws s3 ls "s3://$DST_BUCKET/inventory/" --recursive --human-readable
実行結果は以下のとおりです。
2026-04-23 22:20:25 33 Bytes inventory/devio-express-inv-src--apne1-az4--x-s3/daily-full-report/2026-04-23T00-00Z/manifest.checksum
2026-04-23 22:20:25 904 Bytes inventory/devio-express-inv-src--apne1-az4--x-s3/daily-full-report/2026-04-23T00-00Z/manifest.json
2026-04-23 22:20:17 0 Bytes inventory/devio-express-inv-src--apne1-az4--x-s3/daily-full-report/data/
2026-04-23 22:20:24 3.5 KiB inventory/devio-express-inv-src--apne1-az4--x-s3/daily-full-report/data/5bc79653-697b-400a-b851-52678a86704b.parquet
2026-04-23 22:20:25 152 Bytes inventory/devio-express-inv-src--apne1-az4--x-s3/daily-full-report/hive/dt=2026-04-23-00-00/symlink.txt
配置されたオブジェクトの内容は以下のとおりです。
| パス | 内容 |
|---|---|
<inventory-id>/<snapshot-date>/manifest.json |
レポートのメタデータ。data ファイルへのパスとスキーマを保持 |
<inventory-id>/<snapshot-date>/manifest.checksum |
manifest.json の MD5 チェックサム |
<inventory-id>/data/<uuid>.parquet |
レポート本体。スナップショット時点のオブジェクト一覧 |
<inventory-id>/hive/dt=<snapshot-date>/symlink.txt |
Hive 互換のパーティション用 symlink。Athena から日付パーティションでクエリする際に利用 |
manifest.json をダウンロードして中身を確認します。
aws s3 cp \
"s3://$DST_BUCKET/inventory/$SRC_BUCKET/daily-full-report/2026-04-23T00-00Z/manifest.json" \
./manifest.json
cat manifest.json
中身は次のとおりでした。
{
"sourceBucket" : "devio-express-inv-src--apne1-az4--x-s3",
"destinationBucket" : "arn:aws:s3:::devio-express-inv-dst-20260421",
"version" : "2016-11-30",
"creationTimestamp" : "1776902400001",
"fileFormat" : "Parquet",
"fileSchema" : "message s3.inventory { required binary bucket (STRING); required binary key (STRING); optional int64 size; optional int64 last_modified_date (TIMESTAMP(MILLIS,true)); optional binary e_tag (STRING); optional binary storage_class (STRING); optional boolean is_multipart_uploaded; optional binary encryption_status (STRING); optional binary bucket_key_status (STRING); optional binary checksum_algorithm (STRING);}",
"files" : [ {
"key" : "inventory/devio-express-inv-src--apne1-az4--x-s3/daily-full-report/data/5bc79653-697b-400a-b851-52678a86704b.parquet",
"size" : 3614,
"MD5checksum" : "7835c2a989a416983fc72004841e59e2"
} ]
}
Parquet 本体の中身も確認します。ローカルマシンの duckdb で覗いてみます。
$ aws s3 cp s3://devio-express-inv-dst-20260421/inventory/devio-express-inv-src--apne1-az4--x-s3/daily-full-report/data/5bc79653-697b-400a-b851-52678a86704b.parquet .
$ duckdb -c "SELECT key, size, storage_class, is_multipart_uploaded, encryption_status, checksum_algorithm FROM read_parquet('/tmp/5bc79653-697b-400a-b851-52678a86704b.parquet');"
┌───────────┬──────────┬─────────────────┬───────────────────────┬───────────────────┬────────────────────┐
│ key │ size │ storage_class │ is_multipart_uploaded │ encryption_status │ checksum_algorithm │
│ varchar │ int64 │ varchar │ boolean │ varchar │ varchar │
├───────────┼──────────┼─────────────────┼───────────────────────┼───────────────────┼────────────────────┤
│ small.bin │ 10240 │ EXPRESS_ONEZONE │ false │ SSE-S3 │ CRC64NVME │
│ large.bin │ 20971520 │ EXPRESS_ONEZONE │ true │ SSE-S3 │ CRC64NVME │
└───────────┴──────────┴─────────────────┴───────────────────────┴───────────────────┴────────────────────┘
アップロードした 2 オブジェクトが想定どおり記録されていました。
large.bin は 20 MiB のファイルで、aws s3 cp のマルチパートしきい値を超えます。そのため自動でマルチパートに切り替わり、is_multipart_uploaded が true として記録されています。small.bin は 10 KiB なので false です。
storage_class はディレクトリバケットなので EXPRESS_ONEZONE で固定です。checksum_algorithm は今回 aws s3 cp でアップロードしたため CRC64NVME が記録されていました。AWS CLI v2 の既定では新しいオブジェクトに対して CRC64NVME が選択されます。チェックサムアルゴリズムに興味があれば、こちらの記事も参照してください。
Athena でクエリを試す
Parquet 形式で出力しているため、Athena で CREATE EXTERNAL TABLE を実行すればそのままクエリできます。公式手順の Parquet 向けテンプレートをベースに、今回の OptionalFields(8 項目)に合わせて列を絞ったものが以下です。
インベントリレポートを Athena でクエリする手順全般は公式ドキュメントにまとまっています。
CREATE EXTERNAL TABLE express_inventory_report (
bucket string,
key string,
size bigint,
last_modified_date timestamp,
e_tag string,
storage_class string,
is_multipart_uploaded boolean,
encryption_status string,
bucket_key_status string,
checksum_algorithm string
) PARTITIONED BY (
dt string
)
ROW FORMAT SERDE 'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe'
STORED AS INPUTFORMAT 'org.apache.hadoop.hive.ql.io.SymlinkTextInputFormat'
OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.IgnoreKeyTextOutputFormat'
LOCATION 's3://devio-express-inv-dst-20260421/inventory/devio-express-inv-src--apne1-az4--x-s3/daily-full-report/hive/'
TBLPROPERTIES (
"projection.enabled" = "true",
"projection.dt.type" = "date",
"projection.dt.format" = "yyyy-MM-dd-HH-mm",
"projection.dt.range" = "2026-04-23-00-00,NOW",
"projection.dt.interval" = "1",
"projection.dt.interval.unit" = "HOURS"
);
テーブル作成後、マルチパートアップロードだけ絞り込むクエリを投げてみます。
SELECT key, size, last_modified_date
FROM express_inventory_report
WHERE dt = '2026-04-23-00-00'
AND is_multipart_uploaded = true;
Athena クエリエディタで実行すると、マルチパート対象の large.bin だけが結果に返ってきました。

さいごに
S3 Express One Zone が S3 インベントリに対応したことで、ディレクトリバケットの棚卸しが格段に楽になりました。とくに次のユースケースで役立つのではないでしょうか。
- コンプライアンス棚卸し: 定期的なオブジェクト一覧を S3 に保持し、監査証跡とする
- 暗号化状態の監査:
EncryptionStatus/BucketKeyStatusで全オブジェクトの暗号化状況を確認する - ライフサイクル期限の可視化:
LifecycleExpirationDateを OptionalFields に追加し、削除タイミングを事前に把握する(ライフサイクルルール未設定のバケットでは空欄)
参考
- Amazon S3 Express One Zone now supports S3 Inventory
- Cataloging and analyzing your data with S3 Inventory
- Configuring Amazon S3 Inventory
- Differences for directory buckets
- Directory bucket API operations
- Querying Amazon S3 Inventory with Amazon Athena
- [アップデート]S3 Express One Zone に S3 ライフサイクルルールを設定できるようになりました
- [アップデート] S3 Express One Zone のディレクトリバケットでリクエストメトリクスを CloudWatch で取得できるようになりました






