authentication - Lectura local de archivos S3 a través de Spark(o mejor: pyspark)
amazon-s3 apache-spark (5)
Aquí hay una solución sobre cómo leer las credenciales de ~/.aws/credentials
. Hace uso del hecho de que el archivo de credenciales es un archivo INI que se puede analizar con el 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")
Vea también mi gist en https://gist.github.com/asmaier/5768c7cda3620901440a62248614bbd0 .
Quiero leer un archivo S3 desde mi máquina (local), a través de Spark (pyspark, en realidad). Ahora, sigo recibiendo errores de autenticación como
java.lang.IllegalArgumentException: AWS Access Key ID y Secret Access Key deben especificarse como el nombre de usuario o contraseña (respectivamente) de una URL s3n, o configurando las propiedades fs.s3n.awsAccessKeyId o fs.s3n.awsSecretAccessKey (respectivamente).
Busqué en todas partes aquí y en la web, probé muchas cosas, pero aparentemente el S3 ha cambiado durante el último año o los últimos meses, y todos los métodos fallaron, excepto uno:
pyspark.SparkContext().textFile("s3n://user:password@bucket/key")
(note que s3n
[ s3
no funcionó]). Ahora, no quiero usar una URL con el usuario y la contraseña porque pueden aparecer en los registros, y tampoco estoy seguro de cómo obtenerlos del archivo ~/.aws/credentials
.
Entonces, ¿cómo puedo leer localmente desde S3 hasta Spark (o, mejor, pyspark) usando las credenciales de AWS del archivo ~/.aws/credentials
ahora standard (idealmente, sin copiar las credenciales a otro archivo de configuración)?
PD: probé os.environ["AWS_ACCESS_KEY_ID"] = …
y os.environ["AWS_SECRET_ACCESS_KEY"] = …
, no funcionó.
PPS: no estoy seguro de dónde "establecer las propiedades fs.s3n.awsAccessKeyId o fs.s3n.awsSecretAccessKey" (Google no encontró nada). Sin embargo, probé muchas formas de configurar estos: SparkContext.setSystemProperty()
, sc.setLocalProperty()
y conf = SparkConf(); conf.set(…); conf.set(…); sc = SparkContext(conf=conf)
conf = SparkConf(); conf.set(…); conf.set(…); sc = SparkContext(conf=conf)
conf = SparkConf(); conf.set(…); conf.set(…); sc = SparkContext(conf=conf)
. Nada funcionó.
El problema fue en realidad un error en el módulo Python boto
de Amazon. El problema estaba relacionado con el hecho de que la versión de MacPort es realmente antigua: la instalación de boto
través de pip solucionó el problema: ~/.aws/credentials
se leyó correctamente.
Ahora que tengo más experiencia, diría que, en general (a partir de finales de 2015), las herramientas de Servicios Web de Amazon y Spark / PySpark tienen una documentación irregular y pueden tener algunos errores graves que son muy fáciles de encontrar. Para el primer problema, recomendaría actualizar primero la interfaz de la línea de comandos de aws, boto
y Spark cada vez que suceda algo extraño : esto ya ha solucionado "mágicamente" algunos problemas para mí.
La configuración de las variables de entorno podría ayudar.
Aquí en Spark Preguntas frecuentes bajo la pregunta "¿Cómo puedo acceder a los datos en S3?" sugieren establecer las variables de entorno AWS_ACCESS_KEY_ID
y AWS_SECRET_ACCESS_KEY
.
No puedo decir mucho sobre los objetos java que tienes que darle a la función hadoopFile, solo que esta función ya parece estar menospreciada para algunos "newAPIHadoopFile". La documentación sobre esto es bastante incompleta y creo que necesitas saber Scala / Java para llegar al fondo de todo lo que significa. Mientras tanto, descubrí cómo obtener realmente algunos datos s3 en pyspark y pensé que compartiría mis conclusiones. Esta documentación: la documentación de la API de Spark dice que utiliza un dict que se convierte en una configuración java (XML). Encontré la configuración para java, esto probablemente debería reflejar los valores que debe poner en el dict: Cómo acceder a S3 / S3n desde la instalación local 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)
Este fragmento de código carga el archivo del contenedor y el prefijo (ruta del archivo en el contenedor) especificados en las dos primeras líneas.
Sí, tienes que usar s3n
lugar de s3
. S3 es un abuso extraño de S3 cuyos beneficios no están claros para mí.
Puede pasar las credenciales a las llamadas sc.hadoopFile
o sc.newAPIHadoopFile
:
rdd = sc.hadoopFile(''s3n://my_bucket/my_file'', conf = {
''fs.s3n.awsAccessKeyId'': ''...'',
''fs.s3n.awsSecretAccessKey'': ''...'',
})