🕺

『Snowflakeストレージ統合』を活用してAmazon S3バケットとSnowflake外部ステージの連携を行う

に公開

Snowflakeでは、「ストレージ統合」という仕組みを活用することでSnowflakeがAmazon S3バケットに対してデータを読み書きできるような連携が行えます。

https://docs.snowflake.com/ja/user-guide/data-load-s3-create-stage#external-stages
https://docs.snowflake.com/ja/user-guide/data-load-s3

当エントリでは、この「ストレージ統合」の連携手順を実践し、実際にどのような形でS3バケットとSnowflakeが連携されているのかを見ていきたいと思います。

前提・必要なもの

  • Snowflakeアカウント
    • 当エントリで行う各種SQL操作、及び関連オブジェクトにアクセスできる権限を持つユーザー
    • ストレージ統合を使用するステージを作成するには、スキーマのCREATE STAGE権限とストレージ統合のUSAGE権限を持つロールが必要(※要参照)
  • AWSアカウント
    • 当エントリで必要な操作(S3及びIAM関連)の権限を有するIAMユーザー(が望ましい)

実践手順について

当エントリで進めていく手順は基本的には下記Snowflakeの公式ドキュメントに則る形となります。
https://docs.snowflake.com/ja/user-guide/data-load-s3-config-storage-integration

流れとしては大きく以下のような形で進めていきます。

  • Snowflakeアカウント及びデータベース以下各種環境の用意
  • AWSアカウント及びS3バケットの用意
  • AWSアカウント環境で設定連携に必要なIAMポリシーを作成
  • AWSアカウント環境で設定連携に必要なIAMロールを作成
  • Snowflakeでクラウドストレージ統合を作成(CREATE STORAGE INTEGRATION)
  • Snowflakeで連携に必要なSnowflakeアカウントのAWS IAMユーザー情報を取得
  • AWSアカウント環境でバケットオブジェクトにアクセスするためにIAMユーザー権限を付与
  • Snowflakeで外部ステージを作成
  • 動作・連携確認(AWSアカウント&Snowflake)

#0. Snowflakeと連携させるAmazon S3バケットの確認

まず初めに、Snowflakeと連携させるAmazon S3バケットの確認・準備を行います。通常であれば既存作成済のS3バケットをSnowflake連携用に設定する...というようなケースが当てはまりそうですが、ここでは今回の検証用に別途S3バケットを作成するところから初めてみます。

Snowflakeアカウント側のリージョンを確認し、そのリージョンと合わせる形でS3バケットを作成します。今回の場合はSnowflakeアカウントが東京リージョンでしたのでS3バケットの作成も同様に東京リージョンで行います。

AWSアカウントにログイン後、東京リージョンにてS3バケットを作成。名前は任意のものを指定してください。今回はsnowflake-s3-integration-xxxxxxxxxx-testという名前のバケットを用意することにしました。

以降の設定はデフォルト指定で進めます。運用面を考えてカスタマイズ設定が必要な場合は別途読み替える形で設定を行っておいてください。設定を確認後[バケットを作成]を押下。


#1. S3バケットのアクセス許可を構成(IAMポリシーの作成)

今回の件、SnowflakeとS3バケットの連携を行う上で、IAMポリシーを用意する必要があります。AWS側のベストプラクティスとしても「S3バケットへのSnowflakeアクセス用のIAMポリシーを作成して利用」が推奨されていますのでその内容に従います。

AWS管理コンソールからIAMメニュー→[アカウント設定]を選択、エンドポイントリストの Security Token Service (STS) で、利用するアカウントが存在するSnowflakeリージョンを探し、状態がアクティブになっているかどうかを確認してください。アクティブになっていればOK。そうでない場合は有効化しておいてください。

次いでIAMポリシーの作成へ。[ポリシー]から[ポリシーの作成]を選択。

ポリシーエディタにて情報の作成を行います。エディタ部分の編集方式を[JSON]に変更。

編集内容を書き入れます。

