【问题标题】:403 Exception when attempting to build DataFrame from parquet file in S3 locally尝试从本地 S3 中的镶木地板文件构建 DataFrame 时出现 403 异常
【发布时间】:2019-11-19 12:40:42
【问题描述】:

我正在构建一个 Spark 应用程序并尝试在本地运行它,然后在 EMR 或容器中启动它。当 parquet 文件本身是本地的时,我可以让 DataFrame 正常工作,但如果它在 S3 中,它会拒绝读取 parquet 文件。我试图设置从 S3a 读取时建议的所有我能想到的变量,这就是我创建 Spark 会话的方式:

package util

import org.apache.spark.sql.SparkSession
import scala.io.Source

object SparkSessionFactory {

  def generateSession(sessionLocation: String): SparkSession = {
    val session = {
      sessionLocation match {
        case "local" =>
          SparkSession.builder().appName("LocalS3SparkProfiler").master("yarn").master("local[*]")
            .config("spark.driver.host", "localhost")
            .config("fs.s3a.enableServerSideEncryption", "true")
            .config("fs.s3a.serverSideEncryptionAlgorithm", "aws:kms")
            .getOrCreate()
      }
    }
    setHadoopConfigs(session, sessionLocation)
    session
  }

  private def setHadoopConfigs(session:SparkSession, sessionLocation:String) = {
    session.sparkContext.hadoopConfiguration.set("fs.s3a.impl", "org.apache.hadoop.fs.s3a.S3AFileSystem")
    session.sparkContext.hadoopConfiguration.set("fs.s3a.path.style.access", "true")
    sessionLocation match {
      case "local"=> {
        val userHome = System.getProperty("user.home")
        val aWSCredentialsLines = Source.fromFile(s"$userHome/.aws/credentials").getLines.toList

        val key = aWSCredentialsLines(1).substring(aWSCredentialsLines(1).lastIndexOf(" ")).trim
        val secret = aWSCredentialsLines(2).substring(aWSCredentialsLines(2).lastIndexOf(" ")).trim
        val s3Token = aWSCredentialsLines(3).substring(aWSCredentialsLines(3).lastIndexOf(" ")).trim

        session.sparkContext.hadoopConfiguration.set("fs.s3a.access.key", key)
        session.sparkContext.hadoopConfiguration.set("fs.s3a.secret.key", secret)
        session.sparkContext.hadoopConfiguration.set("fs.s3a.session.token", s3Token)
        session.sparkContext.hadoopConfiguration.set("fs.s3a.aws.credentials.provider", "org.apache.hadoop.fs.s3a.TemporaryAWSCredentialsProvider")
      }
    }
  }
}

然后当我尝试读取数据框时,我调用了

val spark = SparkSessionFactory.generateSession("local")
val df = spark.read.parquet("s3a://my-bucket/thepath/myparquetfile")

并且抛出的错误如下:

线程“main”中的异常 com.amazonaws.services.s3.model.AmazonS3Exception:禁止(服务: 亚马逊 S3;状态码:403;错误代码:403 禁止;请求编号: 366CFE11F21144F3; S3 扩展请求 ID: eW4C6PQZ4uSJOPmYKoZ8qCwmK4PwL6eFPwef9e1KLA3kL2LsiCMctZ+ZLYVplZh927iNiSro7ko=), S3 扩展请求 ID: eW4C6PQZ4uSJOPmYKoZ8qCwmK4PwL6eFPwef9e1KLA3kL2LsiCMctZ+ZLYVplZh927iNiSro7ko= 在 com.amazonaws.http.AmazonHttpClient$RequestExecutor.handleErrorResponse(AmazonHttpClient.java:1632) 在 com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeOneRequest(AmazonHttpClient.java:1304) 在 com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeHelper(AmazonHttpClient.java:1058) 在 com.amazonaws.http.AmazonHttpClient$RequestExecutor.doExecute(AmazonHttpClient.java:743) 在 com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeWithTimer(AmazonHttpClient.java:717) 在 com.amazonaws.http.AmazonHttpClient$RequestExecutor.execute(AmazonHttpClient.java:699) 在 com.amazonaws.http.AmazonHttpClient$RequestExecutor.access$500(AmazonHttpClient.java:667) 在 com.amazonaws.http.AmazonHttpClient$RequestExecutionBuilderImpl.execute(AmazonHttpClient.java:649) 在 com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:513) 在 com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:4330) 在 com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:4277) 在 com.amazonaws.services.s3.AmazonS3Client.getObjectMetadata(AmazonS3Client.java:1265)

我所阅读的所有内容都表明我需要的凭据就是我提供的凭据。我检查了 keysecrets3Token 值,它们看起来是正确的,因为我在另一个使用普通 AWS SDK 的项目中使用了这些凭据,没有问题。

知道问题是什么吗?

【问题讨论】:

    标签: scala apache-spark amazon-s3


    【解决方案1】:

    调试 AWS Auth 失败很困难,因为 AWS 和任何实施客户端的人都不想将机密记录到控制台。 “403”在调试上一般和“400”一样没用

    1. 看看Troubleshooting S3A
    2. 除了直接身份验证问题外,如果文件是使用您的账户无权访问的 AWS KMS 密钥进行 SSE-KMS 加密的文件,您会遇到身份验证失败。错误消息没有特别指出这一点。
    3. 尝试使用相同凭据的 AWS cli 以查看它们是否有效。如果他们让您看到数据,那么这不可避免地是一些 spark/s3a 配置问题。
    4. 下载最新版本的 Hadoop(最好是 3.2),安装它并使用选项配置它的 core-site.xml。然后使用Cloudstore storediag 让它对登录过程进行结构化调试。如果这不起作用,spark 也不会起作用。

    【讨论】:

      猜你喜欢
      • 2019-09-02
      • 1970-01-01
      • 2018-05-19
      • 1970-01-01
      • 2017-01-22
      • 2020-02-19
      • 2020-04-22
      • 1970-01-01
      • 2017-03-10
      相关资源
      最近更新 更多