Databricks から ADLS Gen2 への接続エラー「CONFIG_NOT_AVAILABLE」を徹底解説|原因と安全な設定方法

Azure Databricks から ADLS Gen2 に OAuth(サービス プリンシパル+クライアントシークレット)で接続しようとしたときに、突然 [CONFIG_NOT_AVAILABLE] が出てハマるケースはとても多いです。本記事では、このエラーが意味するところから、具体的な設定例、切り分け手順、再発防止のベストプラクティスまでを、現場で使えるレベルで詳しく解説します。

目次

Databricks と ADLS Gen2 で発生する CONFIG_NOT_AVAILABLE とは

まずは、今回の主役であるエラー内容をおさらいしておきましょう。

[CONFIG_NOT_AVAILABLE] Configuration fs.azure.account.auth.type.<storage-account>.dfs.core.windows.net is not available. (SQLSTATE: 42K0I)

典型的なシナリオは次のようなものです。

  • Databricks ノートブックから ADLS Gen2 へアクセスしたい
  • 認証方式は OAuth(サービス プリンシパル+クライアントシークレット)
  • spark.conf.set(...) で必要な設定を追加しているつもり
  • dbutils.fs.ls("abfss://...") や spark.read... を実行したタイミングで上記エラーが発生
  • クラスタを再作成しても直らない、アプリ登録をやり直しても直らない

ここで重要なのは、このエラーは「認証に失敗している」のではなく、「そもそも必要な設定が見つからない」ことを示している点です。つまり、Azure 側の権限やロール設定以前の話で、Spark / Hadoop 設定のキー名そのものがズレている、または反映されていない、という状況がほとんどです。

CONFIG_NOT_AVAILABLE が示していること

Databricks から ADLS Gen2 に接続する際、内部では ABFS ドライバが Spark 設定を参照しにいきます。そのときに、たとえば次のようなキーを探します。

  • fs.azure.account.auth.type.<storage-account>.dfs.core.windows.net
  • fs.azure.account.oauth2.client.id.<storage-account>.dfs.core.windows.net
  • fs.azure.account.oauth2.client.secret.<storage-account>.dfs.core.windows.net

このうち 1 つでもキーが見つからなかったり、別名で設定されていたりすると、ABFS ドライバは「設定がない」と判断し、[CONFIG_NOT_AVAILABLE] を投げてきます。逆に言うと、キー名さえ完全に合っていれば、次は認証エラーや 403 など別のエラーに変わることが多いです。

前提環境と典型的な構成

本記事で想定している主な構成は次の通りです。

項目例補足
コンピュートAzure Databricks クラスターノートブックで spark.conf.set を実行
ストレージAzure Data Lake Storage Gen2階層 namespace 有効のストレージアカウント
認証方式OAuth 2.0 クライアントクレデンシャルサービス プリンシパル+クライアントシークレット
エンドポイントhttps://login.microsoftonline.com/<tenant>/oauth2/tokenv1 エンドポイントを前提
アクセス URLabfss://<container>@<storage-account>.dfs.core.windows.net/...dfs.core.windows.net を使用

Databricks SQL Warehouse(旧 SQL Analytics)からアクセスする場合は、spark.conf ではなく Unity Catalog の「ストレージ資格情報」「外部ロケーション」を使うのが基本です。この点を混同すると切り分けがぶれてしまうので注意しましょう。

最初に押さえておきたい「結論だけチェックリスト」

細かい説明の前に、とりあえずここを見れば直る可能性が高いというポイントだけを先に整理しておきます。

チェック項目内容
キー名の完全一致<storage-account>.dfs.core.windows.net を含むすべての設定キーがストレージアカウント名と完全一致しているか(余分な空白や改行なし)
設定の実行タイミングspark.read や dbutils.fs.ls を実行する前に、同一セルで spark.conf.set をすべて実行しているか
シークレット参照dbutils.secrets.get(...) の戻り値を変数に受け、その変数を client.secret に渡しているか
abfss パスでの疎通テスト実際のコンテナ・パスを指定して dbutils.fs.ls または spark.read を実行し、エラー内容が変化するか確認したか
サービス プリンシパル権限少なくとも「Storage Blob Data Contributor」ロールが付与されているか。必要ならコンテナ/ディレクトリ ACL も確認

このチェックリストを一通り確認しても解決しない場合は、次の章からの詳細な切り分け手順を順に試してみてください。

