Spark DataFrame无法写入ADLS Gen2容器的授权问题求助
Spark写入ADLS Gen2容器授权失败排查与解决
问题场景
在Azure VM上部署Spark后,尝试用存储访问密钥将DataFrame写入ADLS Gen2容器失败,具体情况:
- 启动pyspark命令:
pyspark --jars azure-storage-7.0.0.jar,hadoop-azure-3.1.2.jar,hadoop-common-3.1.2.jar,jetty-util-12.0.5.jar,jetty-util-ajax-11.0.12.jar --conf spark.hadoop.fs.AbstractFileSystem.wasb.Impl=org.apache.hadoop.fs.azure.Wasb --conf spark.hadoop.fs.azure.account.key.<storageAccount>.blob.core.windows.net=<accessKey>
- Spark写入代码:
data = [("Java", "20000"), ("Python", "100000"), ("Scala", "3000")] df = spark.createDataFrame(data) df.write.csv("wasbs://<container>@<storageAccount>.blob.core.windows.net/TestFolder/", mode = "append")
- 报错核心信息:
24/01/30 20:43:13 ERROR Utils: Aborting task (0 + 2) / 2] java.lang.IllegalStateException: Error closing the output. at com.univocity.parsers.common.AbstractWriter.close(AbstractWriter.java:1000) ... Caused by: com.microsoft.azure.storage.StorageException: This request is not authorized to perform this operation.
- 异常现象:容器已生成
_$azuretmpfolder$临时目录并包含csv文件,TestFolder/_temporary/0/_temporary目录存在但无文件;同一机器用相同访问密钥的Python脚本可正常在容器创建文件。
根因分析
- 协议不匹配:使用
wasb(s)协议访问ADLS Gen2容器,该协议为Azure Blob Storage设计,对ADLS Gen2的分层命名空间支持有限,写入过程中临时文件重命名等操作可能触发权限校验问题。 - 依赖jar包版本冲突:启动命令中
jetty-util(12.0.5)和jetty-util-ajax(11.0.12)版本不一致,且azure-storage与hadoop-azure版本兼容性不足,导致底层IO操作异常。 - 存储端点配置错误:ADLS Gen2的专用端点为
dfs.core.windows.net,而非blob.core.windows.net,使用Blob端点可能导致部分操作权限校验失败。
解决方法
1. 切换到ADLS Gen2专用ABFS协议
修改pyspark启动配置和写入路径,使用abfs协议:
- 启动命令:
pyspark --jars azure-storage-8.6.3.jar,hadoop-azure-3.1.2.jar,hadoop-common-3.1.2.jar,jetty-util-9.4.50.v20221201.jar,jetty-util-ajax-9.4.50.v20221201.jar \ --conf spark.hadoop.fs.AbstractFileSystem.abfs.Impl=org.apache.hadoop.fs.azurebfs.AzureBlobFileSystem \ --conf spark.hadoop.fs.azure.account.key.<storageAccount>.dfs.core.windows.net=<accessKey>
- 修改Spark写入路径:
df.write.csv("abfs://<container>@<storageAccount>.dfs.core.windows.net/TestFolder/", mode = "append")
说明:
abfs协议原生支持ADLS Gen2的分层命名空间,能更好处理文件重命名等写入流程中的操作。
2. 统一依赖jar包版本
确保所有依赖jar包版本兼容:
hadoop-azure与hadoop-common版本保持一致(均为3.1.2);azure-storage使用与hadoop-azure匹配的版本(hadoop-3.1.2对应azure-storage 8.6.3);jetty-util和jetty-util-ajax使用相同版本(推荐与hadoop依赖的jetty版本一致,如9.4.50)。
3. 验证存储账户权限
确认存储访问密钥关联的身份拥有Storage Blob Data Contributor权限——即使Python脚本能创建文件,Spark写入过程涉及更多操作(如重命名、删除临时文件),需确保权限覆盖全流程。
4. 配置专用临时目录
若临时文件无法正常清理,可指定本地和存储端的临时目录,避免权限冲突:
--conf spark.local.dir=/path/to/local/tmp \ --conf spark.hadoop.fs.azure.temp.dir=abfs://<container>@<storageAccount>.dfs.core.windows.net/tmp/
内容的提问来源于stack exchange,提问作者Jetinder Rathore
相关产品推荐
相关产品推荐

