web-dev-qa-db-fra.com

Connectez-vous aux données S3 de PySpark

J'essaie de lire un fichier JSON, à partir d'Amazon s3, pour créer un contexte d'étincelle et l'utiliser pour traiter les données. 

Spark est fondamentalement dans un conteneur docker. Donc, mettre des fichiers dans le chemin du docker, c'est aussi PITA. Par conséquent poussé à S3. 

Le code ci-dessous explique le reste des choses. 

from pyspark import SparkContext, SparkConf
conf = SparkConf().setAppName("first")
sc = SparkContext(conf=conf)

config_dict = {"fs.s3n.awsAccessKeyId":"**",
               "fs.s3n.awsSecretAccessKey":"**"}

bucket = "nonamecpp"
prefix = "dataset.json"
filename = "s3n://{}/{}".format(bucket, prefix)
rdd = sc.hadoopFile(filename,
                    'org.Apache.hadoop.mapred.TextInputFormat',
                    'org.Apache.hadoop.io.Text',
                    'org.Apache.hadoop.io.LongWritable',
                    conf=config_dict)

Je reçois l'erreur suivante - 

Py4JJavaError                             Traceback (most recent call last)
<ipython-input-2-b94543fb0e8e> in <module>()
      9                     'org.Apache.hadoop.io.Text',
     10                     'org.Apache.hadoop.io.LongWritable',
---> 11                     conf=config_dict)
     12 

/usr/local/spark/python/pyspark/context.pyc in hadoopFile(self, path, inputFormatClass, keyClass, valueClass, keyConverter, valueConverter, conf, batchSize)
    558         jrdd = self._jvm.PythonRDD.hadoopFile(self._jsc, path, inputFormatClass, keyClass,
    559                                               valueClass, keyConverter, valueConverter,
--> 560                                               jconf, batchSize)
    561         return RDD(jrdd, self)
    562 

/usr/local/lib/python2.7/dist-packages/py4j/Java_gateway.pyc in __call__(self, *args)
    536         answer = self.gateway_client.send_command(command)
    537         return_value = get_return_value(answer, self.gateway_client,
--> 538                 self.target_id, self.name)
    539 
    540         for temp_arg in temp_args:

