Borderless Lakehouse for Snowflake で BigQuery から Horizon Catalog 上の Iceberg テーブルを参照してみた

Borderless Lakehouse for Snowflake で BigQuery から Horizon Catalog 上の Iceberg テーブルを参照してみた

Google Cloud の Borderless Lakehouse for Snowflake を試してみました。BigQuery から Snowflake の Iceberg テーブルをデータ移行なしで直接クエリできる機能について、WIF認証での設定手順と動作確認をまとめます。
2026.08.05

はじめに

2026年7月に Cross-cloud Lakehouse は、Borderless Lakehouse という名称に変更されました。

https://docs.cloud.google.com/lakehouse/docs/release-notes#July_31_2026

Borderless Lakehouse は、Google Cloud 上で Apache Iceberg 形式のテーブルを管理・参照する Google Cloud Lakehouse のカタログフェデーション機能で、他クラウドプロバイダーに存在する Iceberg テーブルを、データの移行や ETL 処理を行うことなく Google Cloud から直接クエリできるようにするものです。現在プレビューとして提供されています。

これまで、AWS または Google Cloud の外部ロケーションを使用する Databricks Unity Catalog カタログや AWS Glue カタログなどがサポートされていましたが、2026年7月13日のアップデートで、リモートカタログプロバイダーとして Snowflake をサポートするようになりました。

https://docs.cloud.google.com/lakehouse/docs/release-notes#July_13_2026

https://docs.cloud.google.com/lakehouse/docs/about-borderless-lakehouse

この機能を使うと、Snowflake の Horizon カタログに存在する Iceberg テーブルを BigQuery から直接クエリできます。「Borderless Lakehouse for Snowflake」と呼ばれるこの機能を試してみましたので、その際の手順をまとめます。

参考までに、Databricks Unity Catalog・AWS Glue とのフェデレーションについては以下をご参照ください。

https://dev.classmethod.jp/articles/bigquery-unity-catalog-federation-try/

https://dev.classmethod.jp/articles/bigquery-glue-federation-try/

Borderless Lakehouse for Snowflake の概要

本機能の設定手順は以下に記載があります。

https://docs.cloud.google.com/lakehouse/docs/set-up-borderless-lakehouse-snowflake

主なポイントは以下の通りです。

  • BigQuery から Snowflake の Horizon カタログ配下の Iceberg テーブルを直接クエリでき、データの移行や複雑な ETL 処理は不要
  • 認証方式は 2 種類あり、Snowflake 側で発行した PAT(Programmatic Access Tokens)を Secret Manager 経由で渡す方式と、Workload Identity Federation(WIF)方式が選択できる

本記事では、長期的なシークレット管理が不要な WIF 方式で検証しています。

なお逆方向となる、Snowflake から Google Cloud の Lakehouse ランタイムカタログ(旧 BigLake metastore)側の Iceberg テーブルを参照・書き込みする手順は以下の記事で検証しています。

https://dev.classmethod.jp/articles/snowflake-iceberg-rest-catalog-integration-google-cloud-lakehouse-runtime/

両方向のフェデレーションが揃ったことで、データの実体をどちらに置いても、複製や ETL を挟まずに Snowflake・BigQuery の双方から同じ Iceberg テーブルを使い分けられるようになります。

前提条件

検証環境

以下の環境を使用しています。

  • Snowflake:AWS 東京リージョン(ap-northeast-1)上のアカウント
  • Google Cloud:リージョン asia-northeast1

Snowflake アカウントの実体が AWS 東京にあるため、地理的に近い Google Cloud のリージョンとして asia-northeast1 を選択しています。

事前準備

Snowflake 側に検証用のデータベース・スキーマと、Iceberg テーブルを用意しておきます。

Borderless Lakehouse は Iceberg REST Catalog プロトコルで通信するため、BigQuery から参照できるのは Snowflake の通常のネイティブテーブルではなく Iceberg テーブルとなります。

