【摘要】 external-shuffle-service是Spark里面一个重要的特性,有了它后,executor可以在不同的stage阶段动态改变数量,大大提升集群资源利用率。但是这个特性当前在k8s上并不能很好的运行。让我们来看看,在k8s上要实现这个external-shuffle-service特性的最新进展吧。

如果你想在kubernetes集群中运行Spark任务,那么你可能会对:如何在k8s上运行external-shuffle-service感兴趣。把Driver和Executor都当做容器,丢到k8s上(k8s集群则把他们当做一般的容器,和其他业务类app一样对待),这种模式,可以使得集群资源池归一,避免Spark一个资源池,业务类(K8S)集群一个资源池。提升整体资源利用率,统一维护也降低运维成本。这也是Spark官方在2.3版本后为什么要支持Spark-on-k8s的主要驱动力。

1      external-shuffle-service作用

如果想要executor数量可以动态变化,就需要依赖external-shuffle-service功能(注意这句话,因为在k8s集群中,容器启动关闭很方便。所以非常希望executor数量可以动态调整,提升资源利用率)。

原因是在shuffle过程中,一个executor会到另一个executor那里取数据。如果一个executor节点挂掉了,那么它也就无法处理其他executor发过来的 shuffle 的数据读取请求了,它之前生成的数据都没有意义了。为了解决“取shuffle数据”,和“目标executor是否运行”分开。Spark引入了external-shuffle-service服务。相当于先把shuffle数据暂存到external-shuffle-service那里,然后大家去external-shuffle-service那里取就行了(有点像个中介)。

好文参考:https://zhmin.github.io/2019/08/05/spark-external-shuffle-service/

2      原来怎么部署

在原Spark框架中,external-shuffle-service是部署在每个节点上的。

(1)executor 告诉 external-shuffle-service 数据存放在哪里,然后(2) external-shuffle-service 记下来,供别人查询。所以问题的关键是,数据放“哪里”支持哪些格式呢。我们看(1)里面通知是结构是长这样:

public class RegisterExecutor extends BlockTransferMessage {
public final String appId; // spark application id
public final String execId; // executor id
public final ExecutorShuffleInfo executorInfo; // 《==文件路径
}

可以看出来,关键在 “在哪里” 要看(2)长什么样:

public class ExecutorShuffleInfo implements Encodable {

     public final String[] localDirs;         // 《== 第一级目录列表
public final int subDirsPerLocalDir; // 第二级目录列表
public final String shuffleManager; // shuffleManager的类型,目前只有一种类型 SortShuffleManager
}

可以看到,这个shuffle数据 “在哪里” 只能支持HostPath(本地路径)。

问题的关键就来了:executor容器跑在k8s节点上面,external-shuffle-service跑在另一个容器里面。要想共享相同Path文件,那就必须使用节点路径(k8s-hostpath)。要用这个Hostpath 还得拥有节点的所有权,这个对于多用户共享的K8s集群来说,权限不安全,数据未隔离。

3      在k8s上要怎么解决(一)

Spark的external-shuffle-service要怎么在k8s上运行,这是个问题。Spark社区关于这个有个讨论:https://docs.google.com/document/d/1uCkzGGVG17oGC6BJ75TpzLAZNorvrAU3FRd2X-rVHSM/edit#heading=h.btqugnmt2h40

这个文档主要是说:

当前external-shuffle-service的实现有缺点:(1)多个Spark应用共用一个external-shuffle-service,如果external-shuffle-service出问题,多个Spark应用都受影响,即隔离性差。(2)一个节点一个external-shuffle-service,导致不同节点间压力不均衡。同时如果节点挂了,external-shuffle-service也就没了,这个节点上面的所有executor都受影响,可靠性差。(3)在当前较火热的Docker容器环境下,executor写入的shuffle数据(在一个容器内)。不一定就能被external-shuffle-service读取到(在另一个容器内)。因为有些k8s集群中,管理员出于安全考虑,会强制隔离不同用户的容器,禁止任何共享。

所以提出了改进方向:即executor保存shuffle数据时,不限定非得是保存在本地Path中。

具体实现方案可以有多种。

(1)       保存shuffle数据时,通过external-shuffle-service上传的方式。

(2)       external-shuffle-service支持shuffle数据为远端uri地址,而不仅仅是主机路径。

(3)       由Driver来维护所有的shuffle数据信息,取消external-shuffle-service组件。

(4)       将shuffle数据保存到分布式存储中。

(5)       将shuffle数据上传到external-shuffle-service,然后由Driver跟踪文件路径。

总体思路就是:以前external-shuffle-service是本地写,远程读。调整为:远程写,远程读。

4      在k8s上要怎么解决(二)

其实要在k8s上实现executor数量动态调整(dynamic resource allocation),还有另一条小路(即不通过external-shuffle-service的方式)。并且这条路已经实现了,在这个PR里面。https://github.com/apache/spark/pull/24817

Ø  实现原理:

当发现executor里面是shuffle数据没有用了,则可以删除该executor。如果这个executor里面的shuffle数据,还会被其他Jop读取,那么就保持这个executor存活着不被删除。从而实现executor数量可以动态调整。

Ø  缺点:

可以看出来,这种方式其实是一种缓兵之计。(1)删除部分暂时不被使用executor,但是必须保留那些还会被使用的executor。所以动态效果并不是最优的。另外,(2)一个executor也许最近不被使用,被删除了。但是后续其他Stage又有可能去访问那个shuffle数据。结果发现找不到(被动态删除嘛),这个时候又得重新计算,浪费性能。

PR里面的讨论也说了,这个是无法用来完整替代external-shuffle-service的。

5      路标计划

