LoginSignup
4
2

More than 1 year has passed since last update.

Azure Databricks と Azure Data Lake Storage Gen 2の接続について

Last updated at Posted at 2023-03-03
1 / 31

はじめに

Unity Catalog が出たことで色々とアップデートが必要だったので Azure Databricks と Azure Data Lake Storage Gen2への接続のパターンについてまとめ

Azure Databricks と Azure Data Lake Storage Gen 2上のデータを扱ううえでは、アクセス方法認証方法ネットワーク構成方法の3点が重要となるためこれを解説する

Azure Data Lake Storage Gen 2 と Azure Blob Storage の表記の使い分けについて

  • Azure Data Lake Storage Gen 2 はAzure Blob Storage の拡張機能となるので、Azure Blob Storage でも利用可能な部分に関しては、Azure Blob Storage と表記

アクセス方法

Databricks では、データへのアクセス方法はテーブルアクセス or ファイルアクセス と大きく二つの方法にわかれる


テーブルアクセス

テーブル名によるアクセスはレイクハウス上で標準的な方法となる

pyspark
    
    # 構文:spark.table("<table name>") 
    spark.table("default.mytable") 
    
sql
    -- 構文:SELECT * FROM <table name> 
    SELECT * FROM default.mytable 


テーブルが対象としているパスについてはマネージドテーブルかアンマネージドテーブルかに左右され、アンマネージドテーブルの時にはパスを指定することになる(参考

  • アンマネージドテーブル
sql

/*
構文:
CREATE TABLE my_table LOCATION '<path>' 
USING <format>
*/ 
 
CREATE TABLE my_table LOCATION 'abfss://container@storageAccount.dfs.core.windows.net/external-location/path/to/table'
USING DELTA

  • マネージドテーブルでは、あらかじめ環境に指定されるストレージで自動的にディレクトリが形成されるため、ユーザーが意識することはない
    • マネージドテーブル(非Unity Catalog 環境)であればDatabricksに既定で付属するストレージ上に保管される
    • マネージドテーブル(Unity Catalog 環境)であればUnity Catalog で指定したメタストア用ストレージ内に保管される
sql

CREATE TABLE my_table 
USING DELTA


ファイルパスによるアクセス

投入対象など、テーブル化されていないデータにアクセスするのに利用する
※投入対象をアンマネージドテーブルとして管理する方法もとれる

pyspark

    # 構文:spark.read.format("<path>")
    spark.read.format("abfss://container@storageAccount.dfs.core.windows.net/external-location/path/to/table")

sql

    -- 構文:SELECT * FROM <ファイル形式>.`<path>` 
    SELECT * FROM delta.`abfss://container@storageAccount.dfs.core.windows.net/external-location/path/to/table>` 


ファイルパスに利用できるデータレイクのパス

クラウドストレージに一般的な方法である URL形式(ABFS URI) か、 マウント によりローカルファイルシステムのようにアクセスする


ABFS URI

Azure Blob Storage 上のデータを示すURIを直接記入する(推奨)
参考:Azure Data Lake Storage Gen2 の URI を使用する

pyspark

#  path構文:abfss://<container name>@<storage account name>.dfs.core.windows.net/<path>

spark.read.format("delta").load("abfss://container@storageAccount.dfs.core.windows.net/external-location/path/to/data")

Azure Blob Storage の場合、WASB URI として、wasbs://{container name}@{storage account name}.blob.core.windows.net/{path} と記載することになるが、Azure Databricks では現在 WASB URIを利用することは非推奨となった。

Microsoft は、Azure Blob File System ドライバー (ABFS) を優先することに伴って Azure Blob Storage 用の Windows Azure Storage Blob ドライバー (WASB) を非推奨にしました。

引用:WASB (レガシ) を使用した Azure Blob Storage への接続


DBFS マウントパス

あらかじめ Azure Storage 上のディレクトリをDatabricksファイルシステム上にマウントする。
これにより、ストレージアカウントを含めたURLや、認証情報などを spark のセッション内でコンフィグに設定したり把握せずにアクセスできる

現在Unity Catalog により、ストレージへの認証を一元管理し、監査を取得することが推奨の構成となったため、Unity Catalog の監査対象外となってしまうマウントパターンは非推奨。

Databricks では、マウントの使用からの移行と、Unity カタログを使用したデータ ガバナンスの管理を推奨しています。

引用:Azure Databricks へのクラウド オブジェクト ストレージのマウント

誰かが一度マウントすれば、ほかのユーザーはコンフィグ設定などが不要となるという点で取りまわしが楽になるため、非 Unity Catalog 環境ではマウント方式を利用するケースは多い。

ただし大きな欠点として、サービスプリンシパルが必要となり、サービスプリンシパルが用意できない場合、非推奨であるWASBドライバーでのマウントが必要。


pyspark

## マウント構文

# dbutils.fs.mount(
# source = "abfss://<container name>@<storage account name>.dfs.core.windows.net/", 
# mount_point = "/mnt/<path>", 
# extra_configs = configs)

# マウント例

configs = {
  "fs.azure.account.auth.type": "CustomAccessToken",
  "fs.azure.account.custom.token.provider.class": spark.conf.get("spark.databricks.passthrough.adls.gen2.tokenProviderClassName")
}

dbutils.fs.mount(
source = "abfss://data@storageAccount.dfs.core.windows.net/", 
mount_point = "/mnt/adls/data", 
extra_configs = configs)

# 読み取り

spark.read.format("delta").load("dbfs:/mnt/adls/data/mydir")



認証について

データ利用時のアクセス方式については以上の通りだが、それぞれの方式で認証方式がさらに選択可能

  1. Unity Catalog の External Location および、Storage Credentialsを利用する  (推奨)
  2. 従来の方法
    2-1. 資格情報を Spark Conf に設定する
    2-2. マウント時に資格情報をマウント用のconfig として設定する

Unity Catalog の External Location および、Storage Credentialsを利用する

Unity Catalog 上で、External Location について権限をもつユーザーが資格情報を指定せずにアクセス可能とする方式

方式イメージ:

image.png

Pros:Unity Catalogによる完全なガバナンス
Cons:Unity Catalogのセットアップが必要となり、構成の難易度が高い


Unity Catalog メタストアに割当てられた Databricks では、このようにストレージ資格情報欄から資格情報を作成できる

image.png

image.png

資格情報が作成できたら、External Locationを作成する

image.png


コードで実行する場合、構文は以下の通り

sql

CREATE EXTERNAL LOCATION <location_name>
URL 'abfss://<container_name>@<storage_account>.dfs.core.windows.net/<path>'
WITH (STORAGE CREDENTIAL <storage_credential_name>);

各オブジェクトはGRANTにより、ユーザーに利用許可を与えられるが、Storage Credential を直接ユーザーに利用させるよりも、視覚情報とパスとの組み合わせとなる、External location をユーザーに利用させることが推奨となる

ストレージの資格情報に対してアクセス許可を直接付与できますが、Databricks では外部の場所でこれを参照し、代わりにアクセス許可を付与することをお勧めします。

引用:ストレージの資格情報のアクセス許可を管理する

External locationで権限が与えられたユーザーはストレージへの認証情報を構成することなくABFS URIでファイルアクセスが可能となります。

sql

-- 外部の場所を使用してテーブルを作成するアクセス許可を付与する
GRANT CREATE EXTERNAL TABLE ON EXTERNAL LOCATION <location_name> TO <principal>;

-- 外部の場所からファイルを読み取るアクセス許可を付与する
GRANT READ FILES ON EXTERNAL LOCATION <location_name> TO <principal>;




従来の認証方法

従来の方法では、データレイクへアクセスするための構成情報をノートブックなどを通してUnity Catalog ではなくSpark Conf上などで定義することでアクセスする
※Unity Catalog 環境下では、External Location で管理している場所にABFS URI アクセスする場合、Spark Conf などで定義した認証用の構成情報は無視される

認証方式の違いで構成内容が分岐する


サービスプリンシパルを利用してアクセスする

サービスプリンシパルをデータアクセス用の代理IDとする方式

方式イメージ:

image.png

Pros:Azure AD認証およびAzure RBACでデータアクセス制御可能なため、Azure Data Lake Storage Gen2 のフォルダ、ファイル単位のアクセス制御を利用可能
Cons:ユーザー個々で認証されるわけではないので、データアクセスの監査はサービスプリンシパル単位となる


設定する構成情報

対象 ABFSアクセス の場合 対象 マウントの場合 備考
fs.azure.account.auth.type.{storage-account名}.dfs.core.windows.net fs.azure.account.auth.type.{storage-account名}.dfs.core.windows.net OAuth
fs.azure.account.oauth.provider.type.{storage-account名}.dfs.core.windows.net fs.azure.account.oauth.provider.type.{storage-account名}.dfs.core.windows.net org.apache.hadoop.fs.azurebfs.oauth2.ClientCredsTokenProvider
fs.azure.account.oauth2.client.id fs.azure.account.oauth2.client.id サービスプリンシパルのアプリケーションID
fs.azure.account.oauth2.client.secret fs.azure.account.oauth2.client.secret サービスプリンシパルのシークレット Databricksシークレットに格納することを推奨
fs.azure.account.oauth2.client.endpoint fs.azure.account.oauth2.client.endpoint https://login.microsoftonline.com/{サービスプリンシパルの存在するテナントID}/oauth2/token

あらかじめ、サービスプリンシパルの作成と、ストレージへの権限付与が必要。
参考:Azure Active Directory を使ってストレージにアクセスする


なお、SQL ウェアハウスの場合は類似の構成情報をSQL管理コンソールで登録することになる。

参考:データ アクセスの構成

image.png


SASトークン or アカウントキーを利用してアクセスする

ストレージアカウントで払出されるトークンかキーを使用して認証する方式

方式イメージ:
image.png

Pros:セットアップが簡単
Cons:Azure AD認証ではなく、ストレージ側での認証となり、ファイル、フォルダレベルのきめ細かいアクセス制御は不可となる。特にアカウントキーはストレージアカウント全体に対する全操作が可能なので注意。また、マウント時に非推奨のWASBドライバーを通してBlobを使う必要がある


SASトークンの場合

設定する構成情報

対象 ABFSアクセス の場合 対象 マウントの場合※blob利用 備考
fs.azure.account.auth.type.{storage-account名}.dfs.core.windows.net - SAS
fs.azure.sas.token.provider.type.{storage-account名}.dfs.core.windows.net - org.apache.hadoop.fs.azurebfs.sas.FixedSASTokenProvider
fs.azure.sas.fixed.token.{storage-account名}.dfs.core.windows.net fs.azure.sas.{コンテナ名}.{storage-account名}.blob.core.windows.net SASトークンの値

アカウント キーの場合

設定する構成情報

対象 ABFSアクセス の場合 対象 マウントの場合※blob利用 備考
fs.azure.account.key.{storage-account名}.dfs.core.windows.net fs.azure.account.key.{storage-account名}.blob.core.windows.net アカウントキーの値

Azure AD 資格情報パススルーを利用してアクセスする

方式イメージ:

image.png

Pros:ユーザー個々にシークレットなどの構成情報を与える必要がなく、Azure AD 認証を使用しているので、ファイル、フォルダレベルのきめ細かいアクセス制御が可能
Cons:Azure Blob Storageでは、資格情報のパススルーはサポートされていない。


設定する構成情報

資格情報パススルー対応クラスターでは、ABFSアクセスの場合にはspark confの構成は特に不要

対象 ABFSアクセス の場合 対象 マウントの場合 備考
- fs.azure.account.auth.type CustomAccessToken
- fs.azure.account.custom.token.provider.class spark.conf.get("spark.databricks.passthrough.adls.gen2.tokentaProviderClassName")

※資格情報パススルー対応クラスターは以下のチェックボックスをオンにする

image.png


(チートシート)従来の認証用の構文と利用例

サービスプリンシパル

ABFS URI アクセス

構文:

pyspark

service_credential = dbutils.secrets.get(scope="<scope>",key="<service-credential-key>")

spark.conf.set("fs.azure.account.auth.type.<storage-account>.dfs.core.windows.net", "OAuth")
spark.conf.set("fs.azure.account.oauth.provider.type.<storage-account>.dfs.core.windows.net", "org.apache.hadoop.fs.azurebfs.oauth2.ClientCredsTokenProvider")
spark.conf.set("fs.azure.account.oauth2.client.id.<storage-account>.dfs.core.windows.net", "<application-id>")
spark.conf.set("fs.azure.account.oauth2.client.secret.<storage-account>.dfs.core.windows.net", service_credential)
spark.conf.set("fs.azure.account.oauth2.client.endpoint.<storage-account>.dfs.core.windows.net", "https://login.microsoftonline.com/<directory-id>/oauth2/token")


使用例:

pyspark

service_credential = dbutils.secrets.get(scope="akv",key="hoge01-secret")

spark.conf.set("fs.azure.account.auth.type.hogeStorageAccount.dfs.core.windows.net", "OAuth")
spark.conf.set("fs.azure.account.oauth.provider.type.hogeStorageAccount.dfs.core.windows.net", "org.apache.hadoop.fs.azurebfs.oauth2.ClientCredsTokenProvider")
spark.conf.set("fs.azure.account.oauth2.client.id.hogeStorageAccount.dfs.core.windows.net", "hogeappid99009>")
spark.conf.set("fs.azure.account.oauth2.client.secret.hogeStorageAccount.dfs.core.windows.net", service_credential)
spark.conf.set("fs.azure.account.oauth2.client.endpoint.<storage-account>.dfs.core.windows.net", "https://login.microsoftonline.com/hogetenantid0000/oauth2/token")

df = spark.read.format("delta").load("abfss://data@hogeStorageAccount.dfs.core.windows.net/external-location/path/to/data/")


マウントによるアクセス

構文:

pyspark

configs = {"fs.azure.account.auth.type": "OAuth",
          "fs.azure.account.oauth.provider.type": "org.apache.hadoop.fs.azurebfs.oauth2.ClientCredsTokenProvider",
          "fs.azure.account.oauth2.client.id": "<application-id>",
          "fs.azure.account.oauth2.client.secret": dbutils.secrets.get(scope="<scope-name>",key="<service-credential-key-name>"),
          "fs.azure.account.oauth2.client.endpoint": "https://login.microsoftonline.com/<directory-id>/oauth2/token"}

# Optionally, you can add <directory-name> to the source URI of your mount point.
dbutils.fs.mount(
    source = "abfss://<container-name>@<storage-account-name>.dfs.core.windows.net/<path>",
    mount_point = "/mnt/<mount-name>",
    extra_configs = configs)

使用例:

pyspark

configs = {"fs.azure.account.auth.type": "OAuth",
          "fs.azure.account.oauth.provider.type": "org.apache.hadoop.fs.azurebfs.oauth2.ClientCredsTokenProvider",
          "fs.azure.account.oauth2.client.id": "hogeappid99009",
          "fs.azure.account.oauth2.client.secret": dbutils.secrets.get(scope="akv",key="hoge01-secret")),
          "fs.azure.account.oauth2.client.endpoint": "https://login.microsoftonline.com/hogetenantid0000/oauth2/token"}

