1. 程式人生 > 其它 >Spark權威指南(中文版)----第17章 部署Spark應用程式

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應用程式時的一些選項