Роли Spark + S3 + IAM - PullRequest
       17

Роли Spark + S3 + IAM

1 голос
/ 19 октября 2019

Я пытаюсь прочитать CSV-файл в корзине s3 из spark, используя роли IAM, но получаю NoClassDefFoundError на MultiObjectDeleteException

Я установил Spark 2.4.4 без hadoop и установил hadoop 3.2. 1 вместе с hadoop-aws-3.2.1.jar и aws-java-sdk-1.11.655.jar. Мне пришлось установить версию spark без hadoop, потому что jar hadoop, являющийся частью сборки spark, - это 2.7.3, начиная с 2016 года.

sc.hadoopConfiguration.set("fs.s3a.credentialsType", "AssumeRole")
sc.hadoopConfiguration.set("fs.s3a.assumed.role.arn", "arn:aws:iam::[ROLE]")
val myRDD = sc.textFile("s3a://test_bucket/names.csv")
myRDD.count()

Моя политика IAM, связанная с ролью, имеетследующий

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "s3:PutAccountPublicAccessBlock",
                "s3:GetAccountPublicAccessBlock",
                "s3:ListAllMyBuckets",
                "s3:ListJobs",
                "s3:CreateJob",
                "s3:HeadBucket"
            ],
            "Resource": "*"
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": "s3:*",
            "Resource": "arn:aws:s3:::test_bucket"
        }
    ]
}

Я даже пытался sc.hadoopConfiguration.set("fs.s3a.multiobjectdelete.enable", "false"), но та же ошибка, что и ниже:

java.lang.NoClassDefFoundError: com/amazonaws/services/s3/model/MultiObjectDeleteException
  at java.lang.Class.forName0(Native Method)
  at java.lang.Class.forName(Class.java:348)
  at org.apache.hadoop.conf.Configuration.getClassByNameOrNull(Configuration.java:2575)
  at org.apache.hadoop.conf.Configuration.getClassByName(Configuration.java:2540)
  at org.apache.hadoop.conf.Configuration.getClass(Configuration.java:2636)
  at org.apache.hadoop.fs.FileSystem.getFileSystemClass(FileSystem.java:3269)
  at org.apache.hadoop.fs.FileSystem.createFileSystem(FileSystem.java:3301)
  at org.apache.hadoop.fs.FileSystem.access$200(FileSystem.java:124)
  at org.apache.hadoop.fs.FileSystem$Cache.getInternal(FileSystem.java:3352)
  at org.apache.hadoop.fs.FileSystem$Cache.get(FileSystem.java:3320)
  at org.apache.hadoop.fs.FileSystem.get(FileSystem.java:479)
  at org.apache.hadoop.fs.Path.getFileSystem(Path.java:365)
  at org.apache.hadoop.mapred.FileInputFormat.singleThreadedListStatus(FileInputFormat.java:268)
  at org.apache.hadoop.mapred.FileInputFormat.listStatus(FileInputFormat.java:239)
  at org.apache.hadoop.mapred.FileInputFormat.getSplits(FileInputFormat.java:325)
  at org.apache.spark.rdd.HadoopRDD.getPartitions(HadoopRDD.scala:204)
  at org.apache.spark.rdd.RDD$$anonfun$partitions$2.apply(RDD.scala:253)
  at org.apache.spark.rdd.RDD$$anonfun$partitions$2.apply(RDD.scala:251)
  at scala.Option.getOrElse(Option.scala:121)
  at org.apache.spark.rdd.RDD.partitions(RDD.scala:251)
  at org.apache.spark.rdd.MapPartitionsRDD.getPartitions(MapPartitionsRDD.scala:49)
  at org.apache.spark.rdd.RDD$$anonfun$partitions$2.apply(RDD.scala:253)
  at org.apache.spark.rdd.RDD$$anonfun$partitions$2.apply(RDD.scala:251)
  at scala.Option.getOrElse(Option.scala:121)
  at org.apache.spark.rdd.RDD.partitions(RDD.scala:251)
  at org.apache.spark.SparkContext.runJob(SparkContext.scala:2126)
  at org.apache.spark.rdd.RDD.count(RDD.scala:1168)
  ... 49 elided
Caused by: java.lang.ClassNotFoundException: com.amazonaws.services.s3.model.MultiObjectDeleteException
  at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
  at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
  at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
  at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
  ... 76 more

Ответы [ 2 ]

1 голос
/ 22 октября 2019

Вышеуказанная проблема была связана с политикой IAM. У него не было политики для просмотра файла "/ *".

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetBucketLocation",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::test_bucket"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:PutObjectAcl",
                "s3:GetObject",
                "s3:DeleteObject"
            ],
            "Resource": [
                "arn:aws:s3:::test_bucket/*"
            ]
        }
    ]
}

Роль, которую вы создаете, будет иметь вышеуказанную политику IAM. Роль будет привязана к экземпляру EC2 (главному и подчиненному экземплярам AWS EC2), что очень важно, поскольку Spark возобновит роль того, что назначено экземпляру EC2. Поэтому, поскольку EC2 назначена роль, вам не нужно указывать роль в коде scala. Все, что вам нужно сделать, это написать следующий код Scala для чтения файла, который возобновит роль того, что назначено экземпляру EC2.

val myRDD = sc.textFile("s3a://test_bucket/test.csv")
myRDD.count()

hadoop-3.2.1.tar. У gz есть и hadoop-aws-3.2.1.jar, и aws-java-sdk-bundle-1.11.375.jar, расположенные в / opt / hadoop / share / hadoop / tools / lib

Здесь вы хотите убедиться, что вы определили spark-env.sh, который указывает на правильные каталоги jar, поэтому spark загружает jar-файлы в classpath.

cp /opt/spark/conf/spark-env.sh.template /opt/spark/conf/spark-env.sh

export SPARK_DIST_CLASSPATH=/opt/spark/jars:/opt/hadoop/etc/hadoop:/opt/hadoop/share/hadoop/common/lib/*:/opt/hadoop/share/hadoop/common/*:/opt/hadoop/share/hadoop/hdfs:/opt/hadoop/share/hadoop/hdfs/lib/*:/opt/hadoop/share/hadoop/hdfs/*:/opt/hadoop/share/hadoop/yarn/lib/*:/opt/hadoop/share/hadoop/yarn/*:/opt/hadoop/share/hadoop/mapreduce/lib/*:/opt/hadoop/share/hadoop/mapreduce/*:/opt/hadoop/contrib/capacity-scheduler/*.jar:/opt/hadoop/share/hadoop/tools/lib/*
0 голосов
/ 24 октября 2019

Нет варианта fs.s3a.credentialsType;для s3a все в нижнем регистре, что помогает отлаживать эти вещи,

Документы на учетные данные предполагаемой роли охватывают, какие разрешения необходимы https://hadoop.apache.org/docs/r3.1.0/hadoop-aws/tools/hadoop-aws/assumed_roles.html

Способ, которым это работает на hadoop 3.2, заключается в том, чтовызов, который должен иметь полные разрешения, а затем соединитель s3a вызывает STS AssumeRole, чтобы создать некоторые учетные данные недолгого сеанса в данной роли. В EC2 виртуальные машины не имеют разрешения на вызов AssumeRole (они уже выполняются в роли), поэтому вам нужно идти с тем, с чем когда-либо были созданы виртуальные машины.

Пока что используйте предполагаемую роль s3a дляПосмотрите, какую роль позволяют политики.

...