🧩

S3 Tables のカタログ統合を構成して Snowflake Iceberg テーブルを作成するまで

に公開

AWS re:Invent 2024 で Apache Iceberg 形式に最適化されたクラウドオブジェクトストアである Amazon S3 Tables が発表されました。現在は東京リージョンでも利用可能になっており、Snowflake でも Iceberg REST カタログ統合 を作成することで、S3 Tables 上の Iceberg テーブルをカタログ統合経由で参照することができます。(Public Preview 機能を含む)

今回、S3 Tables テーブルから Snowflake Iceberg テーブルを作成するまでを実際にやってみたので、備忘も兼ねてその手順についてまとめてみたいと思います。

S3 Tables リソースの準備

テーブルバケット・名前空間の作成

参照元 S3 Tables テーブルが所属するテーブルバケット、および名前空間を作成します。

main.tf
locals {
  table_bucket_name = "sandboxdb-s3tables-iceberg"
  namespace         = "demo_schema"
}

# S3 Tables Table Bucket
resource "aws_s3tables_table_bucket" "default" {
  name = local.table_bucket_name

  maintenance_configuration = {
    iceberg_unreferenced_file_removal = {
      status = "enabled"
      settings = { non_current_days = 10, unreferenced_days = 3 }
    }
  }
}
# S3 Tables Namespace
resource "aws_s3tables_namespace" "default" {
  table_bucket_arn = local.namespace
  namespace        = aws_s3tables_table_bucket.default.arn
}

S3 Tables テーブルの作成

続いて S3 Tables テーブルを作成します。方法はいくつかあると思いますが、今回は以下記事でも紹介しているように Glue ジョブで作成しました。

SparkConf の設定は S3 Tables 用のものを指定します。

conf = SparkConf()

conf.set("spark.sql.catalog.s3tablesbucket", "org.apache.iceberg.spark.SparkCatalog")
conf.set("spark.sql.catalog.s3tablesbucket.catalog-impl", "software.amazon.s3tables.iceberg.S3TablesCatalog")
conf.set("spark.sql.catalog.s3tablesbucket.warehouse", TABLE_BUCKET_ARN)
conf.set("spark.sql.extensions", "org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions")

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

クライアント用 IAM ロールの作成

S3 Tables テーブルにアクセスするための、クライアント用 IAM ロールを作成します。
(後述のステップでカタログ統合を作成後、AssumeRole ポリシーを修正します)

locals {
  role_name = "sandboxdb-s3tables-client-role"
  s3tables_table_bucket = {
    name = "sandboxdb-s3tables-iceberg"
  }
  datalake_administrators_iam_principals = [
    "arn:aws:iam::000011112222:role/xxxx",
  ]
}

# IAM Role
resource "aws_iam_role" "default" {
  name               = local.role_name
  assume_role_policy = data.aws_iam_policy_document.assume_role_policy.json
}
data "aws_iam_policy_document" "assume_role_policy" {
  statement {
    actions = ["sts:AssumeRole"]
    principals {
      type = "AWS"
      identifiers = local.datalake_administrators_iam_principals
    }
  }
}

resource "aws_iam_role_policy" "default" {
  name   = "${local.role_name}-policy"
  role   = aws_iam_role.default.name
  policy = data.aws_iam_policy_document.default.json
}
data "aws_iam_policy_document" "default" {
  statement {
    actions   = ["lakeformation:GetDataAccess"]
    resources = ["*"]
  }
  statement {
    actions = [
      "glue:GetCatalog",
      "glue:GetDatabase",
      "glue:GetDatabases",
      "glue:GetTable",
      "glue:GetTables",
      "glue:CreateTable",
      "glue:UpdateTable",
    ]
    resources = [
      "arn:aws:glue:*:${var.account_id}:catalog",
      "arn:aws:glue:*:${var.account_id}:catalog/s3tablescatalog",
      "arn:aws:glue:*:${var.account_id}:catalog/s3tablescatalog/${local.s3tables_table_bucket.name}",
      "arn:aws:glue:*:${var.account_id}:database/s3tablescatalog/${local.s3tables_table_bucket.name}/*",
      "arn:aws:glue:*:${var.account_id}:table/s3tablescatalog/${local.s3tables_table_bucket.name}/*/*",
    ]
  }
}

