AWS EMR Spark无法保存表至Hive:S3 /tmp/hive目录访问被拒
Spark应用尝试将数据保存到配置了S3存储的Hive表,但无法访问S3中的/tmp/hive目录。已在SparkSession上设置以下配置并启用.enableHiveSupport,且所有EMR实例都具备该存储桶的读写权限。
已配置参数
spark.sql.warehouse.dir = s3://smt-sessionizer-stage-out/spark/hive/metastore
报错信息
23/01/05 17:44:52 INFO HiveUtils: 正在使用Spark类初始化HiveMetastoreConnection版本2.3.7-amzn-4。
23/01/05 17:44:52 INFO HiveConf: 找到配置文件file:/etc/spark/conf.dist/hive-site.xml
23/01/05 17:44:52 WARN HiveConf: 不存在名为hive.server2.thrift.url的HiveConf配置
org.apache.spark.sql.AnalysisException: java.lang.RuntimeException: java.nio.file.AccessDeniedException: tmp/hive/: 在tmp/hive/上PUT 0字节对象时出错: com.amazonaws.services.s3.model.AmazonS3Exception: 访问被拒绝 (Service: Amazon S3; Status Code: 403; Error Code: AccessDenied; Request ID: 1BPCGWXXYGQ7Y6SE; S3 Extended Request ID: F12HhZZOLPEkok/MNvhXXLSJesYMMvmHCQbN+6XUetg2DzM8Iu1Oe0MjkjM160Mxg54FtEFLKS4=; Proxy: null), S3 Extended Request ID: F12HhZZOLPEkok/MNvhXXLSJesYMMvmHCQbN+6XUetg2DzM8Iu1Oe0MjkjM160Mxg54FtEFLKS4=:AccessDenied
at org.apache.spark.sql.hive.HiveExternalCatalog.withClient(HiveExternalCatalog.scala:135)
at org.apache.spark.sql.hive.HiveExternalCatalog.databaseExists(HiveExternalCatalog.scala:249)
at org.apache.spark.sql.internal.SharedState.externalCatalog$lzycompute(SharedState.scala:135)
at org.apache.spark.sql.internal.SharedState.externalCatalog(SharedState.scala:125)
1. 显式配置Hive临时目录
Hive默认用tmp/hive作为临时工作目录,但这里它尝试访问的是S3根路径下的tmp/hive,而非你指定的warehouse目录。直接在SparkSession中添加以下配置,把临时目录指向S3的合法路径:
.config("hive.exec.scratchdir", "s3://smt-sessionizer-stage-out/spark/hive/tmp") .config("hive.metastore.warehouse.dir", "s3://smt-sessionizer-stage-out/spark/hive/metastore")
确保这个tmp目录所在路径的存储桶,EMR实例的IAM角色有完整读写权限。
2. 覆盖hive-site.xml的冲突配置
日志显示已加载/etc/spark/conf.dist/hive-site.xml,如果该文件里的hive.exec.scratchdir或hive.metastore.warehouse.dir和你设置的不一致,会导致Hive用旧路径。可以:
- 直接修改
hive-site.xml中的对应参数,指向S3正确路径; - 在SparkSession中用带
spark.hadoop前缀的配置强制覆盖:
.config("spark.hadoop.hive.exec.scratchdir", "s3://smt-sessionizer-stage-out/spark/hive/tmp")
3. 验证S3路径权限
虽然EMR实例有存储桶权限,但要确认是否存在路径级限制(比如存储桶策略或IAM策略是否明确允许访问spark/hive/tmp)。在EMR主节点执行以下命令测试:
# 列出目录,验证读权限 s3 ls s3://smt-sessionizer-stage-out/spark/hive/ # 上传测试文件,验证写权限 echo "test" > test.txt s3 cp test.txt s3://smt-sessionizer-stage-out/spark/hive/tmp/
4. 确保S3路径格式正确
所有涉及S3的路径必须用完整的s3://前缀,避免相对路径。Hive如果用了相对路径,会默认访问本地文件系统或S3根目录,触发权限错误。
内容的提问来源于stack exchange,提问作者Sunil

