2015-07-18 20 views
7

Kamuya açık bir Amazon s3 kaynağım (metin dosyası) var ve bu kaynağa erişmek istiyorum. Bunun anlamı - Hiç Amazon kimlik yok - Az önce indirmek istiyorsanız iyi çalışıyor:Erişilebilir erişim mevcuttur Amazon S3 dosyası: Apache Spark

val bucket = "<my-bucket>" 
val key = "<my-key>" 

val client = new AmazonS3Client 
val o = client.getObject(bucket, key) 
val content = o.getObjectContent // <= can be read and used as input stream 

Ancak, kıvılcım bağlamda

val conf = new SparkConf().setAppName("app").setMaster("local") 
val sc = new SparkContext(conf) 
val f = sc.textFile(s"s3a://$bucket/$key") 
println(f.count()) 

aynı kaynağı erişmeye çalıştığınızda aşağıdaki stacktrace hatayı alırsınız:

Exception in thread "main" com.amazonaws.AmazonClientException: Unable to load AWS credentials from any provider in the chain 
    at com.amazonaws.auth.AWSCredentialsProviderChain.getCredentials(AWSCredentialsProviderChain.java:117) 
    at com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:3521) 
    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:2653) 
    at org.apache.hadoop.fs.FileSystem.access$200(FileSystem.java:92) 
    at org.apache.hadoop.fs.FileSystem$Cache.getInternal(FileSystem.java:2687) 
    at org.apache.hadoop.fs.FileSystem$Cache.get(FileSystem.java:2669) 
    at org.apache.hadoop.fs.FileSystem.get(FileSystem.java:371) 
    at org.apache.hadoop.fs.Path.getFileSystem(Path.java:295) 
    at org.apache.hadoop.mapred.FileInputFormat.listStatus(FileInputFormat.java:221) 
    at org.apache.hadoop.mapred.FileInputFormat.getSplits(FileInputFormat.java:270) 
    at org.apache.spark.rdd.HadoopRDD.getPartitions(HadoopRDD.scala:207) 
    at org.apache.spark.rdd.RDD$$anonfun$partitions$2.apply(RDD.scala:219) 
    at org.apache.spark.rdd.RDD$$anonfun$partitions$2.apply(RDD.scala:217) 
    at scala.Option.getOrElse(Option.scala:121) 
    at org.apache.spark.rdd.RDD.partitions(RDD.scala:217) 
    at org.apache.spark.rdd.MapPartitionsRDD.getPartitions(MapPartitionsRDD.scala:32) 
    at org.apache.spark.rdd.RDD$$anonfun$partitions$2.apply(RDD.scala:219) 
    at org.apache.spark.rdd.RDD$$anonfun$partitions$2.apply(RDD.scala:217) 
    at scala.Option.getOrElse(Option.scala:121) 
    at org.apache.spark.rdd.RDD.partitions(RDD.scala:217) 
    at org.apache.spark.SparkContext.runJob(SparkContext.scala:1781) 
    at org.apache.spark.rdd.RDD.count(RDD.scala:1099) 
    at com.example.Main$.main(Main.scala:14) 
    at com.example.Main.main(Main.scala) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:497) 
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140) 

herhangi AWS kimlik bilgilerini sağlamak istemiyoruz - sadece (şimdilik) anonim kaynağa erişmek istiyorum - nasıl bunu başarmak için? Muhtemelen AnonymousAWSCredentialsProvider gibi bir şey kullanmalıyım - ama bunu kıvılcım veya hadoop içine nasıl koyabilirim?

P.S. Benim durumum sadece durum

scalaVersion := "2.11.7" 

libraryDependencies ++= Seq(
    "org.apache.spark" %% "spark-core" % "1.4.1", 
    "org.apache.hadoop" % "hadoop-aws" % "2.7.1" 
) 

GÜNCELLEME: Bazı araştırmaları yaptıktan sonra - çalışmamasının nedenini gördüm. Her şeyden

Birincisi, S3AFileSystem kimlik bilgilerinin aşağıdaki sırayla ile AWS istemcisi oluşturur:

AWSCredentialsProviderChain credentials = new AWSCredentialsProviderChain(
    new BasicAWSCredentialsProvider(accessKey, secretKey), 
    new InstanceProfileCredentialsProvider(), 
    new AnonymousAWSCredentialsProvider() 
); 