CONFIG_NOT_AVAILABLE のよくある原因パターン

現場で特に多い原因を整理すると、次のようなパターンに集約されます。

原因パターン具体例ポイント
キー名のタイプミス・改行混入fs.azure.account.auth.type.mystorage\n .dfs.core.windows.netコピー&ペースト時の改行やゼロ幅スペースが原因
<storage-account> 置換漏れfs.azure.account.auth.type.<storage-account>.dfs... のままサンプルをそのまま使って置換し忘れ
ドメインの取り違えblob.core.windows.net と書いているABFS は dfs.core.windows.net が正解
設定の実行順序の問題spark.read... を先に実行し、その後で spark.conf.set読み込み前に設定が完了していない
シークレットの渡し方の問題文字列リテラルでシークレット名を書いているだけ値ではなく「名前」を渡してしまっている
コンピュートの勘違いSQL Warehouse に対して spark.conf.set を打っているクラスター設定と Warehouse 設定は別物

ここからは、それぞれのポイントをもう少し実践的に見ていきます。

キー名の完全一致を徹底する

ストレージアカウント名とホスト名は 1 文字もズレてはいけない

ABFS 用の設定キーは、ストレージアカウント名とホスト名を含んだ形になっています。

fs.azure.account.auth.type.&lt;storage-account&gt;.dfs.core.windows.net
fs.azure.account.oauth2.client.id.&lt;storage-account&gt;.dfs.core.windows.net
fs.azure.account.oauth2.client.secret.&lt;storage-account&gt;.dfs.core.windows.net
fs.azure.account.oauth2.client.endpoint.&lt;storage-account&gt;.dfs.core.windows.net

例えば、ストレージアカウント名が dlstest01 なら、ホスト名は dlstest01.dfs.core.windows.net です。ここで、

  • dlstest01 (末尾に空白)
  • dlstest01 (全角スペース)
  • dlstest0l(数字の「1」とアルファベットの「l」の取り違え)

といった微妙な違いが 1 文字でも入ると、ABFS ドライバから見ると「別物のキー」になってしまいます。

コピー&ペーストで紛れ込む改行・不可視文字に注意

よくあるパターンが、ドキュメントやメールからコピーした結果、ストレージアカウント名の途中で改行が入ってしまうケースです。Spark のエラーログを見ると、次のように見えることがあります。

fs.azure.account.auth.type.dlstest
01.dfs.core.windows.net is not available

この場合、エラーにそのまま改行付きのキー名が出ているので、「あれ、アカウント名が途中で折り返されてないか?」と疑うのがポイントです。Python から repr でキー名を確認すると、不可視文字の混入も確認しやすくなります。

key = f"fs.azure.account.auth.type.{storage_account}.dfs.core.windows.net"
print(repr(key))

ここで 'fs.azure.account.auth.type.dlstest01.dfs.core.windows.net' のようにきれいに表示されれば OK です。

安全な設定パターン(コピペ推奨サンプル)

タイプミスや改行混入を防ぐためには、キー名をそのままベタ書きしないのが一番です。変数を使ってホスト名を組み立てるパターンにしておくと、再利用もしやすくなります。

基本形:単一ストレージアカウント向けの設定

# 1) 変数に集約してタイプミスを防止
storage_account = "&lt;your-storage-account&gt;"  # 例: dlstest01
tenant_id       = "&lt;your-tenant-id&gt;"
app_id          = "&lt;your-application-id&gt;"
client_secret   = dbutils.secrets.get(scope="&lt;your-scope&gt;", key="&lt;your-secret-key&gt;")

host = f"{storage_account}.dfs.core.windows.net"

# 2) すべて同一セルで実行(読み込み前)
spark.conf.set(f"fs.azure.account.auth.type.{host}", "OAuth")
spark.conf.set(f"fs.azure.account.oauth.provider.type.{host}",
               "org.apache.hadoop.fs.azurebfs.oauth2.ClientCredsTokenProvider")
spark.conf.set(f"fs.azure.account.oauth2.client.id.{host}", app_id)
spark.conf.set(f"fs.azure.account.oauth2.client.secret.{host}", client_secret)
spark.conf.set(f"fs.azure.account.oauth2.client.endpoint.{host}",
               f"https://login.microsoftonline.com/{tenant_id}/oauth2/token")

