使用PySpark无需账户密钥读取Azure Blob时SAS报错如何解决?
问题原因
不存在无需账户密钥就无法读取Blob数据的情况,你遇到的报错是SAS配置和生成的SAS类型不匹配导致的:你通过
generate_blob_sas生成的是单Blob粒度的SAS,而你配置的Spark参数是容器级别的SAS校验位,两者格式要求不匹配,导致Spark无法识别可用凭证。
解决方案
以下两种方案均不需要暴露存储账户密钥:
方案1:修正SAS配置逻辑
- 如果你要继续用SAS方式,可选择任意一种调整方法:
- 改用容器级SAS生成函数:调用
generate_container_sas而非generate_blob_sas生成容器级SAS,再填入你现有的Spark配置项即可,生成SAS时可以直接传入你之前使用的DefaultAzureCredential,不需要填存储账户密钥。 - 保留现有Blob级SAS的话,不需要单独配置SparkConf,直接把SAS拼接在Blob的访问路径后即可,路径格式为
wasbs://<容器名>@<存储账户>.blob.core.windows.net/<Blob路径>?<生成的SAS串>,直接读取该路径即可。
容器级SAS的配置示例如下:
from azure.storage.blob import generate_container_sas, ContainerSasPermissions from datetime import datetime, timedelta import pyspark from pyspark.sql import SparkSession from azure.identity import DefaultAzureCredential # 用DefaultAzureCredential生成容器级SAS,全程不需要存储账户密钥 sas_token = generate_container_sas( account_name=storage_account_name, container_name=container_name, permission=ContainerSasPermissions(read=True, list=True), expiry=datetime.utcnow() + timedelta(hours=2), credential=DefaultAzureCredential() ) spark_conf = pyspark.SparkConf().set( f"fs.azure.sas.{container_name}.{storage_account_name}.blob.core.windows.net", sas_token ) spark = SparkSession.builder \ .config(conf=spark_conf) \ .appName("ReadCsvFromBlob") \ .getOrCreate() df = spark.read.csv(f"wasbs://{container_name}@{storage_account_name}.blob.core.windows.net/{csv_file_path}") - 改用容器级SAS生成函数:调用
方案2:直接沿用DefaultAzureCredential方案(更推荐)
不需要生成SAS,直接配置Spark用Azure AD身份认证即可,省去SAS过期维护的成本:
from pyspark.sql import SparkSession import pyspark spark_conf = pyspark.SparkConf() \ .set("fs.azure.account.auth.type", "OAuth") \ .set("fs.azure.account.oauth.provider.type", "org.apache.hadoop.fs.azurebfs.oauth2.ClientCredsTokenProvider") \ .set("fs.azure.account.oauth2.client.id", "<你的Azure AD应用客户端ID>") \ .set("fs.azure.account.oauth2.client.secret", "<你的Azure AD应用客户端密钥>") \ .set("fs.azure.account.oauth2.client.endpoint", "https://login.microsoftonline.com/<你的租户ID>/oauth2/token") spark = SparkSession.builder \ .config(conf=spark_conf) \ .appName("ReadCsvFromBlob") \ .getOrCreate() # 路径用abfs协议适配AD认证 df = spark.read.csv(f"abfs://{container_name}@{storage_account_name}.dfs.core.windows.net/{csv_file_path}")
如果你是在Azure托管服务(如Databricks、Synapse、绑定了托管标识的AKS节点)上运行,连客户端ID、密钥都不需要配置,直接给托管标识开通Blob读取权限即可,全程不需要任何密钥类敏感信息。
内容的提问来源于stack exchange,提问作者The Questionner
相关产品推荐
相关产品推荐

