Snowflake Open Catalogが一般提供開始!カタログを作成してSnowflakeからテーブルを定義してみた
この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
さがらです。
つい先日、Snowflake Open Catalogが一般提供となりました!
以前はPolaris Catalogと呼ばれていましたが、一般提供に伴って名称が変更されました。ちなみにOSS版は変わらずApache Polarisです。
今回、Snowflake Open Catalogのアカウントを作成し、カタログを作成してSnowflakeからテーブルを定義するところまで試してみたので、本記事でその内容をまとめてみます。
Snowflake Open Catalogのアカウントの作成とログイン
まず、Snowflake Open Catalogのアカウントを作成します。
今回はドキュメントに沿って、下記のSQLを実行してアカウントを作成しました。
use role orgadmin;
create account 任意のアカウント名
admin_name = 任意のユーザー名
admin_password = '任意のパスワード'
email = 'ユーザーのメールアドレス'
edition = standard
region = 'AWS_AP_NORTHEAST_1'
polaris = true;
こちらのクエリを実行すると下図のようにアカウント名などが表示されますので、忘れずに控えておきましょう。特に、accountLocatorUrlがログインする際に使用するURLとなります。

先程控えたaccountLocatorUrlをブラウザのURL欄にいれると、このような画面となるので、先ほどSQLで用いたadmin_nameとadmin_passwordを用いてログインします。(パスワード変更画面は割愛します。)

無事にログインできると、このような画面となります。

カタログ用の外部クラウドストレージの作成
次に、カタログ用の外部クラウドストレージを作成します。今回はAmazon S3を使用します。
マネジメントコンソールからS3を選択し、バケットを作成を押します。

任意のバケット名を入れ、各設定はデフォルトのまま、一番下のバケットを作成を押します。


作成したバケットを開き、フォルダの作成を押して、任意のフォルダ名を入れて作成します。(Apache Icebergテーブルを保存するフォルダとなります。)


作成したフォルダを押し、右上のS3 URIをコピーを押します。ここで取得したURIを、後でSnowflake Open Catalogでカタログを作成する際にDefault base locationというパラメータに入れる形となります。

S3バケットにアクセスするためのIAMポリシー・IAMロールの作成
次に、先ほど作成したS3バケットにアクセスIAMポリシー・IAMロールを作成していきます。
S3バケットへのアクセスを許可するIAMポリシーを作成
マネジメントコンソールからIAMを選択し、画面の左からアカウント設定を押したあと、Security Token Service (STS)の中でエンドポイントから今回使用するリージョンを確認し、STSステータス列がアクティブになっていることを確認します。

この後、左のポリシーからポリシーの作成を押します。

JSONを選択し、下記の内容を入力します。<my_bucket>を先ほど作成したS3バケット名に書き換えた上で次へを押します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:GetObjectVersion",
"s3:DeleteObject",
"s3:DeleteObjectVersion"
],
"Resource": "arn:aws:s3:::<my_bucket>/*"
},
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:GetBucketLocation"
],
"Resource": "arn:aws:s3:::<my_bucket>",
"Condition": {
"StringLike": {
"s3:prefix": [
"*"
]
}
}
}
]
}

任意のポリシー名を入れた後、ポリシーの作成を押します。

S3バケットに対する権限を付与するIAMロールを作成
マネジメントコンソールからIAMを選択し、画面の左からロールを選択し、ロールを作成を押します。

信頼されたエンティティタイプはAWSアカウント、AWSアカウントはこのアカウント、外部IDを要求するにチェックを入れて任意の外部IDを入力し、次へを押します。

許可ポリシーは、先ほど作成したIAMポリシーを選択して、次へを押します。

任意のロール名を入れた後、ロールを作成を押します。

この後、作成したロールを表示して、ARNをコピーしておきます。

Snowflake Open Catalogでカタログを作成
これまでに作成したS3バケットやIAMロールなど情報を用いて、Snowflake Open Catalogでカタログを作成していきます。
Snowflake Open Catalogの画面左のCatalogsから、+ Catalogを押します。