記載した内容は以下の通り。今回は<prefix>に相当する部分は省略し、『対象バケット配下はすべて今回のS3統合用に有効とする』設定としてみました。内容が確認できたら[次へ]を選択。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
              "s3:PutObject",
              "s3:GetObject",
              "s3:GetObjectVersion",
              "s3:DeleteObject",
              "s3:DeleteObjectVersion"
            ],
            "Resource": "arn:aws:s3:::snowflake-s3-integration-xxxxxxxxxx-test/*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket",
                "s3:GetBucketLocation"
            ],
            "Resource": "arn:aws:s3:::snowflake-s3-integration-xxxxxxxxxx-test",
            "Condition": {
                "StringLike": {
                    "s3:prefix": [
                        "*"
                    ]
                }
            }
        }
    ]
}

『ポリシーの詳細』部分に情報を追記し、[ポリシーの作成]を押下。

必要なIAMポリシーが作成出来ました。

#2. IAM AWS ロールを作成

次いで、これも連携設定に必要となる『IAM AWSロール』を作成していきます。

IAMメニュー→[ロール]から[ロールを作成]を選択。

[信頼されたエンティティタイプ]で[AWSアカウント]を選択。

AWSアカウントの部分は[別のアカウント→当該操作しているAWSアカウントのID]を記入、またオプションで「外部IDを要求する」を選択の上外部IDに適当な値(ここでは0000としています)を入力しておいてください。ここは後述する手順で得られる値に置き換える形となり、一旦このタイミングでは仮の値を設定しておく流れとなっています。設定出来たら[次へ]を押下。

「許可するポリシー」にて、先程の手順で作成したIAMポリシーを選択、[次へ]を押下。

「ロールの詳細」に任意の情報を書き入れ、[ロールの作成]を押下。

IAMロールが作成出来ました。作成したIAMロールののARN情報は後述手順で必要となるので、値を控えておいてください。(下記アイコン部分をクリックすることで値をコピー出来ます)

これでAWS側の設定、準備は粗方整いました。

#3. Snowflakeでクラウドストレージ統合を作成(CREATE STORAGE INTEGRATION)

ここからはSnowflake環境下での作業を進めていきます。Snowflake環境は所定のデータベース及びデータベース配下に必要な情報、要素がすでに作成し運用されているという前提で進めます。

Snowflakeにログインし、CREATE STORAGE INTEGRATIONでストレージ統合を作成。検証用のスキーマを任意のデータベース配下に作成し、そこに今回必要となった諸々の要素を配備する形で進めました。

実行SQLのパラメータに関する説明は以下の通り。

  • STORAGE INTEGRATION:任意のストレージ統合の名称。
  • STORAGE_AWS_ROLE_ARN:前述手順(#2)で控えておいた、作成したロールのAmazonリソースネーム(ARN)の文字列。
  • STORAGE_ALLOWED_LOCATIONS:データファイルを保存するS3バケットの名称。これも上述手順で作成、確認したバケットの名称が入ります。
create or replace schema XXXXXXXXDB.SHINYAA31;
CREATE STORAGE INTEGRATION s3_int_xxxxxxxxxx_test
  TYPE = EXTERNAL_STAGE
  STORAGE_PROVIDER = 'S3'
  ENABLED = TRUE
  STORAGE_AWS_ROLE_ARN = 'arn:aws:iam::123456789012:role/iam-aws-role-for-snowflake-s3-integration-xxxxxxxxxx-test'
  STORAGE_ALLOWED_LOCATIONS = ('s3://snowflake-s3-integration-xxxxxxxxxx-test/')
  --// S3バケット配下のもので連携に含めたくないものがあれば別途
  --// `STORAGE_BLOCKED_LOCATIONS`で指定が必要。
  STORAGE_BLOCKED_LOCATIONS = ('s3://mybucket1/mypath1/sensitivedata/', 's3://mybucket2/mypath2/sensitivedata/');
;

#4. 連携に必要なSnowflakeアカウントのAWS IAMユーザー情報を取得

手順#2で作成した「仮置き」としていた部分を置き換える情報をここで取得します。上記で作成したストレージ統合(STORAGE INTEGRATION)の値を参照することでその値が取得出来ます。DESCRIBE INTEGRATIONコマンドを実行。

DESC INTEGRATION s3_int_xxxxxxxxxx_test;

実行すると、以下のような形で一連の情報が表示されます。この項目の中のSTORAGE_AWS_IAM_USER_ARNSTORAGE_AWS_EXTERNAL_IDの値をそれぞれ控えておいてください。

#5. バケットオブジェクトにアクセスするためにIAMユーザー権限を付与(設定変更)

前述作成していたIAMロールを用いて正しくバケットにアクセスできるように、IAMロールのポリシー部分に上述手順で控えたSnowflakeアカウントのIAMユーザー情報を設定(変更)します。

作成したIAMロールの[信頼ポリシーを編集]を選択。

編集画面で該当部分を所定の値に変更します。内容が確認出来たら[ポリシーを更新]を押下。

  • "Principal""AWS"配下の部分:控えておいた項目STORAGE_AWS_IAM_USER_ARNの値
  • "sts:ExternalId"の部分:控えておいた項目STORAGE_AWS_EXTERNAL_IDの値
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::123456789012:user/xxxxxxxxxxxxxxx"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "sts:ExternalId": "XXXXxxxxXXXXXxxxxXXXxxxXXxxxXXxXXx"
        }
      }
    }
  ]
}