dbutils.fs.mount(
    source = "abfss://data@hogeStorageAccount.dfs.core.windows.net/", 
    mount_point = "/mnt/adls/data", 
    extra_configs = configs)

df = spark.read.format("delta").load("dbfs:/mnt/adls/data/external-location/path/to/data/")

SASトークン

ABFS URI アクセス

構文:

pyspark
spark.conf.set("fs.azure.account.auth.type.<storage-account>.dfs.core.windows.net", "SAS")
spark.conf.set("fs.azure.sas.token.provider.type.<storage-account>.dfs.core.windows.net", "org.apache.hadoop.fs.azurebfs.sas.FixedSASTokenProvider")
spark.conf.set("fs.azure.sas.fixed.token.<storage-account>.dfs.core.windows.net", "<token>")

使用例:

pyspark

sas_token = dbutils.secrets.get(scope="akv",key="hoge01-sas")

spark.conf.set("fs.azure.account.auth.type.hogeStorageAccount.dfs.core.windows.net", "SAS")
spark.conf.set("fs.azure.sas.token.provider.type.hogeStorageAccount.dfs.core.windows.net", "org.apache.hadoop.fs.azurebfs.sas.FixedSASTokenProvider")
spark.conf.set("fs.azure.sas.fixed.token.hogeStorageAccount.dfs.core.windows.net", sas_token)