# 3) 設定が入っているか簡易確認(例外が出なければOK)
_ = spark.conf.get(f"fs.azure.account.auth.type.{host}")

# 4) 最小の疎通テスト(パスは実環境に置き換え)
test_path = f"abfss://&lt;container&gt;@{storage_account}.dfs.core.windows.net/&lt;path/to/file_or_folder&gt;"
display(dbutils.fs.ls(test_path))

ポイントは次の通りです。

  • host 変数にホスト名を一元化し、すべてのキーで使い回す
  • 設定と疎通確認を一つのセルにまとめて実行する(セルを分けると、どこまで実行済みか分かりにくくなる)
  • spark.conf.get で最低限の存在確認を行う

複数ストレージアカウントに共通のヘルパー関数を使う

プロジェクトによっては、複数のストレージアカウントを使い分けることも珍しくありません。その場合は、ヘルパー関数を用意しておくとミスを減らせます。

def configure_adls_oauth(storage_account: str,
                         tenant_id: str,
                         app_id: str,
                         secret_scope: str,
                         secret_key: str) -&gt; None:
    host = f"{storage_account}.dfs.core.windows.net"
    client_secret = dbutils.secrets.get(scope=secret_scope, key=secret_key)

    spark.conf.set(f"fs.azure.account.auth.type.{host}", "OAuth")
    spark.conf.set(f"fs.azure.account.oauth.provider.type.{host}",
                   "org.apache.hadoop.fs.azurebfs.oauth2.ClientCredsTokenProvider")
    spark.conf.set(f"fs.azure.account.oauth2.client.id.{host}", app_id)
    spark.conf.set(f"fs.azure.account.oauth2.client.secret.{host}", client_secret)
    spark.conf.set(f"fs.azure.account.oauth2.client.endpoint.{host}",
                   f"https://login.microsoftonline.com/{tenant_id}/oauth2/token")

# 例: 利用
configure_adls_oauth(
    storage_account="dlstest01",
    tenant_id="&lt;tenant-id&gt;",
    app_id="&lt;app-id&gt;",
    secret_scope="sp-secrets",
    secret_key="dlstest01-client-secret"
)

このように関数化しておくと、環境が増えたときにも「パラメータだけ差し替える」運用が可能になります。

設定の実行タイミングとセルの構成

Databricks ノートブックでは、セルの実行順序を自由に変えられます。そのため、次のような「うっかり」がよく起こります。

  1. 一度ノートブックを上から順に実行した
  2. データ読み込みのセルだけを後から再実行した
  3. 別ユーザーがノートブックを開き、読み込みセルだけ実行した(設定セルは実行していない)

この状態で spark.read... を実行すると、当然ながら ABFS 設定は入っていないので [CONFIG_NOT_AVAILABLE] につながります。

パターン症状対策
設定セルと読み込みセルが離れている人によって実行順が変わる「初期設定」セルをノートブック先頭に置き、必ず最初に実行する運用にする
複数ノートブックから同じクラスターを共有どのノートブックで設定されたか分からなくなる可能ならノートブックごとにクラスターを分けるか、初期化スクリプトで共通化

運用上の工夫としては、ノートブックの先頭に「環境初期化」セクションを設け、そのセルにすべての spark.conf.set を集約し、誰が見ても「最初にここを実行すればよい」と分かるようにしておくと安心です。

シークレットの参照漏れ・渡し方のミス

Azure Key Vault / Databricks シークレットスコープを使ってクライアントシークレットを管理している場合、「値」と「名前」を取り違えるミスが頻出します。

よくある NG パターン

# NG 例: シークレット「名」をそのまま書いてしまっている
spark.conf.set(
    f"fs.azure.account.oauth2.client.secret.{host}",
    "&lt;your-secret-key&gt;"  # これは Key Vault の「キー名」であって、値ではない
)

この場合、ABFS はクライアントシークレットとして "<your-secret-key>" という文字列そのものを送信してしまうため、認証自体は確実に失敗します。CONFIG_NOT_AVAILABLE ではなく認証エラーになりますが、根本原因としてはよく似た「参照の仕方の問題」です。

正しいパターン:必ず dbutils.secrets.get を経由する

client_secret = dbutils.secrets.get(scope="&lt;scope-name&gt;", key="&lt;secret-key-name&gt;")