カタログ統合の構成

Iceberg REST のカタログ統合を作成します。[1]

執筆時点最新の Terraform Provider Version v2.1.0 にはカタログ統合の Resource がなさそうなので、SQL で作成することにします。

USE ROLE accountadmin;

CREATE OR REPLACE CATALOG INTEGRATION catalog_int_rest__iceberg_sandboxdb
  CATALOG_SOURCE = ICEBERG_REST
  TABLE_FORMAT = ICEBERG
  CATALOG_NAMESPACE = 'default'
  REST_CONFIG = (
    CATALOG_URI = 'https://glue.ap-northeast-1.amazonaws.com/iceberg'
    CATALOG_API_TYPE = AWS_GLUE
    WAREHOUSE = '000011112222:s3tablescatalog/sandboxdb-s3tables-iceberg'
    ACCESS_DELEGATION_MODE = vended_credentials
  )
  REST_AUTHENTICATION = (
    TYPE = SIGV4
    SIGV4_IAM_ROLE = 'arn:aws:iam::000011112222:role/sandboxdb-s3tables-client-role'
    SIGV4_SIGNING_REGION = 'ap-northeast-1'
  )
  ENABLED = TRUE
;

Snowflake 環境 IAM ユーザー ARN と外部 ID を確認します。

DESC CATALOG INTEGRATION catalog_int_rest__iceberg_sandboxdb;

Snowflake 環境 IAM ユーザーから AssumeRole できるよう、クライアント用 IAM ロールの AssumeRole Policy を修正します。

locals {
  external_identifiers = {
    iam_user_arn = "arn:aws:iam::777788889999:user/username"
    external_id  = "XY12345_SFCRole=xxxxxxxx"
  }
}

data "aws_iam_policy_document" "assume_role_policy" {
  statement {
    actions = ["sts:AssumeRole"]
    principals {
      type = "AWS"
      identifiers = local.datalake_administrators_iam_principals
    }
  }
  # Add Statement
  statement {
    actions = ["sts:AssumeRole"]
    principals {
      type = "AWS"
      identifiers = [ local.external_identifiers.iam_user_arn ]
    }
    condition {
      test     = "StringEquals"
      variable = "sts:ExternalId"
      values   = [ local.external_identifiers.external_id ]     
    }
  }
}

正常に構成できていれば、SYSTEM$VERIFY_CATALOG_INTEGRATION のレスポンスに含まれる "success" の値が true になります。

SELECT SYSTEM$VERIFY_CATALOG_INTEGRATION('CATALOG_INT_REST__ICEBERG_SANDBOXDB');

-- {"success" : true, "errorCode" : "", "errorMessage" : ""}

Lake Formation の設定

クライアント用 IAM ロールに対して、必要な Lake Formation 権限を Grant します。

Resource Type Resources Permissions
Catalog 000011112222:s3tablescatalog/sandboxdb-s3tables-iceberg Describe
Database 000011112222:s3tablescatalog/sandboxdb-s3tables-iceberg/demo_schema Describe
Table 000011112222:s3tablescatalog/sandboxdb-s3tables-iceberg/demo_schema/* *

Snowflake のような外部エンジンから S3 Tables を利用するにあたり、以下の Lake Formation 設定にチェックを入れます。

  • [ Administration ] > [ Application integration settings ] >
    • Allow external engines to access data in Amazon S3 locations with full table access

Snowflake Iceberg テーブルの作成

カタログ統合を使用して、Snowflake Iceberg テーブルを作成します。

CREATE OR REPLACE ICEBERG TABLE sandboxdb.demo_schema.users
  CATALOG = 'CATALOG_INT_REST__ICEBERG_SANDBOXDB'

  CATALOG_NAMESPACE  = 'demo_schema'
  CATALOG_TABLE_NAME = 'users'
  AUTO_REFRESH       = TRUE
;

データを参照できることを確認できます。

SELECT * FROM sandboxdb.demo_schema.users LIMIT 100;

参考

脚注
  1. CREATE CATALOG INTEGRATION (Apache Iceberg™ REST) - Snowflake Documentation ↩︎

Snowflake Data Heroes

Discussion