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é.
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.
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': '...',
})
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 .
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.
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.