Azure DatabricksからADLS Gen2やBlob Storageにアクセスする

こちらでADLSのデータにアクセスする方法を説明しましたが、非推奨の方法を説明してしまっていたので、改めて方法を整理します。

https://qiita.com/taka_yayoi/items/056e2c419eca4ed7f7dc

詳細はこちらの記事をベースにしています。

https://docs.microsoft.com/ja-jp/azure/databricks/data/data-sources/azure/azure-storage

Azure Databricksからストレージにアクセスする方法はいくつかありますが、現在はAzure Blob File System(ABFS)ドライバーを用いる方法が推奨となっています。

| アクセス方法 | 説明 |
|:--|:--|
| Azure Blob File System(ABFS)ドライバーを用いて接続  | **推奨** [ABFS に関する Azure のドキュメント](https://docs.microsoft.com/azure/storage/blobs/data-lake-storage-abfs-driver) |
| Windows Azure Storage(WASB)ドライバーを用いて接続  | **非推奨** [WASB で Azure Blob Storage に接続する \(レガシ\)](https://docs.microsoft.com/ja-jp/azure/databricks/data/data-sources/azure/wasb-blob) |
| 外部データの場所をDatabricksファイルシステムにマウント  | **非推奨** Unity Catalogのカタログではマウントされたデータは機能しません。<br>[Azure Databricks でのクラウド オブジェクト ストレージのマウント](https://docs.microsoft.com/ja-jp/azure/databricks/data/mounts) |
| Azure Active Directoryの資格情報パススルーを使ってAzure Data Lake Storageにアクセス  | **非推奨** [Azure Active Directory の資格情報パススルーを使って Azure Data Lake Storage にアクセスする](https://docs.microsoft.com/ja-jp/azure/databricks/security/credential-passthrough/adls-passthrough) |

# WASBドライバーとABFSドライバー

[Azure Data Lake Storage Gen2 用の Azure BLOB ファイルシステム ドライバー \| Microsoft Docs](https://docs.microsoft.com/ja-jp/azure/storage/blobs/data-lake-storage-abfs-driver)で説明されているように、これまではWindows Azure Storage Blob(WASB)ドライバーが使用されていましたが、コードメンテナンスの困難さやパフォーマンスの課題から新たにAzure File System(ABFS)ドライバーが設計されています。

ABFSドライバーを用いてストレージにアクセスするには、以下のURIスキーマを使用します。

```
abfs[s]://file_system@account_name.dfs.core.windows.net/<path>/<path>/<file_name>
```

# ABFSのURIを用いてADLS Gen2にアクセスする

以下ではマウントポイントを作成せず、ABFS URIを用いて直接ADLS Gen2にアクセスします。アクセスする際には適切に認証情報を設定する必要があります。認証情報を設定する方法には以下のものがあります。

- Azureサービスプリンシパル
- SASトークン
- アカウントキー

## Azureサービスプリンシパルを用いて認証情報を設定する

資格情報の格納には[Azure Databricksシークレット](https://docs.microsoft.com/ja-jp/azure/databricks/security/secrets/secret-scopes)を用いることをお勧めします。

### サービスプリンシパルの作成

1. Azure Portalから**Azure Active Directory**に移動します。
1. **エンタープライズアプリケーション** > **新しいアプリケーション**を選択します。
1. アプリケーションの名前を指定します。リダイレクトURIは後で設定します。
![Screen Shot 2022-08-22 at 10.10.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/d42c44b0-3454-f95a-4600-fccffaeffb81.png)
1. **アプリケーション (クライアント) ID**と**ディレクトリ (テナント) ID**をコピーしておきます。
![Screen Shot 2022-08-22 at 10.46.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/e99c1ee4-ae01-e007-541a-c97830e741a5.png)
1. **クライアントの資格情報**をクリックします。**新しいクライアントシークレット**をクリックしてシークレットを作成します。シークレットの**値**をコピーしておきます。
![Screen Shot 2022-08-22 at 10.21.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/32d6aea5-7473-14cf-233e-e53abd098852.png)
1. リダイレクトURIを設定します。**リダイレクトURI**をクリックします。
![Screen Shot 2022-08-22 at 10.46.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/e3fe841d-2f5e-487f-6ce2-aada27792459.png)

    以下の形式でURIを指定します。上で取得した**ディレクトリ (テナント) ID**を埋め込みます。
    ```
    https://login.microsoftonline.com/<ディレクトリ (テナント) ID>/oauth2/token
    ```
    ![Screen Shot 2022-08-22 at 10.55.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/7685201a-c213-dab2-8d14-e19211a470f0.png)

1. サービスプリンシパルをストレージアカウントに割り当てます。**ストレージアカウント**に移動し**ロールの割り当ての追加**をクリックします。
![Screen Shot 2022-08-22 at 10.51.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/ecf67b5e-cab5-42f0-8b61-bf524cb014cc.png)
1. 上で作成したサービスプリンシパルを**ストレージBLOBデータ共同作成者**として割り当てます。
![Screen Shot 2022-08-22 at 10.13.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/9526d399-e90f-e2aa-e6d7-3e663b9ea3db.png)

### 認証情報の設定

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

- `<scope>` をDatabricksシークレット スコープ名に置き換えます。
- `<service-credential-key>` をクライアントシークレットを含むキーの名前に置き換えます。
- `<storage-account>`はAzureストレージアカウントの名前に置き換えます。
- `<application-id>`をAzure Active Directoryアプリケーションのアプリケーション (クライアント) ID に置き換えます。
- `<directory-id>`をAzure Active Directoryアプリケーションのディレクトリ (テナント) ID に置き換えます。

## SASトークンを用いて認証情報を設定する

[Shared Access Signatures \(SAS\) でデータの制限付きアクセスを付与する \- Azure Storage \| Microsoft Docs](https://docs.microsoft.com/ja-jp/azure/storage/common/storage-sas-overview)をご覧ください。

## アカウントキーを用いて認証情報を設定する

一番お手軽な方法ですが、[アカウントキー](https://docs.microsoft.com/ja-jp/azure/storage/common/storage-account-keys-manage?tabs=azure-portal)の取り扱いには注意してください。[Azure Databricksシークレット](https://docs.microsoft.com/ja-jp/azure/databricks/security/secrets/secret-scopes)を用いることをお勧めします。

```py:Python
spark.conf.set("fs.azure.account.key.<ストレージアカウント名>.dfs.core.windows.net", 
  dbutils.secrets.get(scope="<シークレットのスコープ名>", key="<アカウントキーが含まれるシークレットのキー>"))
```

# ファイル一覧を取得する

```py:Python
display(dbutils.fs.ls("abfss://<コンテナー名>@<ストレージアカウント名>.dfs.core.windows.net/adls_data"))
```
![Screen Shot 2022-08-22 at 10.59.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/6dd2aa87-2cd0-e06b-0c91-60853e12a4d4.png)

# テーブルを作成する

```sql:SQL
CREATE TABLE default.covid_cases(
  Prefecture STRING,
  Cases INT,
  date_parsed TIMESTAMP
) USING CSV LOCATION "abfss://<コンテナー名>@<ストレージアカウント名>.dfs.core.windows.net/adls_data/japan_cases_20220818.csv" OPTIONS("header" = "True");
```

このようにABFSドライバーを使うことで、Azure DatabricksからADLS上のデータにアクセスすることができます。

### Databricks 無料トライアル

[Databricks 無料トライアル](https://databricks.com/jp/try-databricks)