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

## はじめに

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 **ファイルアクセス** と大きく二つの方法にわかれる

---------------------------------------

### テーブルアクセス

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

``` python:pyspark
    
    # 構文：spark.table("<table name>") 
    spark.table("default.mytable") 
    
```

```sql:sql
    -- 構文：SELECT * FROM <table name>　
    SELECT * FROM default.mytable　

```

---------------------------------------


テーブルが対象としているパスについてはマネージドテーブルかアンマネージドテーブルかに左右され、アンマネージドテーブルの時にはパスを指定することになる（[参考](https://qiita.com/ryoma-nagata/items/300ae6df431642bc9919#%E3%83%9E%E3%83%8D%E3%83%BC%E3%82%B8%E3%83%89-%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E3%81%A8%E5%A4%96%E9%83%A8%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6)）
- アンマネージドテーブル
```sql: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:sql

CREATE TABLE my_table 
USING DELTA

```

---------------------------------------



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

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

```python:pyspark

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

```

```sql: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 を使用する](https://learn.microsoft.com/ja-jp/azure/storage/blobs/data-lake-storage-introduction-abfs-uri)


``` python: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 への接続](https://learn.microsoft.com/ja-jp/azure/databricks/storage/wasb-blob)

---------------------------------------


### [DBFS マウントパス](https://learn.microsoft.com/ja-jp/azure/databricks/dbfs/mounts)

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

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

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

引用：[Azure Databricks へのクラウド オブジェクト ストレージのマウント](https://learn.microsoft.com/ja-jp/azure/databricks/dbfs/mounts)

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

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


---------------------------------------



```python: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を利用する](https://learn.microsoft.com/ja-jp/azure/databricks/data-governance/unity-catalog/manage-external-locations-and-credentials)  　（推奨）**
2. 従来の方法
    2-1. **資格情報を Spark Conf に設定する**
    2-2. **マウント時に資格情報をマウント用のconfig として設定する**


---------------------------------------



### [Unity Catalog の External Location および、Storage Credentialsを利用する](https://learn.microsoft.com/ja-jp/azure/databricks/data-governance/unity-catalog/manage-external-locations-and-credentials) 

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

方式イメージ：

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/54d01473-2258-57ad-b8b3-4fcae075e488.png)

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


---------------------------------------



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

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/0f8a0af0-5e9a-9738-9862-26b1dd7b3472.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/7c15db5b-e22e-ec74-84fb-426d8f7e7b84.png)

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

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/572452f7-4d3c-ab3a-7047-c2c52f853945.png)

---------------------------------------



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

```sql: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 では外部の場所でこれを参照し、代わりにアクセス許可を付与することをお勧めします。 

引用：[ストレージの資格情報のアクセス許可を管理する](https://learn.microsoft.com/ja-jp/azure/databricks/data-governance/unity-catalog/manage-external-locations-and-credentials#create-external-location)

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

```sql: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 などで定義した認証用の構成情報は無視される

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

- [Azure サービス プリンシパル](https://learn.microsoft.com/ja-jp/azure/databricks/storage/azure-storage#--access-azure-data-lake-storage-gen2-or-blob-storage-using-oauth-20-with-an-azure-service-principal)
- [SAS トークン](https://learn.microsoft.com/ja-jp/azure/databricks/storage/azure-storage#access-azure-data-lake-storage-gen2-or-blob-storage-using-a-sas-token) か [アカウント キー](https://learn.microsoft.com/ja-jp/azure/databricks/storage/azure-storage#--access-azure-data-lake-storage-gen2-or-blob-storage-using-the-account-key)
- [Azure Active Directory 資格情報パススルー](https://learn.microsoft.com/ja-jp/azure/databricks/data-governance/credential-passthrough/adls-passthrough)


---------------------------------------


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

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

方式イメージ：

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/5fd143e1-ff78-bd7f-6f00-62e733d31cad.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シークレット](https://learn.microsoft.com/ja-jp/azure/databricks/security/secrets/)に格納することを推奨 |
| fs.azure.account.oauth2.client.endpoint                                      | fs.azure.account.oauth2.client.endpoint | https://login.microsoftonline.com/{サービスプリンシパルの存在するテナントID}/oauth2/token |

あらかじめ、サービスプリンシパルの作成と、ストレージへの権限付与が必要。
参考：[Azure Active Directory を使ってストレージにアクセスする](https://learn.microsoft.com/ja-jp/azure/databricks/security/aad-storage-service-principal)


---------------------------------------

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

参考：[データ アクセスの構成](https://learn.microsoft.com/ja-jp/azure/databricks/sql/admin/data-access-configuration)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/7b7f3492-ec8f-09e5-d02a-65a3b4b78d78.png)


---------------------------------------



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

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

方式イメージ：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/3ff38b0b-6133-e08e-b9da-ce685cbe71d3.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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/dad9cec4-be0f-ddc4-b534-78f3c3c2e599.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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/2511d8a0-703b-ec83-fff3-dc736e0b76ea.png)



---------------------------------------



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

#### サービスプリンシパル

##### ABFS URI アクセス

構文：

```python: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")


```

使用例：

```python: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/")


```

##### マウントによるアクセス

構文：

```python: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)

```

使用例：

```python: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 アクセス

構文：

```python: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>")
```

使用例：

```python: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/")


```

##### マウントによるアクセス

構文：

```python: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)

```

使用例：

```python: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 アクセス

構文：

```python:pyspark

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

```

使用例：

```python: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/")


```


##### マウントによるアクセス

構文：

```python: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)

```

使用例：

```python: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 設定などの構文はない


使用例：

```python:pyspark

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

```

##### マウントによるアクセス

構文：

```python: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)

```

使用例：

```python: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 インジェクション](https://learn.microsoft.com/ja-jp/azure/databricks/administration-guide/cloud-configurations/azure/vnet-inject)

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

参考：[仮想ネットワークの管理](https://learn.microsoft.com/ja-jp/azure/databricks/administration-guide/cloud-configurations/azure/)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/a71eb138-373e-d774-138e-e82cc3a0e9a4.png)



---------------------------------------


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

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

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/c199d5c3-f3d1-d0b6-9fe5-d4ec99b55821.png)


---------------------------------------


### Vnet ピアリング

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

また、ピアリング先のNW内の資産へのアクセスには[DNS構成を設定する](https://learn.microsoft.com/ja-jp/azure/databricks/kb/cloud/custom-dns-routing)必要がある

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/e4ef144f-c0d8-f533-a9d3-64b2fe5959d9.png)

---------------------------------------

なお、Vnet の管理をしたくないが、ファイアウォールの背後のデータストアにアクセスしたい場合には、この構成でピアリングされたNWに、[Azure Private DNS Resolver](https://learn.microsoft.com/ja-jp/azure/dns/dns-private-resolver-overview) と対象のデータストアプライベートエンドポイントを配置し、以下のようなinit スクリプトでクラスタを起動することでアクセスができることを確認済み。

```bash: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-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/d2d681b9-32a2-2194-e598-34a93e132136.png)

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

---------------------------------------

## その他参考リンク集


[クラスター UI の変更とクラスター アクセス モード](https://learn.microsoft.com/ja-jp/azure/databricks/clusters/cluster-ui-preview)
[Azure Data Lake Storage Gen2 と Blob Storage にアクセスする](https://learn.microsoft.com/ja-jp/azure/databricks/storage/azure-storage)
[Unity Catalog のベスト プラクティス](https://learn.microsoft.com/ja-jp/azure/databricks/data-governance/unity-catalog/best-practices)
[クラスター構成オプションの管理](https://learn.microsoft.com/ja-jp/azure/databricks/administration-guide/clusters/)
[クラスター ノード初期化スクリプト](https://learn.microsoft.com/ja-jp/azure/databricks/clusters/init-scripts)
[Data Exfiltration Protection with Azure Databricks](https://www.databricks.com/blog/2020/03/27/data-exfiltration-protection-with-azure-databricks.html)