aws 使用 IAM 角色从 spark 访问 s3

aws access s3 from spark using IAM role

我想从 spark 访问 s3,我不想配置任何秘密和访问密钥,我想通过配置 IAM 角色来访问,所以我按照 s3-spark

但我的 EC2 实例(运行 独立 spark)仍然无法正常工作

我测试的时候有效

[ec2-user@ip-172-31-17-146 bin]$ aws s3 ls s3://testmys3/
2019-01-16 17:32:38        130 e.json

但是当我像下面这样尝试时它没有用

scala> val df = spark.read.json("s3a://testmys3/*")

我收到以下错误

19/01/16 18:23:06 WARN FileStreamSink: Error while looking for metadata directory.
com.amazonaws.services.s3.model.AmazonS3Exception: Status Code: 400, AWS Service: Amazon S3, AWS Request ID: E295957C21AFAC37, AWS Error Code: null, AWS Error Message: Bad Request
  at com.amazonaws.http.AmazonHttpClient.handleErrorResponse(AmazonHttpClient.java:798)
  at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:421)
  at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:232)
  at com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:3528)
  at com.amazonaws.services.s3.AmazonS3Client.headBucket(AmazonS3Client.java:1031)
  at com.amazonaws.services.s3.AmazonS3Client.doesBucketExist(AmazonS3Client.java:994)
  at org.apache.hadoop.fs.s3a.S3AFileSystem.initialize(S3AFileSystem.java:297)
  at org.apache.hadoop.fs.FileSystem.createFileSystem(FileSystem.java:2669)
  at org.apache.hadoop.fs.FileSystem.access0(FileSystem.java:94)
  at org.apache.hadoop.fs.FileSystem$Cache.getInternal(FileSystem.java:2703)
  at org.apache.hadoop.fs.FileSystem$Cache.get(FileSystem.java:2685)
  at org.apache.hadoop.fs.FileSystem.get(FileSystem.java:373)
  at org.apache.hadoop.fs.Path.getFileSystem(Path.java:295)
  at org.apache.spark.sql.execution.datasources.DataSource$.org$apache$spark$sql$execution$datasources$DataSource$$checkAndGlobPathIfNecessary(DataSource.scala:616)

“400 Bad Request”是相当无用的,不仅 S3 没有提供太多,S3A 连接器也没有与 auth 相关的日期打印。 troubleshooting the error

上有很大一部分

它发出请求的事实意味着它有一些凭据,只是远端不喜欢它们

可能性

  • 您的 IAM 角色没有 s3:ListBucket 的权限。参见 IAM role permissions for working with s3a
  • 您的存储桶名称错误
  • fs.s3a 或 AWS_env vars 中的某些设置优先于 IAM 角色,但它们是错误的。

您应该自动将 IAM 身份验证作为 S3A 连接器的身份验证机制;它是最后检查的那个:config & env vars.

  1. 查看 fs.s3a.aws.credentials.provider 中设置的内容 - 它必须未设置或包含选项 com.amazonaws.auth.InstanceProfileCredentialsProvider
  2. 假设你在命令行上也有 hadoop,抓取 storediag
hadoop jar cloudstore-0.1-SNAPSHOT.jar storediag s3a://testmys3/

它应该转储有关身份验证的内容。

更新

正如发帖人评论的那样,这是由于特定 S3 端点需要 v4 身份验证。这可以在 2.7.x 版本的 s3a 客户端上启用,但只能通过 Java 系统属性。对于 2.8+,有一些 fs.s3a。您可以设置它的选项

此配置有效

    ./spark-shell \
        --packages com.amazonaws:aws-java-sdk:1.7.4,org.apache.hadoop:hadoop-aws:2.7.3 \
        --conf spark.hadoop.fs.s3a.endpoint=s3.us-east-2.amazonaws.com \
spark.hadoop.fs.s3a.aws.credentials.provider=com.amazonaws.auth.InstanceProfileCredentialsProvider \
        --conf spark.executor.extraJavaOptions=-Dcom.amazonaws.services.s3.enableV4=true \
        --conf spark.driver.extraJavaOptions=-Dcom.amazonaws.services.s3.enableV4=true  

  • 第一步。配置像 Yarn core-site.xml.Then 这样的 spark 容器框架 重启 Yarn

fs.s3a.aws.credentials.provider-- com.cloudera.com.amazonaws.auth.InstanceProfileCredentialsProvider

fs.s3a.endpoint-- s3-ap-northeast-2.amazonaws.com

fs.s3.impl-- org.apache.hadoop.fs.s3a.S3AFileSystem

  • 第二步。 spark shell 进行如下测试。

val rdd=sc.textFile("s3a://path/file")
 rdd.count()
 rdd.take(10).foreach(println)

对我有用