df = spark.read.format("delta").load("abfss://data@hogeStorageAccount.dfs.core.windows.net/external-location/path/to/data/")


マウントによるアクセス

構文:

pyspark

configs = {"fs.azure.sas.<container>.<storage-account>.blob.core.windows.net": <token>}
dbutils.fs.mount(
    source = "wasbs://<container>@<storage-account>.blob.core.windows.net/<path>", 
    mount_point = "/mnt/<mount-name>",
    extra_configs = configs)

使用例:

pyspark

sas_token = dbutils.secrets.get(scope="akv",key="hoge01-sas")

configs = {"fs.azure.sas.data.hogeStorageAccount.blob.core.windows.net": sas_token}

dbutils.fs.mount(
    source = "abfss://data@hogeStorageAccount.dfs.core.windows.net/", 
    mount_point = "/mnt/adls/data", 
    extra_configs = configs)

df = spark.read.format("delta").load("dbfs:/mnt/adls/data/external-location/path/to/data/")

アカウント キー

ABFS URI アクセス

構文:

pyspark

spark.conf.set("fs.azure.account.key.<storage-account>.dfs.core.windows.net","<storage-account-access-key>")

使用例:

pyspark

key = dbutils.secrets.get(scope="akv",key="hoge01-key")
spark.conf.set("fs.azure.account.key.<storage-account>.dfs.core.windows.net",key)