"accessKey" ve "SecretKey" değerlerini kıvılcım conf örneği alınır (tuşlar "fs.s3a olmalıdır. access.key "ve" fs.s3a.secret.key "veya org.apache.hadoop.fs.s3a.Constants.ACCESS_KEY ve org.apache.hadoop.fs.s3a.Constants.SECRET_KEY sabitleri, hangisi daha uygunsa).

İkincisi - muhtemelen AnonymousAWSCredentialsProvider'ın üçüncü seçenek (son öncelik) olduğunu görüyorsunuz - bunun nesi yanlış olabilir? Bu sadece erişim anahtarı ve gizli anahtar her ikisi için null döndürür

public class AnonymousAWSCredentials implements AWSCredentials { 

    public String getAWSAccessKeyId() { 
     return null; 
    } 

    public String getAWSSecretKey() { 
     return null; 
    } 
} 

: AnonymousAWSCredentials uygulanmasını bakın. Makul geliyor. Ama AWSCredentialsProviderChain içine bakmak: Hem tuşlar boş olduğu durumda sağlayıcı seçmez

AWSCredentials credentials = provider.getCredentials(); 

if (credentials.getAWSAccessKeyId() != null && 
    credentials.getAWSSecretKey() != null) { 
    log.debug("Loading credentials from " + provider.toString()); 

    lastUsedProvider = provider; 
    return credentials; 
} 

- anonim kimlik bilgileri çalışmaz anlamına gelir. Aws-java-sdk-1.7.4 içinde bir hataya benziyor. En son sürümü kullanmaya çalıştım - ama hadoop-aws-2.7.1 ile uyumsuz.

Başka bir fikrin var mı?

+0

aracılığıyla sunulan AWS CLI

  • Örnek profil kimlik paylaştığı aws/kimlik bilgileri)? –

  • +0

    hayır, bunu bir süredir denemedim - bunu bile unuttum, hiçbir şey içinzon s3 kullanmayın – pkozlov

    cevap

    3

    Kişisel olarak Spark'den herkese açık veriye hiç erişmedim. Sahte kimlik bilgilerini kullanmaya veya yalnızca bu kullanım için olanları oluşturmaya çalışabilirsiniz. Onları doğrudan SparkConf nesnesine yerleştirin.

    val sparkConf: SparkConf = ??? 
    val accessKeyId: String = ??? 
    val secretAccessKey: String = ??? 
    sparkConf.set("spark.hadoop.fs.s3.awsAccessKeyId", accessKeyId) 
    sparkConf.set("spark.hadoop.fs.s3n.awsAccessKeyId", accessKeyId) 
    sparkConf.set("spark.hadoop.fs.s3.awsSecretAccessKey", secretAccessKey) 
    sparkConf.set("spark.hadoop.fs.s3n.awsSecretAccessKey", secretAccessKey) 
    

    alternatif olarak kimlik bilgileri aradı nerede görmek DefaultAWSCredentialsProviderChain belgelerini okuyun. Liste (sipariş önemlidir) 'dir:

    • Ortam Değişkenleri - AWS_ACCESS_KEY_ID ve AWS_SECRET_KEY
    • Java Sistem Özellikleri - aws.accessKeyId ve aws.secretKey
    • Kimlik profilleri varsayılan konumda dosya (~/.Tüm AWS SDK'larından ve Amazon EC2 meta hizmeti belki daha yeni sürümleri ile herhangi bir başarı, oldu
    +0

    Bir şeyler hala yanlış. Bana verdiğin anahtarlara aşağıdaki değerleri ekledim (tam anlamıyla "aaa" kukla kimlik bilgileri). En kötüsünde hatayı görmeyi bekledim ama aynı istisnayı görüyorum "Zincirdeki herhangi bir sağlayıcıdan AWS kimlik bilgileri yüklenemedi" – pkozlov

    +1

    Doğru anahtarlar "spark.hadoop.fs.s3a.access.key" ve "doğru" olmalıdır. Bu arada, kukla değerler sağlamaya yardımcı olmadı - şimdi 403 hatası görüyorum.Ask ile AWS S3 için anonim kimlik bilgilerini kullanmak imkansız gibi görünüyor Ve göre kaynak kodu - kimlik bilgileri sırası farklıdır AWSCredentialsProviderChain kimlik = yeni AWSCredentialsProviderChain ( yeni BasicAWSCredentialsProvider (accessKey, SecretKey), yeni InstanceProfileCredentialsProvider(), yeni AnonymousAWSCredentialsProvider() ); ve. anonim sadece çalışmıyor. – pkozlov

    +0

    Tamam, pardon 's3a' protokolünü kullandığınızı görmedim. S3n' ile denedin mi? –