web-dev-qa-db-fra.com

Comment lire une entrée de S3 dans une application de cluster Spark Streaming EC2

J'essaie de forcer mon application Spark Streaming à lire ses entrées dans un répertoire S3, mais je continue à avoir cette exception après l'avoir lancée avec le script spark-submit

Exception in thread "main" Java.lang.IllegalArgumentException: AWS Access Key ID and Secret Access Key must be specified as the username or password (respectively) of a s3n URL, or by setting the fs.s3n.awsAccessKeyId or fs.s3n.awsSecretAccessKey properties (respectively).
    at org.Apache.hadoop.fs.s3.S3Credentials.initialize(S3Credentials.Java:66)
    at org.Apache.hadoop.fs.s3native.Jets3tNativeFileSystemStore.initialize(Jets3tNativeFileSystemStore.Java:49)
    at Sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at Sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.Java:57)
    at Sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.Java:43)
    at Java.lang.reflect.Method.invoke(Method.Java:606)
    at org.Apache.hadoop.io.retry.RetryInvocationHandler.invokeMethod(RetryInvocationHandler.Java:82)
    at org.Apache.hadoop.io.retry.RetryInvocationHandler.invoke(RetryInvocationHandler.Java:59)
    at org.Apache.hadoop.fs.s3native.$Proxy6.initialize(Unknown Source)
    at org.Apache.hadoop.fs.s3native.NativeS3FileSystem.initialize(NativeS3FileSystem.Java:216)
    at org.Apache.hadoop.fs.FileSystem.createFileSystem(FileSystem.Java:1386)
    at org.Apache.hadoop.fs.FileSystem.access$200(FileSystem.Java:66)
    at org.Apache.hadoop.fs.FileSystem$Cache.get(FileSystem.Java:1404)
    at org.Apache.hadoop.fs.FileSystem.get(FileSystem.Java:254)
    at org.Apache.hadoop.fs.Path.getFileSystem(Path.Java:187)
    at org.Apache.spark.streaming.StreamingContext.checkpoint(StreamingContext.scala:195)
    at MainClass$.main(MainClass.scala:1190)
    at MainClass.main(MainClass.scala)
    at Sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at Sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.Java:57)
    at Sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.Java:43)
    at Java.lang.reflect.Method.invoke(Method.Java:606)
    at org.Apache.spark.deploy.SparkSubmit$.launch(SparkSubmit.scala:292)
    at org.Apache.spark.deploy.SparkSubmit$.main(SparkSubmit.scala:55)
    at org.Apache.spark.deploy.SparkSubmit.main(SparkSubmit.scala)

Je mets ces variables dans ce bloc de code comme suggéré ici http://spark.Apache.org/docs/latest/ec2-scripts.html (bas de la page):

val ssc = new org.Apache.spark.streaming.StreamingContext(
  conf,
  Seconds(60))
ssc.sparkContext.hadoopConfiguration.set("fs.s3n.awsAccessKeyId",args(2))
ssc.sparkContext.hadoopConfiguration.set("fs.s3n.awsSecretAccessKey",args(3))

args (2) et args (3) sont bien sûr mes identifiants de clé d'accès AWS et de clé d'accès Secrete.

Pourquoi continue à dire qu'ils ne sont pas réglés? 

EDIT: J'ai aussi essayé de cette façon, mais j'ai la même exception:

val lines = ssc.textFileStream("s3n://"+ args(2) +":"+ args(3) + "@<mybucket>/path/")
26
gprivitera

Impair. Essayez également de faire un .set sur la sparkContext. Essayez également d'exporter des variables env avant de démarrer l'application:

export AWS_ACCESS_KEY_ID=<your access>
export AWS_SECRET_ACCESS_KEY=<your secret>

^^ c'est comme ça qu'on le fait.

MISE À JOUR: Selon @tribbloid, ce qui précède s’est rompu dans la version 1.3.0, vous devez maintenant naviguer pendant des siècles avec hdfs-site.xml, ou vous pouvez le faire (et cela fonctionne dans un spark-shell):

val hadoopConf = sc.hadoopConfiguration;
hadoopConf.set("fs.s3.impl", "org.Apache.hadoop.fs.s3native.NativeS3FileSystem")
hadoopConf.set("fs.s3.awsAccessKeyId", myAccessKey)
hadoopConf.set("fs.s3.awsSecretAccessKey", mySecretKey)
23
samthebest