spark.conf.set(
    f"fs.azure.account.oauth2.client.secret.{host}",
    client_secret
)

ここで client_secret は実際のシークレット値が入った文字列になります。この変数を spark.conf.set に渡すことで、ABFS から見ても正しい値が設定されることになります。

トークンエンドポイントの指定と v1 / v2 の違い

CONFIG_NOT_AVAILABLE そのものには直接関係しませんが、認証エラーに移行したときのためにトークンエンドポイントも押さえておきましょう。

  • 基本形:https://login.microsoftonline.com/<tenant-id>/oauth2/token(v1 エンドポイント)
  • 場合によっては v2(.../oauth2/v2.0/token)が必要なケースもある

Databricks の公式ドキュメントでは、多くのサンプルコードが v1 エンドポイントを前提としているため、まずは v1 で試し、必要に応じて v2 を検討するとよいでしょう。いずれにせよ、CONFIG_NOT_AVAILABLE が出ている段階では「そこまで辿り着いていない」ので、まずは設定キー名の整合性を優先的に確認するのが効率的です。

Spark / Hadoop の設定値を覗いてキーを確認する

「設定を入れたつもりなのに CONFIG_NOT_AVAILABLE が出る」という状況では、実際に Spark がどんなキーを持っているのかを見に行くのが一番確実です。

Spark 設定から該当キーを検索する

storage_account = "&lt;your-storage-account&gt;"

for k in spark.conf.getAll().keys():
    if "fs.azure.account." in k and storage_account in k:
        print(repr(k))

この出力に、意図していないキーが紛れ込んでいないか確認します。

  • 'fs.azure.account.auth.type.dlstest01.dfs.core.windows.net '(末尾にスペース)
  • 'fs.azure.account.auth.type.dlstest01..dfs.core.windows.net'(ドットが二重)
  • 'fs.azure.account.auth.type.dlstest01.dfs.core.windows.ne'(末尾の t 抜け)

このようなキーが存在している場合、ABFS ドライバは期待するキーを見つけられず、CONFIG_NOT_AVAILABLE を投げ続けることになります。

Hadoop 設定から直接値を取得してみる

より低レイヤーの確認として、Hadoop 設定を直接覗く方法もあります。

storage_account = "&lt;your-storage-account&gt;"
host = f"{storage_account}.dfs.core.windows.net"

jconf = sc._jsc.hadoopConfiguration()
print("auth.type =", jconf.get(f"fs.azure.account.auth.type.{host}"))
print("client.id =", jconf.get(f"fs.azure.account.oauth2.client.id.{host}"))
print("endpoint  =", jconf.get(f"fs.azure.account.oauth2.client.endpoint.{host}"))

ここで None や空文字が返ってくる場合は、そもそも設定が入っていない(またはキー名が違っている)ことになります。

疎通テストとエラー変化で原因を絞り込む

CONFIG_NOT_AVAILABLE の段階を抜け出せたかどうかは、エラー内容が変わったかどうかで判断するのが分かりやすいです。

最低限の疎通テスト

設定が完了したら、まずは小さなファイル or ディレクトリで疎通テストを行います。

test_path = f"abfss://&lt;container&gt;@{storage_account}.dfs.core.windows.net/&lt;path&gt;"

# ディレクトリ一覧の確認
display(dbutils.fs.ls(test_path))

# または CSV を軽く読む
df = (spark.read
          .format("csv")
          .option("header", "true")
          .load(test_path))
df.limit(1).display()

このときのエラー内容によって、次のように切り分けられます。

エラー内容主な原因候補次に見るべきポイント
[CONFIG_NOT_AVAILABLE]設定キー名の不整合/設定未適用Spark/Hadoop 設定のキー一覧、改行・空白混入を再確認
403 Forbidden / 認可エラーサービス プリンシパルに十分なロールがないStorage Blob Data Contributor 等の RBAC、ACL を確認
認証エラー(invalid_client など)クライアント ID / シークレット / テナント ID の誤りAzure AD アプリ登録、シークレット値の見直し
ファイル/パスが存在しないパス指定ミス、コンテナ名の間違いポータルや Storage Explorer でパスを再確認

このように、エラーが CONFIG_NOT_AVAILABLE から別の種類に変わったら、「設定キーは読めるようになった」と判断し、次のレイヤー(権限やパス)に問題の焦点を移すのが効率的です。