Iceberg テーブルのストレージには、S3 などの外部ボリュームを使う方法のほかに、Snowflake 管理の内部ストレージ(EXTERNAL_VOLUME = 'SNOWFLAKE_MANAGED')を使う方法もあります。こちらは外部クラウドストレージの用意が不要になるため、まずはこの内部ストレージで試してみます。

https://dev.classmethod.jp/articles/snowflake-tables-iceberg-internal-storage-query-try/

はじめに、以下のコマンドで検証用のデータベース・スキーマ、サンプルテーブルを作成しました。

-- 検証用データベース・スキーマ
CREATE DATABASE IF NOT EXISTS SNOWFLAKE_LAKEHOUSE_DB;
CREATE SCHEMA IF NOT EXISTS SNOWFLAKE_LAKEHOUSE_DB.SF_NS;

USE DATABASE SNOWFLAKE_LAKEHOUSE_DB;
USE SCHEMA SF_NS;

-- 動作確認用のサンプル Iceberg テーブル(Snowflake 管理の内部ストレージ)
CREATE ICEBERG TABLE IF NOT EXISTS customers (
  id INT,
  name STRING,
  signup_date DATE
)
CATALOG = 'SNOWFLAKE'
EXTERNAL_VOLUME = 'SNOWFLAKE_MANAGED';

INSERT INTO customers (id, name, signup_date) VALUES
  (1, 'Alice', '2026-01-10'),
  (2, 'Bob',   '2026-02-20'),
  (3, 'Carol', '2026-03-05');

> SELECT * FROM customers ORDER BY id;
+----+-------+-------------+
| ID | NAME  | SIGNUP_DATE |
|----+-------+-------------|
|  1 | Alice | 2026-01-10  |
|  2 | Bob   | 2026-02-20  |
|  3 | Carol | 2026-03-05  |
+----+-------+-------------+

> SHOW ICEBERG TABLES
    ->> SELECT "name", "database_name", "schema_name", "external_volume_name", "catalog_name", "iceberg_table_format_version" FROM $1;
+-----------+------------------------+-------------+----------------------+--------------+------------------------------+
| name      | database_name          | schema_name | external_volume_name | catalog_name | iceberg_table_format_version |
|-----------+------------------------+-------------+----------------------+--------------+------------------------------|
| CUSTOMERS | SNOWFLAKE_LAKEHOUSE_DB | SF_NS       | SNOWFLAKE_MANAGED    | SNOWFLAKE    |                            2 |
+-----------+------------------------+-------------+----------------------+--------------+------------------------------+

Google Cloud 側の設定

Google Cloud 側の設定手順は以下に記載があるので、こちらに沿って進めます。

https://docs.cloud.google.com/lakehouse/docs/set-up-borderless-lakehouse-snowflake

API の有効化

BigLake の API を有効化します。WIF 方式の場合、Secret Manager の API は不要です。

以降のコマンドで使う変数もあわせて定義しておきます。

export PROJECT_ID="<プロジェクトID>"
export REGION="asia-northeast1"
export CATALOG_NAME="federated-catalog" # 任意の名称
export SNOWFLAKE_ACCOUNT_ID="<Snowflakeアカウント識別子>" # <組織-アカウント名>の方式
export SNOWFLAKE_DB_NAME="SNOWFLAKE_LAKEHOUSE_DB"   
export SNOWFLAKE_ROLE="LAKEHOUSE_FEDERATION_ROLE"

gcloud services enable biglake.googleapis.com --project="$PROJECT_ID"

フェデレーションカタログを作成

gcloud alpha biglake iceberg catalogs create でフェデレーションカタログを作成します。--federated-catalog-typesnowflake を指定し、Snowflake のアカウント識別子・ウェアハウス(連携先のデータベース名)・ロールを指定します。