La configuration suivante fonctionne pour moi, assurez-vous de définir également "fs.s3.impl":

val conf = new SparkConf().setAppName("Simple Application").setMaster("local")      
val sc = new SparkContext(conf)
val hadoopConf=sc.hadoopConfiguration;
hadoopConf.set("fs.s3.impl", "org.Apache.hadoop.fs.s3native.NativeS3FileSystem")
hadoopConf.set("fs.s3.awsAccessKeyId",myAccessKey)
hadoopConf.set("fs.s3.awsSecretAccessKey",mySecretKey)
22
harel

Pour ceux qui utilisent EMR, utilisez la version Spark comme décrit à https://github.com/awslabs/emr-bootstrap-actions/tree/master/spark et faites simplement référence à S3 avec l'URI s3: //. Il n'est pas nécessaire de définir l'implémentation S3 ou une configuration supplémentaire, car les informations d'identification sont définies par IAM ou par rôle. 

3
ChristopherB

Sur AWS EMR, les suggestions ci-dessus ne fonctionnaient pas. Au lieu de cela, j'ai mis à jour les propriétés suivantes dans le fichier conf/core-site.xml:

fs.s3n.awsAccessKeyId et fs.s3n.awsSecretAccessKey avec vos informations d'identification S3. 

3
Ishika Paul

Je voulais mettre les informations d'identification de manière plus sécurisée dans un fichier de configuration sur l'une de mes partitions chiffrées. J'ai donc utilisé export HADOOP_CONF_DIR=~/Private/.aws/hadoop_conf avant d'exécuter mon application spark et placé un fichier dans ce répertoire (chiffré via ecryptfs) appelé core-site.xml contenant les informations d'identification suivantes:

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
  <property>
  <name>fs.s3n.awsAccessKeyId</name>
  <value>my_aws_access_key_id_here</value>
  </property>
  <property>
  <name>fs.s3n.awsSecretAccessKey</name>
  <value>my_aws_secret_access_key_here</value>
  </property>
</configuration>

HADOOP_CONF_DIR peut également être défini dans conf/spark-env.sh.

3
nealmcb

Les dernières versions d'EMR (testées sur 4.6.0) requièrent la configuration suivante:

val sc = new SparkContext(conf)
val hadoopConf = sc.hadoopConfiguration
hadoopConf.set("fs.s3.impl", "com.Amazon.ws.emr.hadoop.fs.EmrFileSystem")
hadoopConf.set("fs.s3.awsAccessKeyId", myAccessKey)
hadoopConf.set("fs.s3.awsSecretAccessKey", mySecretKey)

Bien que dans la plupart des cas, la configuration prête à l'emploi devrait fonctionner - c'est le cas si vous avez des informations d'identification S3 différentes de celles avec lesquelles vous avez lancé le cluster.

2
Dan Osipov

En Java, voici les lignes de code. Vous devez ajouter des creds AWS dans SparkContext uniquement et non pas SparkSession.

JavaSparkContext sc = new JavaSparkContext(spark.sparkContext());
sc.hadoopConfiguration().set("fs.s3a.access.key", AWS_KEY);
sc.hadoopConfiguration().set("fs.s3a.secret.key", AWS_SECRET_KEY);
0
Atihska

En augmentant la réponse de @ nealmcb, le moyen le plus simple de le faire est de définir 

HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoop 

dans conf/spark-env.sh ou exporter cette variable env dans ~/.bashrc ou ~/.bash_profile

Cela fonctionnera tant que vous pourrez accéder à s3 via hadoop. Par exemple, si vous pouvez exécuter 

hadoop fs -ls s3n://path/

hadoop peut alors voir le chemin s3. 

Si hadoop ne peut pas voir le chemin, suivez les conseils contenus dans Comment accéder à S3/S3n à partir d’une installation Hadoop 2.6 locale?

0
Bob Baxley

cela fonctionne pour moi dans 1.4.1 Shell:

val conf = sc.getConf
conf.set("spark.hadoop.fs.s3.impl", "org.Apache.hadoop.fs.s3native.NativeS3FileSystem")
conf.set("spark.hadoop.fs.s3.awsAccessKeyId", <your access key>)
conf.set("spark.hadoop.fs.s3.awsSecretAccessKey", <your secret key>)
SparkHadoopUtil.get.conf.addResource(SparkHadoopUtil.get.newConfiguration(conf))
...
sqlContext.read.parquet("s3://...")
0
ru2nuts