サービス プリンシパルの RBAC と ACL の整理

CONFIG_NOT_AVAILABLE の直接原因ではありませんが、設定が正しくなった後に 403 などで止まる場合は、サービス プリンシパルの権限周りを整理する必要があります。

RBAC(ロールベースアクセス制御)

最低限必要になることが多いロールは次の通りです。

ロール名主な用途スコープの例
Storage Blob Data ContributorBlob / Data Lake への読み書きストレージアカウント単位、またはコンテナ単位
Storage Blob Data Reader読み取り専用シナリオ読み取りのみでよい場合に利用

スコープは、セキュリティ要件と運用ポリシーに応じて、サブスクリプション/リソースグループ/ストレージアカウント/コンテナのいずれかで設定します。トラブルシュート中だけ一時的に広めのスコープを与え、問題解決後に絞り込むアプローチも現実的です。

ACL(POSIX 風アクセス制御)

ADLS Gen2 では、RBAC に加えて POSIX 風の ACL が有効になっていることがあります。この場合、RBAC だけ付けても ACL で拒否されるとアクセスできません。

  • 対象ディレクトリに対してサービス プリンシパルに r-x など適切な権限を付与
  • 途中の親ディレクトリにも「実行(x)」権限が必要

ACL でブロックされている場合は、CONFIG_NOT_AVAILABLE ではなく 403 系のエラーになるため、前述の「エラー変化による切り分け」を使うと原因に辿り着きやすくなります。

Databricks SQL Warehouse を使う場合の注意点

ここまでの説明は「Databricks クラスター+ノートブック」でのケースを想定していましたが、Databricks SQL Warehouse(旧 SQL Analytics)から ADLS にアクセスする場合は、登場人物が少し変わります。

  • spark.conf.set は SQL Warehouse には直接効かない
  • 基本的には Unity Catalog の「ストレージ資格情報」「外部ロケーション」を使って接続する
  • その場合は、Databricks 側のマネージド ID や別のサービス プリンシパルを使う構成になる

もし「ノートブックではうまく行くのに、SQL Warehouse からだと CONFIG_NOT_AVAILABLE になる」という状況であれば、そもそも「どのレイヤーで設定を行うべきか」を一度整理し直すことをおすすめします。

再発防止のためのベストプラクティス

最後に、同じ CONFIG_NOT_AVAILABLE で何度もハマらないための工夫をまとめます。

  • キー名を変数で組み立てる
    文字列ベタ書きをやめ、host = f"{storage_account}.dfs.core.windows.net" のように一元化する。
  • 設定セルをノートブック先頭に固定する
    「初期設定」セルを最初に実行する運用を徹底し、コメントで明示する。
  • ヘルパー関数を作って共通化する
    複数プロジェクトで同じような設定を毎回書かない。1 箇所を直せば全体に反映されるようにする。
  • 疎通テスト用パスを決めておく
    シンプルなテスト用ディレクトリ / ファイルを決めておき、切り分け時は必ずそこを使う。
  • エラー内容の変化をログに残す
    CONFIG_NOT_AVAILABLE → 403 → ファイル未検出… のように、どこまで進んだかを記録しておくと、後から見直したときに原因が追いやすい。

まとめ

Databricks から ADLS Gen2 に OAuth で接続する際の [CONFIG_NOT_AVAILABLE] は、一見すると「難しい認証エラー」に見えますが、実態はほとんどが設定キー名の不整合です。

  • ABFS ドライバが探しているキー名と、実際に設定されているキー名が 1 文字でも違うと CONFIG_NOT_AVAILABLE になる
  • キー名は <storage-account>.dfs.core.windows.net まで含めて完全一致させる必要がある
  • 設定は spark.read などを行う前に、同一セルで一括実行するのが安全
  • シークレットは dbutils.secrets.get の戻り値(実際の値)を client.secret に渡す
  • 設定が正しくなれば、次のステップでは RBAC や ACL の問題に移行することが多い

本記事で紹介したサンプルコードと切り分け手順をテンプレートとしてストックしておけば、今後同じエラーに遭遇したときにも、短時間で原因に辿り着けるはずです。Databricks と ADLS Gen2 を組み合わせたデータ基盤を運用している方は、ぜひ自分の環境用にカスタマイズした「接続設定ノートブック」を用意しておくことをおすすめします。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次