gcloud alpha biglake iceberg catalogs create "$CATALOG_NAME" \
  --project="$PROJECT_ID" \
  --primary-location="$REGION" \
  --catalog-type="federated" \
  --federated-catalog-type="snowflake" \
  --snowflake-account-identifier="$SNOWFLAKE_ACCOUNT_ID" \
  --snowflake-warehouse="$SNOWFLAKE_DB_NAME" \
  --snowflake-role="$SNOWFLAKE_ROLE" \
  --refresh-interval="5m"

ここで、--snowflake-warehouse という名前から Snowflake の仮想ウェアハウス名ではなく、カタログとして公開する Snowflake のデータベース名を指定する必要がある点にご注意ください。

実行結果は以下のようになり、作成後の BigLake service account が表示されます。

Created catalog [projects/<プロジェクトID>/catalogs/federated-catalog].
BigLake service account: blirc-xxxxxxxxxxxxx-xxxx@gcp-sa-biglakerestcatalog.iam.gserviceaccount.com
BigLake service account ID: xxxxxxxxxxxxxxxxxxxx

BigLake サービスアカウント ID を取得

catalogs describe で、後続の Snowflake 側の手順で使用するサービスアカウント ID を確認します。

gcloud alpha biglake iceberg catalogs describe "$CATALOG_NAME" \
  --project="$PROJECT_ID"
biglake-service-account: blirc-xxxxxxxxxxxxx-xxxx@gcp-sa-biglakerestcatalog.iam.gserviceaccount.com
biglake-service-account-id: 'xxxxxxxxxxxxxxxxxxxx'
catalog-type: CATALOG_TYPE_FEDERATED
credential-mode: CREDENTIAL_MODE_VENDED_CREDENTIALS
federated-catalog-options:
  snowflake-catalog-info:
    account-identifier: <Snowflakeアカウント識別>
    snowflake-role: LAKEHOUSE_FEDERATION_ROLE
    warehouse: SNOWFLAKE_LAKEHOUSE_DB
...

ここで credential-modeCREDENTIAL_MODE_VENDED_CREDENTIALS になっていました。これにより Google Cloud 側でストレージの認証情報を個別に設定しなくても、Snowflake 側が一時的な認証情報を払い出してくれる方式であることがわかります。

Snowflake 側でサービスユーザーを作成

BigLake のサービスアカウント ID が確定したので、Snowflake 側に WIF 用のサービスユーザーを作成します。

-- フェデレーション専用ロール
CREATE ROLE IF NOT EXISTS LAKEHOUSE_FEDERATION_ROLE;

CREATE USER SNOWFLAKE_SERVICE_USER
  TYPE = SERVICE
  WORKLOAD_IDENTITY = (
    TYPE = GCP
    SUBJECT = '<biglake-service-account-id>'
  )
  DEFAULT_ROLE = LAKEHOUSE_FEDERATION_ROLE;

GRANT ROLE LAKEHOUSE_FEDERATION_ROLE TO USER SNOWFLAKE_SERVICE_USER;

-- 対象 DB・スキーマ・ウェアハウスへの参照権限を付与
GRANT USAGE ON WAREHOUSE COMPUTE_WH TO ROLE LAKEHOUSE_FEDERATION_ROLE;
GRANT USAGE ON DATABASE SNOWFLAKE_LAKEHOUSE_DB TO ROLE LAKEHOUSE_FEDERATION_ROLE;
GRANT USAGE ON SCHEMA SNOWFLAKE_LAKEHOUSE_DB.SF_NS TO ROLE LAKEHOUSE_FEDERATION_ROLE;
GRANT SELECT ON ALL ICEBERG TABLES IN SCHEMA SNOWFLAKE_LAKEHOUSE_DB.SF_NS TO ROLE LAKEHOUSE_FEDERATION_ROLE;
GRANT SELECT ON FUTURE ICEBERG TABLES IN SCHEMA SNOWFLAKE_LAKEHOUSE_DB.SF_NS TO ROLE LAKEHOUSE_FEDERATION_ROLE;

接続確認

権限付与後、ネームスペース一覧を確認します。

gcloud alpha biglake iceberg namespaces list \
  --catalog="$CATALOG_NAME" --project="$PROJECT_ID"