df = spark.read.format("delta").load("abfss://data@hogeStorageAccount.dfs.core.windows.net/external-location/path/to/data/")


マウントによるアクセス

構文:

pyspark

configs = {"fs.azure.account.key.hogeStorageAccount.blob.core.windows.net": "<storage-account-access-key>"}

dbutils.fs.mount(
    source = "wasbs://<container>@<storage-account>.blob.core.windows.net/<path>", 
    mount_point = "/mnt/<mount-name>",
    extra_configs = configs)

使用例:

pyspark

key = dbutils.secrets.get(scope="akv",key="hoge01-key")
configs = {"fs.azure.account.key.hogeStorageAccount.blob.core.windows.net": key}

dbutils.fs.mount(
    source = "wasbs://data@hogeStorageAccount.blob.core.windows.net/", 
    mount_point = "/mnt/adls/data", 
    extra_configs = configs)

df = spark.read.format("delta").load("dbfs:/mnt/adls/data/external-location/path/to/data/")

Azure AD 資格情報パススルー

ABFS URI アクセス

Spark conf 設定などの構文はない

使用例:

pyspark

df = spark.read.format("delta").load("abfss://data@hogeStorageAccount.dfs.core.windows.net/external-location/path/to/data/")

マウントによるアクセス

構文:

