耗时很长时间解决了一个spark in docker的问题,记录一下。
为霸州等地区用户提供了全套网页设计制作服务,及霸州网站建设行业解决方案。主营业务为网站建设、成都网站建设、霸州网站设计,以传统方式定制建设网站,并提供域名空间备案等一条龙服务,秉承以专业、用心的态度为用户提供真诚的服务。我们深信只要达到每一位用户的要求,就会得到认可,从而选择与我们长期合作。这样,我们也可以走得更远!这是个非常奇怪的问题,找遍谷歌都找不到答案,与其说是分析出来倒不如说是偶然发现。
先介绍一下架构和环境。
Z机器是docker的宿主机,在每个docker里面都跑了一个Zeppelin用作数据分析,之所以这样弄,是客户要求每个人的环境都必须是独立的。
Zdocker假设是Z上面跑着zeppelin的运行的一个docker镜像。
Zdocker使用默认的bridge方式连接到外部集群
Hadoop集群按照加入集群的先后顺序分为两部分进行观察。A为先加入集群的机器有31台,B为后加入集群的机器15台。
Spark使用client方式提交,用YARN做资源管理。
表象:
Zdocker里面通过Zeppelin页面提交的Spark计算任务一直都是正常的,直到B的15台加入到集群里
B的15台配置从操作系统到网络到JVM到hadoop全部一模一样,没有区别。
B加入后,所有从Zdocker里面提交的Spark任务全部不能跑,executor在15台机器执行时会报 NoRouteToHost gateway: 7337
B加入后,所有在Zdocker外面提交的Spark任务全部正常。
B加入后,所有executor不运行在B机器上的全部正常
B加入后,Zdocker内外所有MapReduce任务正常。
在YARN里去掉B的15台机器,一切正常。
分析:
7337为spark的yarn shuffle端口
第一阶段
既然是NoRouteToHost,第一反应是DNS问题,检查所有DNS和hosts文件,没有发现问题,检查iptables,route表,全部无问题,解决失败。
第二阶段
怀疑是spark bug,我想知道 gateway 是从哪冒出来的,翻阅了spark里面报错相关的scala和java代码,没有找到这个跟gateway相关的东西。
第三阶段
因为B加入前是正常的,B加入后就不正常了,检查docker里面的DNS和hosts,全部正常,继续失败。
第四阶段
怀疑环境变量不同,检查所有A,B机器配置,环境变量完全一样。
因为是yarn shuffle,怀疑spark-assembly问题,检查后发现无问题。
第五阶段
尝试暴力解决,将gateway加入DNS解析,强行指到B集群的一台机器上。也就是所有的spark 外部shuffle会指向到一台机器的 7337端口。好,跑了一天没问题,第二天就有问题了,那台被强行指定的机器报找不到作业在本地shuffle的index文件。
第六阶段
尝试在docker里面发现问题,看了一下docker的路由表,发现172.17.42.1是docker的网关,抱着死马心态在docker里面ping了一下gateway主机名,发现通的。于是裆下一紧,感觉有门可入。
docker内部默认的网关是172.17.42.1,然后默认还给了个hostname叫gateway,或许这就是了。
于是跑到A找了一台机器ping gateway主机名,ping卡死,因为无论DNS还是hosts,在任何hadoop的节点都是没有解析过gateway这个主机名的。然后到B找了一台机器ping,直接退出报 ping: unknown host gateway。
于是开始琢磨,两个机器网络环境不同,或许这就是问题点了。
A的几十台机器,因为安全需要,没有开放任何外网访问。所以在A的机器上ping gateway时,根本连域名都解析不了,所以会卡死。而B的十几台机器因为是新加的,运维忘了关闭外网访问,所以能找到公网的域名解析服务器,但是公网解析不了gateway域名,于是直接返回 unknown host 并退出。
让运维关闭B机器的公网访问,再从Zdocker上面提交作业,一切正常。
原因:
解决了问题再回来分析一下应该是因为zeppelin从docker里面提交spark作业,spark是client方式跑,driver是跑在docker里面的,driver在向docker外的yarn申请资源分配executor的时候,在哪里带上了gateway这个主机名作为环境变量传递给了executor的container。如果没有外网访问,executor会使用本机的 7337作为yarn shuffle的端口,而有了外网访问,executor会去查询gateway的ip,但是DNS返回错误,于是就会造成executor执行错误。这也很好的解释了为什么docker外面的spark作业无论B是否启动都不会报错正常执行。
所以这他妈其实是一个很低端的错误,只是谁都不会想到,spark执行的失败还能跟是否访问公网有关。就跟上次解决MR速度慢一样,谁能想到网卡能他妈自己跳成10Mbps啊。
后续还需要继续研究docker的网络机制和spark的driver和executor之间的传参机制,才能彻底干掉这个问题。
另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。