/usr/local/lib/python2.7/dist-packages/py4j/protocol.pyc in get_return_value(answer, gateway_client, target_id, name)
    298                 raise Py4JJavaError(
    299                     'An error occurred while calling {0}{1}{2}.\n'.
--> 300                     format(target_id, '.', name), value)
    301             else:
    302                 raise Py4JError(

Py4JJavaError: An error occurred while calling z:org.Apache.spark.api.python.PythonRDD.hadoopFile.
: 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:70)
    at org.Apache.hadoop.fs.s3native.Jets3tNativeFileSystemStore.initialize(Jets3tNativeFileSystemStore.Java:73)
    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:190)
    at org.Apache.hadoop.io.retry.RetryInvocationHandler.invoke(RetryInvocationHandler.Java:103)
    at org.Apache.hadoop.fs.s3native.$Proxy20.initialize(Unknown Source)
    at org.Apache.hadoop.fs.s3native.NativeS3FileSystem.initialize(NativeS3FileSystem.Java:272)
    at org.Apache.hadoop.fs.FileSystem.createFileSystem(FileSystem.Java:2397)
    at org.Apache.hadoop.fs.FileSystem.access$200(FileSystem.Java:89)
    at org.Apache.hadoop.fs.FileSystem$Cache.getInternal(FileSystem.Java:2431)
    at org.Apache.hadoop.fs.FileSystem$Cache.get(FileSystem.Java:2413)
    at org.Apache.hadoop.fs.FileSystem.get(FileSystem.Java:368)
    at org.Apache.hadoop.fs.Path.getFileSystem(Path.Java:296)
    at org.Apache.hadoop.mapred.FileInputFormat.singleThreadedListStatus(FileInputFormat.Java:256)
    at org.Apache.hadoop.mapred.FileInputFormat.listStatus(FileInputFormat.Java:228)
    at org.Apache.hadoop.mapred.FileInputFormat.getSplits(FileInputFormat.Java:304)
    at org.Apache.spark.rdd.HadoopRDD.getPartitions(HadoopRDD.scala:201)
    at org.Apache.spark.rdd.RDD$$anonfun$partitions$2.apply(RDD.scala:205)
    at org.Apache.spark.rdd.RDD$$anonfun$partitions$2.apply(RDD.scala:203)
    at scala.Option.getOrElse(Option.scala:120)
    at org.Apache.spark.rdd.RDD.partitions(RDD.scala:203)
    at org.Apache.spark.rdd.MappedRDD.getPartitions(MappedRDD.scala:28)
    at org.Apache.spark.rdd.RDD$$anonfun$partitions$2.apply(RDD.scala:205)
    at org.Apache.spark.rdd.RDD$$anonfun$partitions$2.apply(RDD.scala:203)
    at scala.Option.getOrElse(Option.scala:120)
    at org.Apache.spark.rdd.RDD.partitions(RDD.scala:203)
    at org.Apache.spark.rdd.RDD.take(RDD.scala:1060)
    at org.Apache.spark.rdd.RDD.first(RDD.scala:1093)
    at org.Apache.spark.api.python.SerDeUtil$.pairRDDToPython(SerDeUtil.scala:202)
    at org.Apache.spark.api.python.PythonRDD$.hadoopFile(PythonRDD.scala:543)
    at org.Apache.spark.api.python.PythonRDD.hadoopFile(PythonRDD.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 py4j.reflection.MethodInvoker.invoke(MethodInvoker.Java:231)
    at py4j.reflection.ReflectionEngine.invoke(ReflectionEngine.Java:379)
    at py4j.Gateway.invoke(Gateway.Java:259)
    at py4j.commands.AbstractCommand.invokeMethod(AbstractCommand.Java:133)
    at py4j.commands.CallCommand.execute(CallCommand.Java:79)
    at py4j.GatewayConnection.run(GatewayConnection.Java:207)
    at Java.lang.Thread.run(Thread.Java:744)

J'ai clairement fourni aswSecretAccessKey et awsAccessId. Qu'est-ce qui ne va pas?

8
Elon Musk

J'ai résolu d'ajouter --packages org.Apache.hadoop:hadoop-aws:2.7.1 dans la commande spark-submit.

Il téléchargera tous les paquets manquants hadoop qui vous permettront d'exécuter des travaux d'étincelle avec S3.

Ensuite, dans votre travail, vous devez définir vos informations d'identification AWS telles que:

sc._jsc.hadoopConfiguration().set("fs.s3n.awsAccessKeyId", aws_id)
sc._jsc.hadoopConfiguration().set("fs.s3n.awsSecretAccessKey", aws_key)

Une autre option pour définir vos identifiants est de les définir dans spark/conf/spark-env:

#!/usr/bin/env bash
AWS_ACCESS_KEY_ID='xxxx'
AWS_SECRET_ACCESS_KEY='xxxx'

SPARK_WORKER_CORES=1 # to set the number of cores to use on this machine
SPARK_WORKER_MEMORY=1g # to set how much total memory workers have to give executors (e.g. 1000m, 2g)
SPARK_EXECUTOR_INSTANCES=10 #, to set the number of worker processes per node

Plus d'informations: 

12
Franzi

Je suggère de passer par ce lien .

Dans mon cas, j'ai utilisé Informations d'identification de profil d'instance pour accéder aux données s3.

Informations d'identification de profil d'instance: utilisées sur les instances EC2 et transmises Via le service de métadonnées Amazon EC2. AWS SDK for Java utilise InstanceProfileCredentialsProvider pour charger ces informations d'identification.

Remarque

Les informations d'identification du profil d'instance ne sont utilisées que si AWS_CONTAINER_CREDENTIALS_RELATIVE_URI n'est pas défini. Voir EC2ContainerCredentialsProviderWrapper pour plus d'informations.

Pour pyspark, j'utilise les paramètres pour accéder au contenu s3.

def get_spark_context(app_name):
    # configure
    conf = pyspark.SparkConf()

    # init & return
    sc = pyspark.SparkContext.getOrCreate(conf=conf)

    # s3a config
    sc._jsc.hadoopConfiguration().set('fs.s3a.endpoint',
                                      's3.eu-central-1.amazonaws.com')
    sc._jsc.hadoopConfiguration().set(
        'fs.s3a.aws.credentials.provider',
        'com.amazonaws.auth.InstanceProfileCredentialsProvider,'
        'com.amazonaws.auth.profile.ProfileCredentialsProvider'
    )

    return pyspark.SQLContext(sparkContext=sc)

Plus sur le contexte des étincelles ici .

Veuillez consulter this pour un accès de type S3.

0
Amit Kushwaha