ポリシーの更新完了。これでAWSのS3バケットとSnowflakeがストレージ統合を通じて連携できるようになりました。

#6. Snowflakeの外部ステージを作成

ここからは動作確認です。対象スキーマ配下でCREATE STAGEコマンドにて外部ステージを作成。

USE SCHEMA XXXXXXXXDB.SHINYAA31;
CREATE OR REPLACE FILE FORMAT shinyaa31_csv_format
  TYPE = 'CSV',
  FIELD_DELIMITER = ',',
  SKIP_HEADER = 1;
CREATE STAGE test_stage_shinyaa31
  STORAGE_INTEGRATION = s3_int_xxxxxxxxxx_test
  URL = 's3://snowflake-s3-integration-xxxxxxxxxx-test/'
  FILE_FORMAT = shinyaa31_csv_format;

S3バケット直下にCSVファイルを置いてみます。

sample.csv
user_id,name,age
100,Taro,11
200,Jiro,22
300,Saburo,33

そしてSnowflake側で内容を確認。対象スキーマ配下にステージ(Stages)として上記で作成したステージが確認出来ます。但し現状だと何も表示されていません。[Enable Directory Table]を押下すると、

先ほどS3にアップロードしたファイルがSnowflake外部ステージ側でも見えるようになりました。いい感じで連携出来ています!

Snowflake外部ステージ上にあるファイルをCOPY INTOコマンドでテーブルにロードすることも出来ました。

CREATE TABLE xxxxxxxxxx.SHINYAA31.sample_table (
  user_id INT,
  name STRING,
  age INT
);

COPY INTO xxxxxxxxxx.SHINYAA31.sample_table
  FROM @TEST_STAGE_SHINYAA31
  PATTERN='sample.csv';

また。階層を深掘る形でS3のバケット配下にフォルダを作成し、そこにファイルを新たにアップロードした場合も、

対応する外部ステージを別途作成することで同様の対応、連携を確認することが出来ました!

CREATE STAGE test_stage_shinyaa31_xx_data
  STORAGE_INTEGRATION = s3_int_xxxxxxxxxx_test
  URL = 's3://snowflake-s3-integration-xxxxxxxxxx-test/xx_data'
  FILE_FORMAT = shinyaa31_csv_format;

まとめ

ということで、ストレージ統合を活用したS3バケットとSnowflakeの連携手順について、その内容を紹介しました。公式ドキュメントの手順もとても分かりやすく、スムーズに作業を進めることが出来ました!運用面を考慮して各種関連オブジェクトの命名規約やS3バケット、Snowflake外部ステージの運用方法等を併せて検討しておくと良いかもしれません。このエントリが何らかの参考になりましたら幸いです。

参考:

truestarテックブログ
設定によりコメント欄が無効化されています