Apache spark Fargate can上的火花';找不到本地IP

Apache spark Fargate can上的火花';找不到本地IP,apache-spark,pyspark,containers,spark-submit,Apache Spark,Pyspark,Containers,Spark Submit,我有一个构建工作,我正试图在一个由1个节点组成的AWS Fargate集群中进行设置。当我试图运行Spark来构建数据时,我得到了一个错误,似乎是因为Java无法找到“localHost” 我通过运行一个脚本来设置配置,该脚本添加spark env.sh文件,更新/etc/hosts文件,并更新spark defaults.conf文件 在$SPARK_HOME/conf/SPARK env.sh文件中,我添加了: SPARK\u LOCAL\u IP SPARK\u MASTER\u主机

我有一个构建工作,我正试图在一个由1个节点组成的AWS Fargate集群中进行设置。当我试图运行Spark来构建数据时,我得到了一个错误,似乎是因为Java无法找到“localHost”

我通过运行一个脚本来设置配置,该脚本添加
spark env.sh
文件,更新
/etc/hosts
文件,并更新
spark defaults.conf
文件

$SPARK_HOME/conf/SPARK env.sh
文件中,我添加了:

  • SPARK\u LOCAL\u IP
  • SPARK\u MASTER\u主机
$SPARK\u HOME/conf/SPARK defaults.conf

  • spark.jars.packages
  • spark.master
  • spark.driver.bindAddress
  • spark.driver.host
/etc/hosts
文件中,我附加:

  • master
通过传递带有IP或URL的
-master
参数来调用
spark submit
脚本似乎没有帮助

我尝试过使用
local[*]
spark://:
变体,但都没有用。 使用
127.0.0.1
localhost
与使用
master
和从元数据返回的IP相比,似乎没有什么不同

在AWS方面,Fargate集群运行在连接了NatGateway的私有子网中,因此据我所知,它确实有进出网络路由。我已经尝试使用公共网络并启用了ECS自动将公共IP连接到容器的设置。 Spark docs的所有标准端口也在容器上打开

它似乎一直运行良好,直到它试图收集自己的IP为止

我返回的错误在堆栈中有以下内容:

spark.jars.packages com.amazonaws:aws-java-sdk:1.7.4,org.apache.hadoop:hadoop-aws:2.7.2
spark.master spark://10.0.41.190:7077
Spark Command: /docker-java-home/bin/java -cp /usr/spark/conf/:/usr/spark/jars/* -Xmx1gg org.apache.spark.deploy.SparkSubmit --master spark://10.0.41.190:7077 --verbose --jars lib/RedshiftJDBC42-1.2.12.1017.jar --packages org.apache.hadoop:hadoop-aws:2.7.3,com.amazonaws:aws-java-sdk:1.7.4,com.upplication:s3fs:2.2.1 ./build_phase.py
========================================
Using properties file: /usr/spark/conf/spark-defaults.conf
Exception in thread "main" java.lang.ExceptionInInitializerError
at org.apache.spark.util.Utils$.redact(Utils.scala:2653)
at org.apache.spark.deploy.SparkSubmitArguments$$anonfun$defaultSparkProperties$1.apply(SparkSubmitArguments.scala:93)
at org.apache.spark.deploy.SparkSubmitArguments$$anonfun$defaultSparkProperties$1.apply(SparkSubmitArguments.scala:86)
at scala.Option.foreach(Option.scala:257)
at org.apache.spark.deploy.SparkSubmitArguments.defaultSparkProperties$lzycompute(SparkSubmitArguments.scala:86)
at org.apache.spark.deploy.SparkSubmitArguments.defaultSparkProperties(SparkSubmitArguments.scala:82)
at org.apache.spark.deploy.SparkSubmitArguments.mergeDefaultSparkProperties(SparkSubmitArguments.scala:126)
at org.apache.spark.deploy.SparkSubmitArguments.<init>(SparkSubmitArguments.scala:110)
at org.apache.spark.deploy.SparkSubmit$.main(SparkSubmit.scala:112)
at org.apache.spark.deploy.SparkSubmit.main(SparkSubmit.scala)
Caused by: java.net.UnknownHostException: d4771b650361: d4771b650361: Name or service not known
at java.net.InetAddress.getLocalHost(InetAddress.java:1505)
at org.apache.spark.util.Utils$.findLocalInetAddress(Utils.scala:891)
at org.apache.spark.util.Utils$.org$apache$spark$util$Utils$$localIpAddress$lzycompute(Utils.scala:884)
at org.apache.spark.util.Utils$.org$apache$spark$util$Utils$$localIpAddress(Utils.scala:884)
at org.apache.spark.util.Utils$$anonfun$localHostName$1.apply(Utils.scala:941)
at org.apache.spark.util.Utils$$anonfun$localHostName$1.apply(Utils.scala:941)
at scala.Option.getOrElse(Option.scala:121)
at org.apache.spark.util.Utils$.localHostName(Utils.scala:941)
at org.apache.spark.internal.config.package$.<init>(package.scala:204)
at org.apache.spark.internal.config.package$.<clinit>(package.scala)
... 10 more
SparkConf运行时配置:

def get_dataframe(query):
    ...
    sc = SparkCtx.get_sparkCtx()
    sql_context = SQLContext(sc)

    df = sql_context.read \
        .format("jdbc") \
        .option("driver", "com.amazon.redshift.jdbc42.Driver") \
        .option("url", os.getenv('JDBC_URL')) \
        .option("user", os.getenv('REDSHIFT_USER')) \
        .option("password", os.getenv('REDSHIFT_PASSWORD')) \
        .option("dbtable", "( " + query + " ) tmp ") \
        .load()

    return df
编辑2

在浏览器中,仅使用
spark env
配置并使用图像中的默认值运行会出现此错误

java.util.NoSuchElementException
at java.util.Collections$EmptyIterator.next(Collections.java:4189)
at org.apache.spark.util.kvstore.InMemoryStore$InMemoryIterator.next(InMemoryStore.java:281)
at org.apache.spark.status.AppStatusStore.applicationInfo(AppStatusStore.scala:38)
at org.apache.spark.ui.jobs.AllJobsPage.render(AllJobsPage.scala:273)
at org.apache.spark.ui.WebUI$$anonfun$2.apply(WebUI.scala:82)
at org.apache.spark.ui.WebUI$$anonfun$2.apply(WebUI.scala:82)
at org.apache.spark.ui.JettyUtils$$anon$3.doGet(JettyUtils.scala:90)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at org.spark_project.jetty.servlet.ServletHolder.handle(ServletHolder.java:848)
at org.spark_project.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:584)
at org.spark_project.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1180)
at org.spark_project.jetty.servlet.ServletHandler.doScope(ServletHandler.java:512)
at org.spark_project.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1112)
at org.spark_project.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at org.spark_project.jetty.server.handler.gzip.GzipHandler.handle(GzipHandler.java:493)
at org.spark_project.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:213)
at org.spark_project.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:134)
at org.spark_project.jetty.server.Server.handle(Server.java:534)
at org.spark_project.jetty.server.HttpChannel.handle(HttpChannel.java:320)
at org.spark_project.jetty.server.HttpConnection.onFillable(HttpConnection.java:251)
at org.spark_project.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:283)
at org.spark_project.jetty.io.FillInterest.fillable(FillInterest.java:108)
at org.spark_project.jetty.io.SelectChannelEndPoint$2.run(SelectChannelEndPoint.java:93)
at org.spark_project.jetty.util.thread.strategy.ExecuteProduceConsume.executeProduceConsume(ExecuteProduceConsume.java:303)
at org.spark_project.jetty.util.thread.strategy.ExecuteProduceConsume.produceConsume(ExecuteProduceConsume.java:148)
at org.spark_project.jetty.util.thread.strategy.ExecuteProduceConsume.run(ExecuteProduceConsume.java:136)
at org.spark_project.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:671)
at org.spark_project.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:589)
at java.lang.Thread.run(Thread.java:748)

转到AWS控制台,并在您的安全组配置下,允许所有到实例的入站流量


    • 解决方案是避免用户错误

      这是一个完全的面部手掌的情况,但我希望我对火花系统的误解可以帮助一些可怜的傻瓜,像我一样,他们花了太多时间在同一类型的问题上

      上一次迭代(
      gettyimages/docker spark
      docker image)的答案是,我试图在没有启动主映像或工作映像的情况下运行
      spark submit
      命令。 在
      gettyimages/docker spark
      repo中,您可以找到一个
      docker compose
      文件,该文件显示它在任何spark工作完成之前创建
      主节点
      工作者节点。image创建主进程或工作进程的方式是使用
      spark类
      脚本并分别传入
      org.apache.spark.deploy..

      因此,总而言之,我可以使用我正在使用的配置,但我必须先创建
      主程序
      工作程序
      ,然后执行
      spark submit
      命令,就像我已经做的一样

      这是一个快速而肮脏的实现,尽管我保证有更好的实现,由真正知道自己在做什么的人完成:

      前3个步骤发生在集群引导脚本中。我在AWS Lambda中执行此操作,由APIGateway触发

    • 创建集群和队列或某种消息代理系统,如zookeeper/kafka。(我正在为此使用API网关->lambda)
    • 选择主节点(lambda中的逻辑)
    • 创建一条包含一些基本信息的消息,如主服务器的IP或域,并从步骤1开始将其放入队列(发生在lambda中)
    • 下面的所有内容都发生在Spark节点上的启动脚本中

    • 在启动脚本中创建一个步骤,让节点在队列中检查步骤3中的消息
    • 使用步骤4中获取的消息中的信息,将
      SPARK_MASTER_HOST
      SPARK_LOCAL_IP
      添加到
      $SPARK_HOME/conf/SPARK env.sh
      文件中
    • 使用步骤4中获取的消息中的信息,将
      spark.driver.bindAddress
      添加到
      $spark\u HOME/conf/spark defaults.conf
      文件中
    • 在启动脚本中使用一些逻辑来确定“this”节点是主节点或工作节点
    • 启动主程序或工作程序。在
      gettyimages/docker spark
      图像中,您可以使用
      $spark\u HOME/bin/spark class org.apache.spark.deploy.master.master-h:7077启动主程序
    • 现在可以运行
      spark submit
      命令,该命令将工作部署到集群
    • 编辑:(一些代码供参考) 这是对lambda的补充

      def handler(event, context):
          config = BuildConfig(event)
          res = create_job(config)
          return build_response(res)
      
      编辑之后呢

      def handler(event, context):
          config = BuildConfig(event)
          coordination_queue = config.cluster + '-coordination'
      
          sqs = boto3.client('sqs')
          message_for_master_node = {'type': 'master', 'count': config.count}
          queue_urls = sqs.list_queues(QueueNamePrefix=coordination_queue)['QueueUrls']
      
          if not queue_urls:
              queue_url = sqs.create_queue(QueueName=coordination_queue)['QueueUrl']
          else:
              queue_url = queue_urls[0]
      
           sqs.send_message(QueueUrl=queue_url,
                       MessageBody=message_for_master_node)
      
          res = create_job(config)
          return build_response(res)
      
      然后我在启动时Spark集群中的节点运行的脚本中添加了一点:

      # addition to the "main" in the Spark node's startup script
      sqs = boto3.client('sqs')
      boot_info_message = sqs.receive_message(
          QueueUrl=os.getenv('COORDINATIN_QUEUE_URL'),
          MaxNumberOfMessages=1)['Messages'][0]
      boot_info = boot_info_message['Body']
      message_for_worker = {'type': 'worker', 'master': self_url}
      
      if boot_info['type'] == 'master':
          for i in range(int(boot_info['count'])):
              sqs.send_message(QueueUrl=os.getenv('COORDINATIN_QUEUE_URL'),
                               MessageBody=message_for_worker)
      sqs.delete_message(QueueUrl=os.getenv('COORDINATIN_QUEUE_URL'),
                         ReceiptHandle=boot_info_message['ReceiptHandle'])
      
      ...
      # starts a master or worker node
      startup_command = "org.apache.spark.deploy.{}.{}".format(
          boot_info['type'], boot_info['type'].title())
      subprocess.call(startup_command)
      

      谢谢你的回复。安全组是开放的,所以这不是问题所在。子网、NACL、路由、NAT网关和IGW都已连接并等待Spark运行,但我仍在SparkConfiguration中错误地配置它。自从第一次编辑以来,我已经将Spark和Hadoop的版本升级到了2.3和2.8,并且仍在努力让它在本地运行。第一次和第二次编辑中的错误来自我的本地
      docker run….
      命令
      # addition to the "main" in the Spark node's startup script
      sqs = boto3.client('sqs')
      boot_info_message = sqs.receive_message(
          QueueUrl=os.getenv('COORDINATIN_QUEUE_URL'),
          MaxNumberOfMessages=1)['Messages'][0]
      boot_info = boot_info_message['Body']
      message_for_worker = {'type': 'worker', 'master': self_url}
      
      if boot_info['type'] == 'master':
          for i in range(int(boot_info['count'])):
              sqs.send_message(QueueUrl=os.getenv('COORDINATIN_QUEUE_URL'),
                               MessageBody=message_for_worker)
      sqs.delete_message(QueueUrl=os.getenv('COORDINATIN_QUEUE_URL'),
                         ReceiptHandle=boot_info_message['ReceiptHandle'])
      
      ...
      # starts a master or worker node
      startup_command = "org.apache.spark.deploy.{}.{}".format(
          boot_info['type'], boot_info['type'].title())
      subprocess.call(startup_command)