これまでに作成したリソースの情報を入力して、Createを押します。
Name:任意のカタログ名を入力External:チェックを入れるStorage provider:「S3」を選択Default base location:作成したS3のURIS3 role ARN:作成したIAMロールのARNExternal ID:IAMロール作成時に入力した「外部ID」

Snowflake Open Catalogで作られたIAMユーザーに権限を付与
これまでの手順でカタログは作られたのですが、Snowflake Open Catalogで作られたIAMユーザーにバケットへのアクセス権限を付与する必要があります。
Open CatalogアカウントのIAMユーザーを取得
まず、先ほど作成したカタログを選択し、IAM user arnをコピーします。

IAMユーザーにバケットへのアクセス権限を付与
AWSのマネジメントコンソールに戻り、先ほど作成したIAMロールの画面に移動し、信頼関係タブを押します。

信頼ポリシーを編集を押します。

"Principal"の"AWS"の値を、先程確認したカタログのIAM user arnに変更して、ポリシーを更新を押します。

新しいConnectionの作成
Snowflake Open Catalogから、Snowflakeを含む外部サービスと接続するためのConnectionを作成します。
Snowflake Open Catalogの左のConnectionsから、+ Connectionを押します。

下図のように入力し、Createを押します。※Principal Roleについては、実際にサービスとの連携時に使用するロールであり、各カタログに対する権限(Catalog Role)をまとめてPrincipal Roleに付与することが出来ます。公式ドキュメントのRBAC Modelの図がわかりやすいと思います。

すると、このConnectionを利用する際に必要なClient IDとClient Secretが表示されますので、忘れずにコピーして控えておきましょう。

Catalog Roleの作成とPrincipal Roleへの付与
次に、先程Connectionと併せてPrincipal Roleを作成しましたが、どのカタログに対しての権限も与えていない状況です。
そのため、Catalog Roleを作成して、先程作成したPrincipal Roleに付与していきます。
Catalog Roleの作成
まず、先程作成したカタログを開き、Rolesタブから+ Catalog Roleを押します。

任意のNameを入れた後、PrivilegesにはCATALOG_MANAGE_CONTENTを入れ、Createを押します。(CATALOG_MANAGE_CONTENTはCatalog Roleに付与できる最上位の権限です。他の権限についてはこちらのドキュメントをご覧ください。)

作成したCatalog RoleをPrincipal Roleへ付与
次に、作成したCatalog RoleをPrincipal Roleに付与していきます。
同じカタログの画面のRolesタブで、Grant to Principal Roleを押します。

下図のようにこれまで作成したCatalog RoleとPrincipal Roleを選択し、Grantを押します。

Catalogのnamespaceを作成
次に、Catalogのnamespaceを作成します。(SnowflakeからCATALOG INTEGRATIONを作成する際に必要となります。)
Snowflake Open Catalog上で作成したカタログを開き、Namespacesタブから+ Namespaceを押します。

任意のNameを入力し、Createを押します。

