はじめに
最近よく聞く「Iceberg」に関する記事です!
Icebergテーブルとカタログの関係性など、少しスッキリしたので記事に残します🧊
では早速、SnowflakeからS3にあるIcebergテーブルへアクセスしてみます。
前提
- 外部カタログを使用
- IcebergのカタログはAWSのGlue Data Catalogを
- この記事で紹介するAWSの作業は認証のみ
- Glue Data CatalogにIcebergテーブルを作成済
以下のように
外部カタログ(Glue Data Catalog)を使用し、外部クラウドストレージ(AWSのS3)に保存されたテーブルデータとメタデータに、外部ボリュームを使用してアクセスします。
準備するもの
-
Snowflake
- カタログ統合
- 外部ボリューム
- Icebergテーブル
-
AWS
- IAMロール(SnowflakeリソースのIDを信頼関係に追加します)
手順
1 SnowflakeにAWS Glueのカタログ統合を作成
1-1 Snowflakeでカタログ統合を作成
以下のSQLを実行してAWS Glueのカタログ統合を作成します。
--Glueのカタログ統合を作成
CREATE OR REPLACE CATALOG INTEGRATION <カタログ統合の名前>
CATALOG_SOURCE = GLUE
TABLE_FORMAT = ICEBERG
GLUE_AWS_ROLE_ARN = '<IAMロールのARN>'
GLUE_CATALOG_ID = '<Glue Data Catalog を管理する AWS アカウント ID>'
GLUE_REGION = '<Glue Data Catalog の AWS リージョン>'
CATALOG_NAMESPACE = '<Glue Data Catalog のデータベース名>'
ENABLED = TRUE -- カタログ統合をIcebergテーブルで使用する
;
1-2 SnowflakeアカウントのAWS IAMエンティティの情報と外部IDを取得
作成したカタログ統合をDESCRIBE
して、AWSに渡す情報を取得します。
DESCRIBE CATALOG INTEGRATION <カタログ統合の名前>;
- (1) GLUE_AWS_IAM_USER_ARN
- SnowflakeアカウントにあるAWS IAMエンティティ
- (2) GLUE_AWS_EXTERNAL_ID
- 信頼関係を確立するために必要な外部ID
1-3 IAMロールの信頼関係にSnowflakeの情報を追加
SnowflakeのAWS IAMエンティティにAWS側で用意したロールを引き渡すため、IAMロールの信頼関係にSnowflakeの情報を追加します。
これによりSnowflakeからAWSにアクセス出来ます。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "<(1)>"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": [
"< カタログ統合(2) >",
]
}
}
}
]
}
2 外部ボリュームを作成
2-1 AWSに保存されているデータにアクセスするため外部ボリュームを作成
以下を実行してSnowflakeに外部ボリュームを作成します。
CREATE OR REPLACE EXTERNAL VOLUME <外部ボリュームの名前>
STORAGE_LOCATIONS =
(
(
NAME = '<名前>'
STORAGE_PROVIDER = 'S3'
STORAGE_BASE_URL = 's3://<作成したs3バケット>'
STORAGE_AWS_ROLE_ARN = '<IAMロールのARN>'
STORAGE_AWS_EXTERNAL_ID = 'iceberg_table_external_id'
)
)
ALLOW_WRITES = FALSE; --読み取り専用に
2-2 外部IDを取得
先ほどの1-2と同じようにDESCRIBE
して、AWSに渡す情報を取得します。
DESCRIBE EXTERNAL VOLUME <外部ボリュームの名前>;
- (2) STORAGE_AWS_EXTERNAL_ID
- 信頼関係を確立するために必要な外部ID
2-3 IAMロールの信頼関係にSnowflakeの情報を追加
1-3と同じようにIAMロールの信頼関係に追加します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "<(1)>"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": [
"<カタログ統合(2)>",
"<外部ボリューム(2)>"
]
}
}
}
]
}
2-4 ストレージにアクセスしてみる
AWSの認証が上手くいっているか確認のため、外部ボリュームにアクセスできるか試します。
SELECT SYSTEM$VERIFY_EXTERNAL_VOLUME('<外部ボリューム名>');
成功すると"success":true
が返却されます。
外部ボリュームに読み取り専用 ALLOW_WRITES = FALSE;
の設定を忘れると、
s3:PutObject
の権限が無いためエラーになります。("success":false
)
3 SnowflakeにIcebergテーブルを作成
3-1 IAMポリシーにS3の権限を追加
Snowflakeでテーブルを作成する前に、IAMポリシー に s3:GetObject
を追加します。これにより、外部ボリュームを使用してS3にあるデータへアクセス出来ます。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowGlueCatalogTableAccess",
"Effect": "Allow",
"Action": [
"glue:GetTable",
"glue:GetTables"
],
"Resource": [
"arn:aws:glue:*:xxxxx:table/*/*",
"arn:aws:glue:*:xxxxx:catalog",
"arn:aws:glue:*:xxxxx:database/default"
]
},
{
"Sid": "AllowS3BucketAccess", ★追加
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": "<S3のURL>/*"
}
]
}
3-2 SnowflakeからGlue Data Catalog 上のテーブルを参照しIcebergテーブルを作成
以下のSQLを実行してIcebergテーブルを作成します。
--データベース、スキーマ作成
USE DATABASE db;
USE SCHEMA sc;
--Icebergテーブル作成
CREATE ICEBERG TABLE db.sc.<テーブル名>
EXTERNAL_VOLUME='<作成した外部ボリューム>'
CATALOG='<作成したカタログ統合>'
CATALOG_TABLE_NAME='<Glue Data Catalogにあるテーブル名>';
3-3 IcebergテーブルをSELECTしデータが取得できるか確認
SELECT * from db.sc.<テーブル名>;
Glue Data Catalogに作成したIcebergテーブルのデータがSELECTできました!
おわりに
SnowflakeからIcebergテーブルへアクセスできるかの検証にあたり、カタログ統合/外部ボリューム/Icebergテーブルなど、新しい要素を一度に学べてお得でした。
はじめは何から手を付けるか分からずでしたが、以下を整理することが大事だなと感じました。
・どのカタログを使うの?(Snowflake管理?/外部のもの?)
・どこにあるデータを見る?(今回は外部のS3)
AWS認証周りの理解はストレージ統合の経験が役立ったなと思います。
AWSのGlue Data CatalogをSnowflakeでカタログ統合し外部ボリュームを作成することで、AWSにあるIcebergテーブルへアクセスできました。AWS Glue CatalogがもつIcebergテーブルの情報を、Snowflakeでも認識する為にカタログを統合していると理解しました。ご参考までに!🌵