web-dev-qa-db-fra.com

Lecture locale de fichiers S3 via Spark (ou mieux: pyspark)

Je veux lire un fichier S3 sur ma machine (locale), via Spark (pyspark, vraiment). Maintenant, je continue à recevoir des erreurs d'authentification comme

Java.lang.IllegalArgumentException: l'ID de clé d'accès AWS et la clé d'accès secrète doivent être spécifiés comme nom d'utilisateur ou mot de passe (respectivement) d'une URL s3n, ou en définissant les propriétés fs.s3n.awsAccessKeyId ou fs.s3n.awsSecretAccessKey (respectivement).

J'ai regardé partout ici et sur le Web, j'ai essayé beaucoup de choses, mais apparemment, S3 a changé au cours de la dernière année ou des derniers mois, et toutes les méthodes ont échoué sauf une:

pyspark.SparkContext().textFile("s3n://user:password@bucket/key")

(notez que s3n [s3 n'a pas fonctionné]). Maintenant, je ne veux pas utiliser une URL avec l'utilisateur et le mot de passe car ils peuvent apparaître dans les journaux, et je ne sais pas non plus comment les obtenir du fichier ~/.aws/credentials De toute façon.

Alors, comment puis-je lire localement de S3 à Spark (ou, mieux, pyspark) en utilisant les informations d'identification AWS du fichier maintenant standard~/.aws/credentials ( idéalement, sans copier les informations d'identification dans un autre fichier de configuration)?

PS: J'ai essayé os.environ["AWS_ACCESS_KEY_ID"] = … Et os.environ["AWS_SECRET_ACCESS_KEY"] = …, Cela n'a pas fonctionné.

PPS: je ne sais pas où "définir les propriétés fs.s3n.awsAccessKeyId ou fs.s3n.awsSecretAccessKey" (Google n'a rien trouvé). Cependant, j'ai essayé de nombreuses façons de les définir: SparkContext.setSystemProperty(), sc.setLocalProperty() et conf = SparkConf(); conf.set(…); conf.set(…); sc = SparkContext(conf=conf). Rien n'a fonctionné.

23
Eric O Lebigot

Le problème était en fait un bogue dans le module boto Python d'Amazon. Le problème était lié au fait que la version de MacPort est en fait ancienne: installation de boto via pip résolu le problème: ~/.aws/credentials a été correctement lu.

Maintenant que j'ai plus d'expérience, je dirais qu'en général (à la fin de 2015) les outils Amazon Web Services et Spark/PySpark ont ​​une documentation inégale et peuvent avoir de graves bugs qui sont très faciles à exécuter. Pour le premier problème, je recommanderais mettez d'abord à jour l'interface de ligne de commande aws, boto et Spark chaque fois que quelque chose d'étrange se produit: cela a " comme par magie ", j'ai déjà résolu quelques problèmes.

2
Eric O Lebigot

Oui, vous devez utiliser s3n au lieu de s3. s3 est un abus étrange de S3 dont les avantages ne sont pas clairs pour moi.

Vous pouvez transmettre les informations d'identification au sc.hadoopFile ou sc.newAPIHadoopFile appels:

rdd = sc.hadoopFile('s3n://my_bucket/my_file', conf = {
  'fs.s3n.awsAccessKeyId': '...',
  'fs.s3n.awsSecretAccessKey': '...',
})
7
Daniel Darabos

Voici une solution sur la façon de lire les informations d'identification de ~/.aws/credentials. Il utilise le fait que le fichier d'informations d'identification est un fichier INI qui peut être analysé avec le configparser de Python.

import os
import configparser

config = configparser.ConfigParser()
config.read(os.path.expanduser("~/.aws/credentials"))

aws_profile = 'default' # your AWS profile to use

access_id = config.get(aws_profile, "aws_access_key_id") 
access_key = config.get(aws_profile, "aws_secret_access_key") 

Voir aussi mon Gist à https://Gist.github.com/asmaier/5768c7cda3620901440a62248614bbd .

2
asmaier

La configuration des variables d'environnement pourrait aider.

Ici dans Spark FAQ sous la question "Comment puis-je accéder aux données dans S3?", Ils suggèrent de définir AWS_ACCESS_KEY_ID et AWS_SECRET_ACCESS_KEY Variables d'environnement.

1
Zeke Fast

Je ne peux pas en dire beaucoup sur les objets Java que vous devez donner à la fonction hadoopFile, mais seulement que cette fonction semble déjà privée pour certains "newAPIHadoopFile". La documentation à ce sujet est assez sommaire et j'ai l'impression que vous devez connaître Scala/Java pour vraiment comprendre ce que tout signifie. En attendant, j'ai compris comment obtenir des données s3 dans pyspark et j'ai pensé partager mes résultats. Cette documentation: Documentation de l'API Spark dit qu'il utilise un dict qui est converti en une configuration Java (XML). J'ai trouvé la configuration pour Java, cela devrait probablement refléter les valeurs dans lesquelles vous devriez mettre le dict: Comment accéder à S3/S3n depuis l'installation locale de hadoop

bucket = "mycompany-mydata-bucket"
prefix = "2015/04/04/mybiglogfile.log.gz"
filename = "s3n://{}/{}".format(bucket, prefix)

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

rdd = sc.hadoopFile(filename,
                    'org.Apache.hadoop.mapred.TextInputFormat',
                    'org.Apache.hadoop.io.Text',
                    'org.Apache.hadoop.io.LongWritable',
                    conf=config_dict)

Cet extrait de code charge le fichier à partir du compartiment et du préfixe (chemin du fichier dans le compartiment) spécifié sur les deux premières lignes.

0
firelynx