Apache spark Fargate can上的火花';找不到本地IP
我有一个构建工作,我正试图在一个由1个节点组成的AWS Fargate集群中进行设置。当我试图运行Spark来构建数据时,我得到了一个错误,似乎是因为Java无法找到“localHost” 我通过运行一个脚本来设置配置,该脚本添加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主机
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
-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)