Amazon S3 Tables の AWS 分析サービスとの統合

記事タイトルとURLをコピーする

はじめに

こんにちは。エンタープライズクラウド部の脇江です。

Amazon S3 Tables(以下、S3 Tables)のチュートリアルを実施してみたのですが、AWS 分析サービスからアクセスするために必要な統合の設定を進める中でエラーに遭遇し苦戦しました。

docs.aws.amazon.com

この記事では、S3 Tables の AWS 分析サービスとの統合設定や検証を通じて遭遇した問題と、その解決方法について解説します。

S3 Tables とは

S3 Tables とは、分析用に最適化された S3 ストレージを提供し、Apache Iceberg 形式のテーブルで表形式のデータを保存することのできるサービスです。 通常 S3 として使用する汎用バケットとは別に「テーブルバケット」を作成して、そこにデータを保存する形となります。

Amazon Athena や Amazon Redshift などの AWS 分析サービスがテーブルバケット内のデータにアクセスするために「AWS 分析サービスとの統合」を設定することが必要となります。

aws.amazon.com

S3 Tables については関連した弊社ブログがいくつかありますので、興味のある方はこちらもご覧になっていただけると嬉しいです。

blog.serverworks.co.jp

AWS 分析サービスとの統合

AWS 分析サービスがテーブルバケット内のデータにアクセスできるようにするために AWS 分析サービスとの統合を設定します。

実行されるアクション

AWS 分析サービスとの統合を有効化(あるいはマネジメントコンソールからテーブルバケットを作成)すると次のアクションが実行されます。 アクションはリージョンごとに 1 回のみ実施されます。

  • AWS Lake Formation(以下、Lake Formation)に対してすべてのテーブルバケットへのアクセスを許可する IAM サービスロールが作成される
  • 作成された IAM サービスロールを使用して、Lake Formation にテーブルバケットが登録される
  • AWS Glue Data Catalog(以下、Glue Data Catalog)にカタログ s3tablescatalog が追加される

それぞれの詳細を解説します。

IAM サービスロールの作成

Lake Formation が AWS アカウント内のすべてのテーブルバケットにアクセスできるように AWS マネージドポリシー AmazonS3TablesLakeFormationServiceRole がアタッチされた IAM ロール S3TablesRoleForLakeFormation が作成されます。

AmazonS3TablesLakeFormationServiceRole のポリシー内容は以下となります。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PermissionsForS3ListTableBuckets",
            "Effect": "Allow",
            "Action": [
                "s3tables:ListTableBuckets"
            ],
            "Resource": [
                "*"
            ],
            "Condition": {
                "StringEquals": {
                    "aws:ResourceAccount": "${aws:PrincipalAccount}"
                }
            }
        },
        {
            "Sid": "DataAccessPermissionsForS3TablesResources",
            "Effect": "Allow",
            "Action": [
                "s3tables:CreateTableBucket",
                "s3tables:GetTableBucket",
                "s3tables:CreateNamespace",
                "s3tables:GetNamespace",
                "s3tables:ListNamespaces",
                "s3tables:DeleteNamespace",
                "s3tables:DeleteTableBucket",
                "s3tables:CreateTable",
                "s3tables:DeleteTable",
                "s3tables:GetTable",
                "s3tables:ListTables",
                "s3tables:RenameTable",
                "s3tables:UpdateTableMetadataLocation",
                "s3tables:GetTableMetadataLocation",
                "s3tables:GetTableData",
                "s3tables:PutTableData",
                "s3tables:PutTableBucketEncryption"
            ],
            "Resource": [
                "*"
            ],
            "Condition": {
                "StringEquals": {
                    "aws:ResourceAccount": "${aws:PrincipalAccount}"
                }
            }
        },
        {
            "Sid": "KMSDataAccessPermissionsForS3TablesResources",
            "Effect": "Allow",
            "Action": [
                "kms:GenerateDataKey",
                "kms:Decrypt"
            ],
            "Resource": "*",
            "Condition": {
                "StringLike": {
                    "kms:ViaService": [
                        "s3.*.amazonaws.com"
                    ],
                    "kms:EncryptionContext:aws:s3:arn": "arn:aws:s3tables:*:*:bucket/*/table/*"
                },
                "StringEquals": {
                    "aws:ResourceAccount": "${aws:PrincipalAccount}"
                }
            }
        },
        {
            "Sid": "KMSDescribeKeyAccessPermissionsForS3TablesResources",
            "Effect": "Allow",
            "Action": [
                "kms:DescribeKey"
            ],
            "Resource": "*",
            "Condition": {
                "StringLike": {
                    "kms:ViaService": [
                        "s3tables.*.amazonaws.com"
                    ]
                },
                "StringEquals": {
                    "aws:ResourceAccount": "${aws:PrincipalAccount}"
                }
            }
        }
    ]
}