CATALOG INTEGRATIONの定義
これまでの工程でSnowflakeからSnowflake Open Catalogに接続する準備が出来たので、Snowflake上でSnowflake Open CatalogとのCATALOG INTEGRATIONを定義していきます。
チュートリアルのクエリを参考に、下記のクエリを実行しました。
create or replace catalog integration sagara_open_catalog_int
catalog_source=polaris
table_format=iceberg
catalog_namespace=<事前にOpen Catalogで作成したnamespace>
rest_config = (
catalog_uri = 'https://<aa00000.ap-northeast-1.awsの形式でOpen Catalogのアカウント識別子を入れる>.snowflakecomputing.com/polaris/api/catalog'
warehouse = '<事前にOpen Catalogで作成したカタログ名>'
)
rest_authentication=(
type=OAUTH
oauth_client_id='Connection作成時に表示されたclient_id'
oauth_client_secret='Connection作成時に表示されたclient_secret'
oauth_allowed_scopes=('PRINCIPAL_ROLE:ALL') -- 「ALL」は作成したPricipale Roleの名称に書き換えてもOK
)
enabled=true;
Snowflake上でExternal Volumeを定義
SnowflakeからIceberg Tableを定義するにはExternal Volumeの定義が必要のため、External Volumeの作成を行います。
ただ、すでにSnowflake Open CatalogでS3バケットやIAMロールを作成しているため、これらのリソースを用いて、下記ドキュメントでいうStep 4からの手順を行えばOKです。
まず、Snowflake Open Catalogでカタログ作成時に作成したS3バケットやIAMロールの情報を用いて、下記のようなクエリを実行します。※下記は私の実例です。create external volumeについてはこちらの公式ドキュメントも併せてご覧ください。
create or replace external volume sagara_iceberg_external_volume
storage_locations = (
(
name = 'sagara-snowflake-open-catalog-ap-northeast-1'
storage_provider = 's3'
storage_base_url = 's3://sagara-snowflake-open-catalog/iceberg-tables/'
storage_aws_role_arn = 'arn:aws:iam::<AWSアカウントID>:role/sagara_snowflake_open_catalog_role'
storage_aws_external_id = 'sagara_open_catalog_external_id'
)
);
次に、作成したExternal Volumeについて下記のクエリを実行します。この結果から確認できるSTORAGE_AWS_IAM_USER_ARNの値をコピーします。
desc external volume sagara_iceberg_external_volume;

その後、事前に作成したIAMロールの信頼ポリシーに対して、確認したSTORAGE_AWS_IAM_USER_ARNの値を追記し、ポリシーを更新を押します。

次に、Snowflake上で下記のクエリを実行してExternal Volumeが問題なく機能するかを確認します。"success":trueが表示されればOKです!
select system$verify_external_volume('sagara_iceberg_external_volume');

Iceberg Tableの作成
長い準備となりましたが、これでSnowflakeからSnowflake Open CatalogをカタログとしたIceberg Tableを作成する準備が整いました!
今回は定番サンプルデータのsnowflake_sample_data.tpch_sf1.customerテーブルのデータをINSERTしてみたいと思います。
下記のクエリを実行して、Iceberg Tableを作成します。
create or replace iceberg table customer_iceberg (
c_custkey INTEGER,
c_name STRING,
c_address STRING,
c_nationkey INTEGER,
c_phone STRING,
c_acctbal INTEGER,
c_mktsegment STRING,
c_comment STRING
)
catalog = 'snowflake'
external_volume = 'sagara_iceberg_external_volume'
base_location = 'customer_iceberg' -- S3上でのフォルダ名となるため、作成するテーブル名と同名にするのがわかりやすいと思います
catalog_sync = 'sagara_open_catalog_int';
この状態でS3を見ると、customer_icebergというフォルダが出来て、中を見るとIcebergのメタデータを管理するmetadataフォルダも出来ています。


次に、下記のクエリを実行して、作成したテーブルにデータをINSERTします。
insert into customer_iceberg
select * from snowflake_sample_data.tpch_sf1.customer limit 10000;
この後で、S3のcustomer_icebergを見ると、新しくdataというフォルタが出来ています。中を見ると、eeというサブフォルダが作られ、その中にparquetファイルが作られています。



また、Snowflake Open Catalogも見ると、作成したIceberg Tableが見れるようになっています。

最後に
Snowflake Open Catalogが一般提供となったので、Snowflake Open Catalogのアカウントを作成し、カタログを作成してSnowflakeからテーブルを定義するところまで試してみました。
最初の準備は少し時間がかかりますが、この手順でテーブルを作れば、Snowflake Open CatalogをベースにSnowflakeからもSnowflake外部からもクエリを実行することができるようになります!(Snowflake外部からのクエリは別途ブログを書きたいと思っています。)
ここからSnowflakeでのIcebergを用いたレイクハウス活用が本格化していくと思います!!盛り上がってきました!!