NAME: projects/<プロジェクトID>/catalogs/federated-catalog/namespaces/SF_NS
NAMESPACE-ID: SF_NS

Snowflake 側で作成したスキーマがネームスペースとして認識されていることが確認できました。BigQuery のコンソール上でもデータセットとして認識されています。

20260805155549

20260805155712

4 階層名(プロジェクト.カタログ.ネームスペース.テーブル)で直接クエリしてみます。

SELECT * FROM `<プロジェクトID>.federated-catalog.SF_NS.customers` LIMIT 1000;

Snowflake 側で投入したレコードを BigQuery からストレージの認証情報設定は不要で参照できました。

20260805155814

BigQuery からの書き込みを試してみる

本機能では BigQuery からの直接の書き込みはできません。実際に試してみます。

INSERT INTO `<プロジェクトID>.federated-catalog.SF_NS.customers` (id, name, signup_date)
VALUES (4, 'Dave', '2026-04-15');

想定通り、BigQuery 側からの DML 操作は許可されませんでした。

20260805160257

Snowflake 側でのデータ更新の反映確認

Snowflake 側で加えた変更が refresh-interval の経過後に BigQuery 側へ反映されるかを確認します。

既存テーブルへのレコード追加

USE DATABASE SNOWFLAKE_LAKEHOUSE_DB;
USE SCHEMA SF_NS;

INSERT INTO customers (id, name, signup_date) VALUES
  (4, 'Dave', '2026-04-15');

refresh-interval 経過後、BigQuery 側で追加したレコードが取得できることを確認できました。

20260805161123

新規テーブルの作成

続けて、Snowflake 側にスキーマ作成後に新しく Iceberg テーブルを追加した場合も確認します。

USE DATABASE SNOWFLAKE_LAKEHOUSE_DB;
USE SCHEMA SF_NS;

CREATE ICEBERG TABLE IF NOT EXISTS orders (
  order_id INT,
  amount NUMBER(10,2)
)
CATALOG = 'SNOWFLAKE'
EXTERNAL_VOLUME = 'SNOWFLAKE_MANAGED';

INSERT INTO orders (order_id, amount) VALUES
  (100, 1980.00);

新規テーブルも BigQuery 側から参照できました。

20260805162202

ログイン履歴の確認

WIF による接続はログイン履歴からも確認できました。

> SELECT event_timestamp, event_type, is_success, client_ip, reported_client_type, first_authentication_factor
FROM SNOWFLAKE.ACCOUNT_USAGE.LOGIN_HISTORY
WHERE user_name = 'SNOWFLAKE_SERVICE_USER'
ORDER BY event_timestamp DESC
LIMIT 1;
+-------------------------------+------------+------------+-----------+----------------------+-----------------------------+
| EVENT_TIMESTAMP               | EVENT_TYPE | IS_SUCCESS | CLIENT_IP | REPORTED_CLIENT_TYPE | FIRST_AUTHENTICATION_FACTOR |
|-------------------------------+------------+------------+-----------+----------------------+-----------------------------|
| 2026-08-05 00:23:10.302 -0700 | LOGIN      | YES        | 0.0.0.0   | OTHER                | WORKLOAD_IDENTITY           |
+-------------------------------+------------+------------+-----------+----------------------+-----------------------------+

External Volume(S3)でも試してみる

ここまでは Snowflake 管理の内部ストレージ(SNOWFLAKE_MANAGED)で検証してきましたが、外部ボリューム(S3)を使う通常の Iceberg テーブルでも同様に参照できるかを確認します。Snowflake アカウントの実体が AWS 東京にあるため、外部ボリュームも S3 で構成します。

Snowflake 側で External Volume を作成します。STORAGE_AWS_ROLE_ARN はこの時点ではまだ存在しない IAM ロールでもよく、あとから DESC EXTERNAL VOLUME で払い出される STORAGE_AWS_IAM_USER_ARN / STORAGE_AWS_EXTERNAL_ID を使って AWS 側のロールを作成・信頼設定します。