通过上面的分析,基本了解了在k8s上面跑external-shuffle-service的困难和思路。

所以要达到目的的路径为:(1)external-shuffle-service支持远端保存shuffle数据。(2)executor和external-shuffle-service共享云端shuffle数据。(3)executor数量可以动态调整,不影响功能。(4)在k8s上支持了executor数量动态调整(dynamic resource allocation)。

看Spark的规划是在 3.0.0 版本提供完整能力,嗯,让我们期待Spark on K8s越来越溜吧。

https://issues.apache.org/jira/browse/SPARK-24432

作者:tsjsdbd

快速理解spark-on-k8s中的external-shuffle-service的更多相关文章

  1. 降本增效利器!趣头条Spark Remote Shuffle Service最佳实践

    王振华,趣头条大数据总监,趣头条大数据负责人 曹佳清,趣头条大数据离线团队高级研发工程师,曾就职于饿了么大数据INF团队负责存储层和计算层组件研发,目前负责趣头条大数据计算层组件Spark的建设 范振 ...

  2. Spark机器学习 Day2 快速理解机器学习

    Spark机器学习 Day2 快速理解机器学习 有两个问题: 机器学习到底是什么. 大数据机器学习到底是什么. 机器学习到底是什么 人正常思维的过程是根据历史经验得出一定的规律,然后在当前情况下根据这 ...

  3. 理解Spark RDD中的aggregate函数(转)

    针对Spark的RDD,API中有一个aggregate函数,本人理解起来费了很大劲,明白之后,mark一下,供以后参考. 首先,Spark文档中aggregate函数定义如下 def aggrega ...

  4. 快速理解Python中使用百分号占位符的字符串格式化方法中%s和%r的输出内容的区别

    <Python中使用百分号占位符的字符串格式化方法中%s和%r的输出内容有何不同?>老猿介绍了二者的区别,为了快速理解,老猿在此使用另外一种方式补充说明一下: 1.使用%r是调用objec ...

  5. 在 K8S 中快速部署 Redis Cluster & Redisinsight

    Redis Cluster 部署 使用 Bitnami helm chart 在 K8S redis 命名空间中一键部署 Redis cluster . helm repo add bitnami h ...

  6. k8s中几个基本概念的理解,pod,service,deployment,ingress的使用场景

    k8s 总体概览 前言 Pod 副本控制器(Replication Controller,RC) 副本集(Replica Set,RS) 部署(Deployment) 服务(Service) ingr ...

  7. 深入理解k8s中的访问控制(认证、鉴权、审计)流程

    Kubernetes自身并没有用户管理能力,无法像操作Pod一样,通过API的方式创建/删除一个用户实例,也无法在etcd中找到用户对应的存储对象. 在Kubernetes的访问控制流程中,用户模型是 ...

  8. 《深入理解Spark:核心思想与源码分析》(前言及第1章)

    自己牺牲了7个月的周末和下班空闲时间,通过研究Spark源码和原理,总结整理的<深入理解Spark:核心思想与源码分析>一书现在已经正式出版上市,目前亚马逊.京东.当当.天猫等网站均有销售 ...

  9. 《深入理解Spark:核心思想与源码分析》(第2章)

    <深入理解Spark:核心思想与源码分析>一书前言的内容请看链接<深入理解SPARK:核心思想与源码分析>一书正式出版上市 <深入理解Spark:核心思想与源码分析> ...

随机推荐

  1. 参观路线——并查集+dfs

    题目描述 Lambdaland由N个城市组成,任两个城市间都有一条道路相连.  下个月TBL准备参观Lambdaland.他将从城市1开始,以深度优先搜索顺序参观能所有遍历到的城市. 由于TBL是一位 ...

  2. 转:java 看好的一些书

    地址 :  http://www.cnblogs.com/xrq730/p/4994545.html

  3. vue实现tab选项卡切换效果

    tab选项卡切换效果: 通过点击事件传入参数,然后通过v-show来进行切换显示 <template> <div class="box"> <div ...

  4. PTA刷题记录(3)

    团队天梯赛-------(3)分值:15 给定一个 k 位整数 N=d​k−1​​10​k−1​​+⋯+d​1​​10​1​​+d​0​​ (0≤d​i​​≤9, i=0,⋯,k−1, d​k−1​​ ...

  5. 模拟实现IoC容器

    Spring的IoC核心就是控制反转,将对实现对象的操作控制器交出来,由IoC容器来管理,从配置文件中获取配置信息,Java对XML文档提供了完美的支持,dom4j功能强大,而下面我就用JDOM这一开 ...

  6. java多线程与线程并发一:线程基础回顾

    本文章内容整理自:张孝祥_Java多线程与并发库高级应用视频教程 线程简单来讲就是程序正在做的事情.多线程即一个程序同时做多件事情,一个线程就是一件事情. 在java中创建线程的方法有两种. 方法一是 ...

  7. 015.Kubernetes二进制部署所有节点kubelet

    一 部署 kubelet kubelet 运行在每个 worker 节点上,接收 kube-apiserver 发送的请求,管理 Pod 容器,执行交互式命令,如 exec.run.logs 等. k ...

  8. [TCP/IP] 学习TCP/IP协议的笔记

    1.我看的视频是https://www.bilibili.com/video/av10610680?from=search&seid=1733008388243131444这位大大的视频讲解. ...

  9. nyoj 21-三个水杯(BFS)

    21-三个水杯 内存限制:64MB 时间限制:1000ms Special Judge: No accepted:7 submit:18 题目描述: 给出三个水杯,大小不一,并且只有最大的水杯的水是装 ...

  10. python:爬虫2——隐藏自己

    一.添加浏览器 方法一: head['User-Agent'] = 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, li ...