Lake Formation へのテーブルバケット登録

ここは文字通り、Lake Formation による管理対象としてテーブルバケットが登録されます。 Lake Formation からテーブルバケットへのアクセスについては前述の IAM サービスロールが使用されます。

Lake Formation の管理対象として登録されていない S3 バケットは Lake Formation によるアクセス制御の対象外となり、通常通りの IAM ポリシーや S3 バケットポリシーによって管理されることとなります。

統合処理でテーブルバケットが Lake Formation に登録されることにより、テーブルバケットへのアクセス制御は Lake Formation によって管理されるようになります。

Glue Data Catalog への s3tablescatalog の追加

リージョン内のすべてのテーブルバケット、名前空間、テーブルが Glue Data Catalog に追加されます。 Glue Data Catalog と S3 Tables のそれぞれのオブジェクトの関係性は以下のようになります。

Glue Data Catalog と S3 Tables のオブジェクトの関係性

参考: https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/s3-tables-integrating-aws.html

統合が実施されることで、Glue Data Catalog 上ではデフォルトのカタログとは別に「s3tablescatalog」が作成されます。その「s3tablescatalog」の配下のオブジェクトとしてカタログやデータベース、テーブルが作成されるという形になります。

設定手順

実際の設定手順を紹介します。

AWS 分析サービスとの統合

マネジメントコンソールから AWS 分析サービスとの統合を実行する手順を紹介します。

S3 コンソールを開き、画面左メニューから [テーブルバケット] を選択します。 内の統合ステータスを確認します。 リージョンで統合を実行したことがなければ、統合ステータスは「無効」となっています。

AWS 分析サービスとの統合ステータス - 統合前

統合を有効にするために [統合を有効にする] をクリックします。

統合を有効にする - ボタン

実行されるアクションで紹介した通り、「Lake Formation へのテーブルバケットの登録」「Glue Data Catalog への s3tablescatalog の追加」がそれぞれ実行される旨が説明に記載されています。 [統合を有効にする] をクリックします。

統合を有効にする - 実行画面

正常に処理が完了し、統合ステータスが「有効」となりました。

AWS 分析サービスとの統合ステータス - 統合後

Lake Formation 設定の確認

統合によって Lake Formation でどんな設定が実行されたかを確認します。

Lake Formation へのテーブルバケットの登録

Lake Formation コンソールを開き、画面左メニューから [Administration] → [Data lake locations] を選択します。

Data lake locations にテーブルバケットが追加

統合によって作成された IAM サービスロール S3TablesRoleForLakeFormation を使用して、Data lake location としてアカウント内のすべてのテーブルバケットが登録されていることが確認できました。これによって、今後作成されるすべてのテーブルバケットは Lake Formation によるアクセス制御の対象となります。

Glue Data Catalog への s3tablescatalog の追加

Lake Formation コンソールを開き、画面左メニューから [Data Catalog] → [Catalogs] を選択します。

カタログ s3tablescatalog の追加

統合によって、カタログとして s3tablescatalog が追加されていることが確認できました。

統合ステータスが「不明」の場合の確認

今回、冒頭に記載のチュートリアルと実行しようとした時にテーブルバケットの統合ステータスが「不明」となっていました。

AWS 分析サービスとの統合ステータス - 不明

「不明」の部分をクリックすると以下の説明が表示されます。

不明な統合ステータスの最も一般的な理由は、glue:GetCatalog または lakeformation:DescribeResource アクセス許可がないことです。さらに、コンソールへのアクセスに使用しているプリンシパルが Lake Formation のこの統合にアクセスするように設定されていることを確認してください。

結論としては、説明に記載の「コンソールへのアクセスに使用しているプリンシパルが Lake Formation のこの統合にアクセスするように設定されていること」を満たしていないことが原因でした。

以前に違うユーザーで S3 Tables のテーブルバケットを作成したことがあり、それによって既に s3tablescatalog が作成されている状態でした。今回は以前のテーブルバケット作成時とは異なるユーザーで操作していたことで権限が不足しており、統合ステータスが「不明」という状態になっていました。

Lake Formation の Data lake administrators に今回使用するユーザーを登録することで無事統合ステータスを「有効」とすることができました。

おわりに

S3 Tables と AWS 分析サービスとの統合について、実際の設定手順と遭遇した問題の解決方法を解説しました。

S3 Tables は Apache Iceberg 形式での分析用データ管理をするための有用なサービスですが、Lake Formation との連携部分で権限設定に注意が必要と感じました。

この記事が S3 Tables の導入を検討している方や、同様の問題に遭遇した方の参考になれば嬉しいです。

脇江 凜 (記事一覧)

エンタープライズクラウド部クラウドリライアビリティ課

猫が好きです。