CREATE OR REPLACE EXTERNAL VOLUME SF_LAKEHOUSE_EXT_VOL
  STORAGE_LOCATIONS = (
    (
      NAME = 'sf-lakehouse-s3'
      STORAGE_PROVIDER = 'S3'
      STORAGE_BASE_URL = 's3://<バケット名>/sf-ext-vol/'
      STORAGE_AWS_ROLE_ARN = 'arn:aws:iam::<AWSアカウントID>:role/<ロール名>'
    )
  );

DESC EXTERNAL VOLUME SF_LAKEHOUSE_EXT_VOL;

DESC で得られた値を使って、AWS 側で信頼ポリシー・S3 アクセスポリシーを設定した IAM ロールを作成します。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "<STORAGE_AWS_IAM_USER_ARN>"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "sts:ExternalId": "<STORAGE_AWS_EXTERNAL_ID>"
        }
      }
    }
  ]
}

IAMポリシーは以下のようにしました。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowSnowflakeS3Access",
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:GetObjectVersion",
        "s3:PutObject",
        "s3:DeleteObject",
        "s3:ListBucket",
        "s3:GetBucketLocation"
      ],
      "Resource": [
        "arn:aws:s3:::<バケット名>/sf-ext-vol/*",
        "arn:aws:s3:::<バケット名>"
      ]
    }
  ]
}

External Volume を使う Iceberg テーブルを作成します。

USE DATABASE SNOWFLAKE_LAKEHOUSE_DB;
USE SCHEMA SF_NS;

CREATE ICEBERG TABLE IF NOT EXISTS customers_ext (
  id INT,
  name STRING,
  signup_date DATE
)
CATALOG = 'SNOWFLAKE'
EXTERNAL_VOLUME = 'SF_LAKEHOUSE_EXT_VOL'
BASE_LOCATION = 'customers_ext/';

INSERT INTO customers_ext (id, name, signup_date) VALUES
  (1, 'Alice', '2026-01-10'),
  (2, 'Bob',   '2026-02-20');

S3 側にもデータ・メタデータが作成されていることが確認できます。

20260805164337

SNOWFLAKE_MANAGED のときとの違いとして、External Volume の場合はテーブルへの SELECT 権限に加え、ボリューム自体への USAGE 権限もロールに付与する必要があります。

GRANT USAGE ON EXTERNAL VOLUME SF_LAKEHOUSE_EXT_VOL TO ROLE LAKEHOUSE_FEDERATION_ROLE;

refresh-interval 経過後、BigQuery 側からも問題なく参照できました。

20260805164910

20260805165007

Google Cloud 側では S3 の認証情報を一切設定していないにもかかわらず参照できたことから、SNOWFLAKE_MANAGED のときと同じく、Snowflake 側が一時的なストレージ認証情報を払い出す vended credentials の仕組みで動作しているものと考えられます。

さいごに

Borderless Lakehouse for Snowflake のカタログフェデーション機能を使用して、Snowflake の Horizon カタログにある Iceberg テーブルを Google Cloud の BigQuery から直接参照する手順を確認してみました。

ストレージが Snowflake 管理の内部ストレージでも、S3 の External Volume でも、Google Cloud 側でストレージの認証情報を個別に設定することなく参照できました。

こちらの内容がどなたかの参考になれば幸いです。


Snowflake World Tour Tokyo 2026に参加しませんか?

Snowflakeの国内最大級イベント「Snowflake World Tour Tokyo」が2026年9月10日(水)・11日(木)にグランドプリンスホテル新高輪にて開催されます。
最新のAI・データ活用事例やライブデモを体感できる無料イベントです。

Snowflake World Tour Tokyoイベントに参加する


Snowflakeの導入支援はクラスメソッドに!

クラスメソッドでは Snowflake の導入を支援しております。
製品の詳細や支援の内容についてお気軽にお問い合わせください。

Snowflakeの詳細を見る

この記事をシェアする

関連記事