pyspark

configs = {
  "fs.azure.account.auth.type": "CustomAccessToken",
  "fs.azure.account.custom.token.provider.class": spark.conf.get("spark.databricks.passthrough.adls.gen2.tokenProviderClassName")
}

dbutils.fs.mount(
    source = "abfss://<container-name>@<storage-account-name>.dfs.core.windows.net/",
    mount_point = "/mnt/<mount-name>",
    extra_configs = configs)

使用例:

pyspark

configs = {
  "fs.azure.account.auth.type": "CustomAccessToken",
  "fs.azure.account.custom.token.provider.class": spark.conf.get("spark.databricks.passthrough.adls.gen2.tokenProviderClassName")
}

dbutils.fs.mount(
    source = "wasbs://data@hogeStorageAccount.dfs.core.windows.net/", 
    mount_point = "/mnt/adls/data", 
    extra_configs = configs)

df = spark.read.format("delta").load("dbfs:/mnt/adls/data/external-location/path/to/data/")


ネットワーク構成について

対象のStorage Account がファイアウォールの背後にある場合、Azure Databricks のクラスターからのネットワークアクセスを構成する必要がある


Vnet インジェクション

通常、Azure Databricks は自動生成されるマネージドリソースグループ内のVnet でクラスタを動作させるが、Vnetインジェクションを用いることで、クラスターが動作するVnetを変更管理することが可能となる

参考:仮想ネットワークの管理

image.png


データストアにアクセスするための構成

Vnet インジェクションで Azure Databricks をデプロイした後は、データストアにアクセスさせる方式により、サービスエンドポイントか、プライベートエンドポイントを構成することでファイアウォールの背後のデータにアクセスすることが可能

image.png


Vnet ピアリング

通常はロックされているVnetだが、ピアリング設定のみ可能。VNet インジェクションを構成していない場合にはこちらが利用可能
ただし、基本的に閉域網へのアクセスはVnet インジェクションの構成が推奨される。

また、ピアリング先のNW内の資産へのアクセスにはDNS構成を設定する必要がある

image.png


なお、Vnet の管理をしたくないが、ファイアウォールの背後のデータストアにアクセスしたい場合には、この構成でピアリングされたNWに、Azure Private DNS Resolver と対象のデータストアプライベートエンドポイントを配置し、以下のようなinit スクリプトでクラスタを起動することでアクセスができることを確認済み。

bash

#!/bin/bash
mv /etc/resolv.conf /etc/resolv.conf.orig
echo nameserver <Private DNS Resolver の受信エンドポイントIP>| sudo tee --append /etc/resolv.conf

実際にやってみた記事はこちら:https://qiita.com/ryoma-nagata/items/1dbf250125bc9b767392


サーバーレス SQL ウェアハウスからのアクセスの許可

サーバーレス SQL ウェアハウスは Microsoft サブスクリプション内のマルチテナントなクラスターからのアクセスとなるので、このクラスターの存在するサブネットからのアクセス許可を設定することで、疎通させる。

image.png

実際にやってみた記事はこちら:https://qiita.com/ryoma-nagata/items/5cc56db7aa355ffe5ff5


その他参考リンク集

クラスター UI の変更とクラスター アクセス モード
Azure Data Lake Storage Gen2 と Blob Storage にアクセスする
Unity Catalog のベスト プラクティス
クラスター構成オプションの管理
クラスター ノード初期化スクリプト
Data Exfiltration Protection with Azure Databricks

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2