Spark权威指南(中文版)----第17章 部署Spark应用程序

本章探讨了您和您的团队运行Spark应用程序所需的基础设施:

  • 集群部署的选项
  • Spark的不同集群管理器
  • 部署考虑事项和配置部署

在大多数情况下,Spark应该与所有受支持的集群管理器配合工作; 然而,自定义设置意味着需要理解每个集群管理系统的复杂性。最难的部分是如何选择集群管理器。尽管我们很乐意包含关于如何使用不同的集群管理器配置不同集群的详细信息,但是本书不可能为每种环境中的每种情况提供超特定的详细信息。因此,本章的目标不是详细讨论每个集群管理器,而是研究它们之间的基本差异,并为Spark网站上已有的大量资料提供参考。不幸的是,“哪个集群管理器最容易运行”这个问题没有简单的答案,因为它会随着用例、经验和资源的不同而变化。Spark官方文档(http://spark.apache.org/docs/latest/cluster-overview.html)提供了许多关于使用可操作示例部署Spark的详细信息。我们尽力讨论最相关的问题。

在撰写本文时,Spark有三个官方支持的集群管理器:

  • Standalone mode
  • Hadoop YARN
  • Apache Mesos

这些集群管理器维护一组机器,您可以将Spark应用程序部署到这些机器上。当然,每个集群管理器对管理都有自己的观点,因此您需要记住一些权衡和语义。但是,它们都以相同的方式运行Spark应用程序(如第16章所述)。让我们从第一点开始:在哪里部署集群。

17.1.   在哪里部署集群来运行Spark应用程序

在何处部署Spark集群有两个选项:部署在本地集群或公共云中。这两个选择都是有适用场景的,因此值得讨论。

17.1.1.   本地集群部署

将Spark部署到本地集群有时是一个合理的选择,特别是对于已经管理自己的数据中心的组织。与其他所有事情一样,这种方法也需要权衡。本地集群使您能够完全控制所使用的硬件,这意味着您可以为特定的工作负载优化性能。然而,它也带来了一些挑战,尤其是涉及到像Spark这样的数据分析工作负载时。首先,使用本地部署,集群的大小是固定的,而数据分析工作负载的资源需求通常是弹性的。如果集群太小,就很难偶尔启动非常大的分析查询或为新机器学习模型训练工作,而如果集群太大,就会有闲置的资源。其次,对于本地集群,您需要选择并操作自己的存储系统,比如Hadoop文件系统或可伸缩键值存储。这包括在必要时设置应用程序和灾难恢复。

如果要在本地部署,解决资源利用率问题的最佳方法是使用集群管理器,它允许您运行许多Spark应用程序,并在它们之间动态地重新分配资源,甚至允许在同一集群上运行非Spark应用程序。Spark支持的所有集群管理器都允许多个并发应用程序,但是yarn和Mesos更好地支持动态共享,而且还支持非Spark工作负载。处理资源共享可能是您的用户每天在Spark本地集群部署和在公共云中部署看到的最大差异:在公共云中,很容易为每个应用程序提供其自己的集群,集群的大小正好满足该任务的持续时间。

对于存储,您有几个不同的选项,但是深入讨论所有的权衡和操作细节可能需要特定的书籍。用于Spark的大多数常见存储系统是分布式文件系统(如Hadoop的HDFS)和键值存储(如Apache Cassandra)。流消息总线系统(如Apache Kafka)也经常用于获取数据。所有这些系统都有不同程度的管理、备份支持,有时内置在系统中,有时仅通过第三方商业工具。在选择存储选项之前,我们建议评估其Spark连接器的性能并评估可用的管理工具。

17.1.2.   公共云中部署

虽然早期的大数据系统是为现场部署而设计的,但云现在是部署Spark的一个越来越常见的平台。在大数据工作负载方面,公共云有几个优势。首先,可以弹性地启动和关闭资源,这样您就可以运行偶尔出现的“怪物”任务,这需要数百台机器花费几个小时,而不必一直为它们付费。即使对于正常的操作,您也可以为每个应用程序选择不同类型的机器和集群大小,以优化其成本性能——例如,为您的深度学习工作启动具有图形处理单元(gpu)的机器。其次,公共云包括低成本、地理位置复杂的存储,这使得管理大量数据变得更容易。

许多希望迁移到云的公司设想他们将以与运行本地集群相同的方式运行应用程序。所有主要的云提供商(Amazon Web Services [AWS]、Microsoft Azure、谷歌云平台[GCP]和IBM Bluemix)都为它们的客户提供托管Hadoop集群,这些集群为存储和Apache Spark提供HDFS。然而,这实际上不是在云中运行Spark的好方法,因为使用固定大小的集群和文件系统,您将无法利用灵活性。相反,使用与特定集群(如Amazon S3、Azure Blob存储或谷歌云存储)解耦的全局存储系统,并为每个Spark工作负载动态地启动机器,通常是一个更好的主意。使用解耦的计算和存储,您将能够只在需要的时候为计算资源付费,动态地扩展它们,并混合不同的硬件类型。基本上,记住,Spark在云中运行并不意味着一个本地安装迁移到虚拟机:本机可以基于云存储运行Spark,以充分利用云的弹性,节约成本效益和管理工具,而无需管理内部计算堆栈在您的云环境。

有几家公司提供“原生云”的基于Spark的服务,Apache Spark的所有安装当然都可以连接到云存储。由加州大学伯克利分校Spark团队创建的Databricks公司就是专门为Spark构建的云服务提供商的一个例子。

如果您在公共云中运行Spark,本章中的大部分内容可能都不相关,因为您常常可以为您执行的每个作业创建一个单独的、短暂的Spark集群。在这种情况下,独立集群管理器可能是最容易使用的。但是,如果您希望在许多应用程序之间共享更长寿的集群,或者自己在虚拟机上安装Spark,那么您可能仍然希望阅读本文。

    17.2.  集群管理器

 

除非使用高级集群管理服务,否则必须决定使用集群管理器来处理Spark。Spark支持前面提到的三个集群管理器:独立集群、Hadoop yarn和Mesos。我们来复习一下。

17.2.1.   Standalone模式

Spark的Standalone集群管理器是专门为Apache Spark工作负载构建的轻量级平台。使用它,您可以在同一个集群上运行多个Spark应用程序。它还提供了简单的接口,但可以扩展到大型Spark工作负载。Standalone模式的主要缺点是,与其他集群管理器相比,使用范围有限——尤其是,您的集群只能运行Spark。但是,如果您只是想快速在集群上运行Spark,而没有使用Yarn或Mesos的经验,那么这可能是最好的起点。

17.2.1.1.启动Standalone集群

启动Standalone集群需要先准备机器。这意味着启动它们,确保它们可以通过网络彼此通信,并获得您希望在这些机器上运行的Spark版本。之后,有两种方法启动集群:手工启动或使用内置启动脚本。

让我们首先手工启动一个集群。第一步是在我们想要运行的机器上启动master进程,使用以下命令:

$SPARK_HOME/sbin/start-master.sh

 

当我们运行这个命令时,集群管理器master进程将在该机器上启动。一旦启动,master服务器将输出一个spark://HOST:PORT URI。在启动集群的每个worker节点时可以使用它,并且可以在应用程序初始化时将它用作SparkSession的master参数值。您还可以在master web UI上找到这个URI,web UI默认访问地址下是http://master-ip-address:8080。使用该URI,通过登录到每台机器并使用刚刚从master节点接收到的URI运行以下脚本来启动worker节点。master机器必须在您正在使用的worker节点的网络上可用,并且master节点上的端口也必须打开:

$SPARK_HOME/sbin/start-slave.sh <master-spark-URI>

一旦您在另一台机器上运行了它,您就有了一个正在运行的Spark集群!这个过程自然有点手工;幸运的是,有一些脚本可以帮助自动化这个过程。

17.2.1.2.集群启动脚本

您可以配置可以自动启动Standalone集群的集群启动脚本。为此,在您的Spark目录中创建一个名为conf/slave的文件,该文件将包含您打算启动Spark workers的所有机器的主机名,每行一个。如果该文件不存在,则一切将以local方式启动。当您实际启动集群时,master计算机将通过SSH访问每个worker计算机。默认情况下,SSH是并行运行的,需要您配置无密码访问(使用私钥)。如果没有无密码设置,可以设置环境变量SPARK_SSH_FOREGROUND,并连续地为每个worker提供密码。在您设置好这个文件之后,您可以使用以下shell脚本启动或停止您的集群,这些脚本基于Hadoop的部署脚本,可以在$SPARK_HOME/sbin中找到:

$SPARK_HOME/sbin/start-master.sh在执行脚本所在机器上启动一个master实例。$SPARK_HOME/sbin/start-slaves.sh在conf/slaves文件中指定的每台机器上启动slave实例。$SPARK_HOME/sbin/start-slave.sh在执行脚本所在机器上启动slave实例。$SPARK_HOME/sbin/start-all.sh如前所述,启动一个master和一些slave.$SPARK_HOME/sbin/stop-master.sh停止通过bin/start-master.sh脚本启动的master程序。$SPARK_HOME/sbin/stop-slaves.sh停止conf/slaves文件中指定的机器上的所有slave实例.$SPARK_HOME/sbin/stop-all.sh如前所述,同时停止master进程和slave进程。
17.2.1.3.Standalone的集群配置

Standalone集群有许多配置,您可以使用它们来调优应用程序。这些配置控制着,从终止应用程序时的每个worker上的旧文件处理,到worker的core和内存资源配置的所有内容。这些通过环境变量或应用程序属性来控制。由于空间限制,我们不能在这里包含整个配置集。请参考Spark官方文档中关于Standalone环境变量的相关配置表(http://spark.apache.org/docs/latest/spark-standalone.html#cluster-launch-scripts)。

17.2.1.4.提交应用程序

创建集群之后,可以使用master服务器的spark:// URI向集群提交应用程序。您可以在master节点本身或另一台机器上,使用spark-submit执行此操作。standalone模式有一些特定的命令行参数,我们在“启动应用程序”中介绍过。

17.2.2.   Spark On Yarn

HadoopYarn 是一个用于作业调度和集群资源管理的框架。尽管Spark经常被归类为“Hadoop生态系统”的一部分,但实际上,Spark与Hadoop几乎没有什么关系。Spark本身支持Hadoop Yarn集群管理器,但它不需要Hadoop本身的任何东西。

您可以在Spark -submit命令行参数中将master指定为yarn,从而在Hadoop yarn上运行Spark作业。就像standalone模式一样,有许多配置可以根据您希望集群做的事情进行调优。配置的数量自然比Spark的standalone模式多,因为Hadoop yarn是针对大量不同执行框架的通用调度程序。

建立yarn集群超出了本书的范围,但是有一些关于这个主题的好书(http://shop.oreilly.com/product/0636920033448.do)以及可以简化这种体验的托管服务。

17.2.2.1.提交应用程序

当向yarn提交应用程序时,与其他部署方式的核心区别在于——master将设置为yarn,而不是处于standalone模式时的master节点IP。相反,Spark将使用环境变量hadoop_con_dir或yarn_con_dir查找yarn配置文件。一旦将这些环境变量设置为Hadoop安装的配置目录,就可以运行spark-submit,就像我们在第16章中看到的那样。

注意有两种部署模式可以用于在yarn上启动Spark。正如前面几章所讨论的,集群模式将spark driver程序作为yarn集群管理的进程,客户端可以在创建应用程序后退出。在客户端client模式下,driver程序将在客户端进程中运行,因此yarn只负责将executor资源授予应用程序,而不负责维护master节点。同样值得注意的是,在集群cluster模式下,Spark不一定运行在执行它的同一台机器上。因此,库和外部jar必须手工分发,或者通过--jars命令行参数分发。

您可以使用spark-submit设置一些特定于yarn的属性。这些允许您控制优先级队列和诸如keytabs之类的安全性。我们在第16章“启动应用程序”中讨论了这些。

17.2.2.2.Spark on yarn的应用配置

将Spark部署为yarn应用程序需要了解各种不同的配置及其对Spark应用程序的影响。本节将介绍基本配置的一些最佳实践,并包含对运行Spark应用程序的一些重要配置的指南。

Hadoop配置

如果您计划使用Spark从HDFS读写,您需要在Spark的类路径上包括两个Hadoop配置文件:hdfs-site.xml--为HDFS客户端提供默认行为;和core-sitexml,它设置默认的文件系统名称。这些配置文件的位置在不同Hadoop版本中各不相同,但是一个常见的位置位于/etc/hadoop/conf中。一些工具还动态创建这些配置,因此了解托管服务如何部署这些配置也很重要。

要使这些文件对Spark可见,请将$SPARK_HOME/spark-env.sh中的HADOOP_CONF_DIR设置为包含配置文件的位置,或者在Spark-submit提交应用程序时配置为环境变量参数。

17.2.2.3.Yarn模式下的应用程序属性

有许多与hadoop相关的配置很大程度上与Spark无关,只是以影响Spark运行的方式运行yarn。由于空间限制,我们不能在这里包含配置集。请参阅Spark文档(http://spark.apache.org/docs/latest/running-on-yarn.html#configuration)中有关yarn配置的相关表格。

17.2.4.   Spark on  Mesos

Apache Mesos是Spark可以运行的另一个集群管理系统。关于Mesos的一个有趣的事实是,这个项目也是由Spark的许多原始作者发起的,包括本书的一位作者。用Mesos项目自己的话来说:

Apache Mesos将CPU、内存、存储和其他计算资源从机器(物理的或虚拟的)中抽象出来,从而能够轻松地构建和有效地运行容错和弹性分布式系统。

在大多数情况下,Mesos打算成为一个数据中心规模的集群管理器,它不仅管理像Spark这样的短期应用程序,还管理像web应用程序或其他资源接口这样的长时间运行的应用程序。Mesos是最重量级的集群管理器,原因很简单,只有当您的组织已经大规模部署了Mesos时,您才可能选择这个集群管理器,但是它仍然是一个很好的集群管理器。

Mesos是一个很大的基础设施,不幸的是,对于我们来说,关于如何部署和维护Mesos集群的信息实在太多了。关于这个主题有很多很棒的书,包括Dipa Dubhashi和Akhil Das的Mastering Mesos (O 'Reilly, 2016)。这里的目标是提出在Mesos上运行Spark应用程序时需要考虑的一些事项。

例如,您可能看到过,Mesos上Spark的一个常见特性是细粒度模式与粗粒度模式。从历史上看,Mesos支持各种不同的模式(细粒度和粗粒度),但是目前版本,它只支持粗粒度调度(细粒度已被弃用)。粗粒度模式意味着每个Spark executor作为一个Mesos任务运行。Spark executor的大小取决于以下应用程序属性:

  • spark.executor.memory

  • spark.executor.cores

  • spark.cores.max/spark.executor.cores

17.2.3.1.提交应用程序

向Mesos集群提交应用程序类似于为Spark的其他集群管理器提交应用程序。在大多数情况下,在使用Mesos时应该用集群模式提交应用程序。客户端模式需要您进行一些额外的配置,特别是在分配集群资源方面。

例如,在客户端模式下,dirver程序需要spark-env.sh中的额外配置信息来兼容Mesos。

在spark-env.sh中设置一些环境变量:

exportMESOS_NATIVE_JAVA_LIBRARY=<path to libmesos.so>

该路径通常<prefix>/lib/libmesos。默认前缀是/usr/local。在Mac OS X上,这个库名为libmesos.dylib而不是libmesos.so:

export SPARK_EXECUTOR_URI=<URLof spark-2.2.0.tar.gz uploaded above>

最后,设置Spark应用程序属性Spark.executor.uri为< spark-2.2.0.tar.gz>的URL。现在,当在集群上启动Spark应用程序时,在创建SparkContex时传递一个mesos:// URL作为master,并在您的SparkConf变量中设置该属性作为参数,或者初始化SparkSession:

// in Scalaimport org.apache.spark.sql.SparkSessionval spark = SparkSession.builder  .master("mesos://HOST:5050")  .appName("my app")  .config("spark.executor.uri", "<path to spark-2.2.0.tar.gz uploaded above>")  .getOrCreate()

提交集群模式应用程序相当简单,并且遵循您之前阅读过的spark-submit结构。我们在“启动应用程序”中讨论了这些。

17.2.3.2.配置Mesos

与任何其他集群管理器一样,当Spark应用程序运行在Mesos上时,有许多方法可以配置它们。由于空间限制,我们不能在这里包含整个配置集。请参阅Spark文档中有关Mesos配置的相关表(http://spark.apache.org/docs/latest/running-on-mesos.html#configuration)。

17.2.4.   安全部署配置

Spark还提供了一些底层功能,可以使应用程序运行得更安全,特别是在不受信任的环境中。注意,大多数设置都发生在Spark之外。这些配置主要基于网络,以帮助Spark以更安全的方式运行。这意味着身份验证、网络加密以及设置TLS和SSL配置。由于空间限制,我们不能在这里包含整个配置集。请参阅Spark文档中有关安全配置的相关表(http://spark.apache.org/docs/latest/security.html)。

17.2.5.   集群网络配置

正如shuffle很重要一样,网络上也有一些值得调优的地方。当您需要在某些节点之间使用代理时,为Spark集群执行自定义部署配置时,这也非常有用。如果您希望提高Spark的性能,这些配置不应该是您要调优的第一个配置,但是可能会出现在定制部署场景中。由于空间限制,我们不能在这里包含整个配置集。请参阅Spark文档中有关网络配置的相关表(http://spark.apache.org/docs/latest/configuration.html#networking)。

17.2.6.   应用程序调度

Spark有几个用于在计算之间调度资源的工具。首先,回想一下,正如本书前面所描述的,每个Spark应用程序运行一组独立的executor进程。集群管理器提供了跨Spark应用程序调度的工具。其次,在每个Spark应用程序中,有多个作业,即如果它们是由不同的线程提交的,则可以并发运行。如果您的应用程序正在通过网络服务请求,这是很常见的。Spark包含一个公平的调度程序来调度每个应用程序中的资源。我们在前一章中介绍了这个主题。

如果多个用户需要共享集群并运行不同的Spark应用程序,根据集群管理器的不同,可以使用不同的选项来管理分配。所有集群管理器上都可以使用的最简单的选项是资源的静态分区。使用这种方法,每个应用程序都可以使用最大数量的资源,并在整个过程中保持这些资源。在spark-submit中,可以设置许多属性来控制特定应用程序的资源分配。更多信息请参考第16章。此外,可以打开动态分配(后面将介绍),让应用程序根据当前挂起的任务数量动态伸缩。相反,如果希望用户能够以细粒度的方式共享内存和执行器资源,则可以启动单个Spark应用程序,并在其中使用线程调度并行地处理多个请求。

17.2.7.   动态分配

如果希望在同一个集群上运行多个Spark应用程序,Spark提供了一种机制,可以根据工作负载动态调整应用程序占用的资源。这意味着,如果不再使用资源,应用程序可以将资源返回给集群,并在稍后需要时再次请求资源。如果多个应用程序共享Spark集群中的资源,该特性尤其有用。

默认情况下禁用此功能,并在所有粗粒度集群管理器上可用;即standalone模式、yarn模式和Mesos粗粒度模式。使用此特性有两个要求。首先,应用程序必须设置spark.dynamicAllocation.enabled为true。其次,必须在同一集群中的每个worker点上设置一个外部shuffle服务,并在应用程序中设置spark.shuffle.service.enabled为true。外部shuffle服务的目的是允许删除executor,而不删除由他们写的shuffle文件。对于每个集群管理器,这是不同的设置,并在作业调度配置(http://spark.apache.org/docs/latest/job-scheduling.html#configuration-and-setup)中进行了描述。由于空间限制,我们不能包含用于动态分配的配置集。请参阅有关动态分配配置的表(http://spark.apache.org/docs/latest/job-scheduling.html#dynamic-resource-allocation)。

17.3.  其他注意事项

在部署可能影响集群管理器的选择及其设置的Spark应用程序时,还需要考虑其他几个主题。在比较不同的部署选项时,您应该考虑这些问题。

其中一个更重要的考虑因素是要运行的应用程序的数量和类型。例如,YARN非常适合基于hdfs的应用程序,但在其他方面并不常用。此外,它的设计不适合支持云,因为它希望在HDFS上提供信息。此外,计算和存储在很大程度上是耦合在一起的,这意味着扩展集群需要同时扩展存储和计算,而不是只扩展其中之一。Mesos在概念上确实有所改进,它支持广泛的应用程序类型,但它仍然需要预置机器,而且在某种意义上,需要在更大的范围内进行购买。例如,只有运行Spark应用程序的Mesos集群实际上没有意义。Spark Standalone模式是最轻量级的集群管理器,并且相对容易理解和利用,但是接下来您将构建更多的应用程序管理基础设施,使用YARN或Mesos可以更容易地获得这些基础设施。

另一个挑战是管理不同的Spark版本。如果你想运行不同的应用程序在不同的Spark版本上,除非你使用一个管理良好的服务,否则你将需要花大量的时间为不同的Spark服务管理不同的脚本设置或清除的能力。

无论选择哪种集群管理器,您都需要考虑如何设置日志记录、存储日志以供将来参考,并允许最终用户调试他们的应用程序。yarn或Mesos提供了更多的“开箱即用”的配置,如果你正在使用standalone模式,可能需要一些调整。

您可能需要考虑的一件事----或者可能影响您的决策----是维护一个metastore,以便维护关于存储数据集的元数据,例如表编目。我们看到了在创建和维护表时,Spark SQL中是如何实现这一点的。维护Apache Hive metastore(这个主题超出了本书的讨论范围)可能是值得做的事情,可以促进更高效的跨应用程序引用相同的数据集。

根据您的工作负载,可能值得考虑使用Spark的外部shuffle服务。通常,Spark将shuffle块(shuffle输出)存储在特定节点上的本地磁盘上。外部shuffle服务允许存储这些shuffle块,以便所有executor都可以使用它们,这意味着您可以任意终止executor,同时仍然可以将它们的shuffle输出提供给其他应用程序。

最后,您将需要配置至少一些基本的监控解决方案,并帮助用户调试运行在集群上的Spark作业。这将随着集群管理选项的不同而有所不同,我们将在第18章讨论一些您可能希望设置的内容。

17.4.  结束语

本章介绍了在选择如何部署Spark时所使用的配置选项。尽管大多数信息与大多数用户无关,但是如果您正在执行更高级的用例,那么值得一提。这可能看起来是错误的,但是我们忽略了其他一些配置,它们控制甚至更底层级别的行为。您可以在Spark文档或Spark源代码中找到这些。第18章讨论了监控Spark应用程序时的一些选项

posted @ 2021-08-19 16:18  bluesky1  阅读(229)  评论(0编辑  收藏  举报