本文作者: 林武康(花名:知瑕),阿里巴巴计算平台事业部技术专家,Apache HUE Contributor, 参与了多个开源项目的研发工作,对于分布式系统设计应用有较丰富的经验,目前主要专注于EMR数据开发相关的产品的研发工作。
本文介绍Spark Operator的设计和实现相关的内容.
Spark运行时架构
经过近几年的高速发展,分布式计算框架的架构逐渐趋同. 资源管理模块作为其中最通用的模块逐渐与框架解耦,独立成通用的组件.目前大部分分布式计算框架都支持接入多款不同的资源管理器. 资源管理器负责集群资源的管理和调度,为计算任务分配资源容器并保证资源隔离.Apache Spark作为通用分布式计算平台,目前同时支持多款资源管理器,包括:
YARN
Mesos
Kubernetes(K8s)
Spark Standalone(自带的资源管理器)
Apache Spark的运行时框架如下图所示, 其与各类资源调度器的交互流程比较类似.
图1 Spark运行时框架(Client模式)
其中,Driver负责作业逻辑的调度和任务的监控, 资源管理器负责资源分配和监控.Driver根据部署模式的不同,启动和运行的物理位置有所不同. 其中,Client模式下,Driver模块运行在Spark-Submit进程中, Cluster模式下,Driver的启动过程和Executor类似,运行在资源调度器分配的资源容器内.
K8s是Spark在2.3开始支持资源管理器,而相关讨论早在2016年就已经开始展开(https://issues.apache.org/jira/browse/SPARK-18278). Spark对K8s的支持随着版本的迭代也逐步深入, 在即将发布的3.0中,Spark on K8s提供了更好的Kerberos支持和资源动态支持的特性.
Spark on K8s
Kubernetes是由Google开源的一款面向应用的容器集群部署和管理系统,近年来发展十分迅猛,相关生态已经日趋完善. 在Spark官方接入K8s前,社区通常通过在K8s集群上部署一个Spark Standalone集群的方式来实现在K8s集群上运行Spark任务的目的.方案架构如下图所示:
图2 Spark Standalone on K8s
这个模式简单易用,但存在相当大的缺陷:
无法按需扩展, Spark Standalone部署后集群规模固定,无法根据作业需求自动扩展集群;
无法利用K8s原生能力, Spark Standalone内建的资源调度器不支持扩展,难以接入K8s调度,无法利用K8s提供的云原生特性;
Spark Standalone集群在多租户资源隔离上天生存在短板;
为此,Spark社区进行了深入而广泛的讨论,在2.3版本提供了对K8s的官方支持.Spark接入K8s的好处是十分明显的:
直接和K8s对接,可以更加高效和快捷的获取集群资源;
利用K8s原生能力(如namespace等)可以更好的实现资源隔离和管控.
Spark on K8s方案架构如下图所示, 设计细节可以参考:SPARK-18278
https://issues.apache.org/jira/browse/SPARK-18278?spm=a2c6h.12873639.0.0.4c2a21c4pIXnNk
图3 Spark on K8s (Native)
在这个方案中,
Spark-Submit通过调用K8s API在K8s集群中启动一个Spark Driver Pod;
Driver通过调用K8s API启动相应的Executor Pod, 组成一个Spark Application集群,并指派作业任务到这些Executor中执行;
作业结束后,Executor Pod会被销毁, 而Driver Pod会持久化相关日志,并保持在'completed'状态,直到用户手清理或被K8s集群的垃圾回收机制回收.
当前的方案已经解决了Spark Standalone on K8s方案的部分缺陷,然而,Spark Application的生命周期管理方式和调度方式与K8s内置的工作负载(如Deployments、DaemonSets、StatefulSets等)存在较大差异,在K8s上执行作业仍然存在不少问题:
Spark-submit在K8s集群之外,使用非声明式的提交接口;
Spark Application之间没有协同调度,在小集群中很容易出现调度饿死的情况;
需要手动配置网络,来访问WebUI;
任务监控比较麻烦,没有接入Prometheus集群监控;
当然Spark on K8s方案目前还在快速开发中,更多特性不久会发布出来,相信未来和K8s的集成会更加紧密和Native, 这些特性包括:
动态资源分配和外部Shullfe服务
本地文件依赖管理器
Spark Application管理器
作业队列和资源管理器
Spark Operator浅析
在分析Spark Operator的实现之前, 先简单梳理下Kubernetes Operator的基本概念. Kubernetes Operator是由CoreOS开发的Kubernetes扩展特性, 目标是通过定义一系列CRD(自定义资源)和实现控制器,将特定领域的应用程序运维技术和知识(如部署方法、监控、故障恢复等)通过代码的方式固化下来. Spark Operator是Google基于Operator模式开发的一款的工具(https://github.com/GoogleClou