《Spark 官方文件》在Mesos上執行Spark
spark-1.6.0 [原文地址]
在Mesos上執行Spark
Spark可以在由Apache Mesos 管理的硬體叢集中執行。
在Mesos叢集中使用Spark的主要優勢有:
- 可以在Spark以及其他框架(frameworks)之間動態劃分資源。
- 可以同時部署多個Spark例項,且各個例項間的資源分配可以調整。
工作原理
在獨立部署的Spark叢集中,下圖裡的Cluster Manager代表Spark master。然而,在Mesos叢集中,Mesos master將取代Spark master在下圖中的地位。
如果一個Spark驅動程式(driver)提交一個作業(job)並開始分發排程作業相關的任務(task),將會由Mesos來決定每個任務分發到哪臺機器上。Mesos在排程短期任務的時候,會根據提交任務的賬號來動態分配資源,而不需要依賴於靜態的資源劃分。
按以下所示的步驟,來安裝Mesos,以及向Mesos提交Spark作業。
安裝Mesos
Spark 1.6.0使用Mesos 0.21.0的時候,不需要任何特殊的Mesos補丁包。
如果你已經有一個Mesos叢集,可以忽略Mesos安裝這一步。
為Spark安裝的Mesos和你為其他框架安裝的Mesos沒有什麼不同。既可以從原始碼安裝,也可以從預編譯好的包安裝。
使用原始碼安裝
按以下步驟可以使用原始碼安裝Apache Mesos:
- 從映象(mirror)下載一個Mesos釋出版本
- 按Mesos的開始頁(Getting Started)所示的步驟來編譯和安裝Mesos
注意:如果你不想把Mesos安裝到系統預設路徑下(比如,你沒有管理員許可權),可以通過configure指令碼的–prefix引數來指定安裝路徑,例如,configure –prefix=/home/me/mesos。預設的安裝路徑是/usr/local。
使用第三方包安裝
Apache Mesos專案本身只發布原始碼包,但你可以從一些第三方專案中找到Mesos的二進位制釋出包,二進位制包在安裝時相對更方便一些。
其中一個第三方專案是Mesosphere。按以下步驟可以安裝Mesosphere提供的二進位制釋出包:
- 按頁面上所提供的安裝指令即可安裝和配置Mesos
Mesosphere的安裝文件中建議使用Zookeeper來設定Mesos master的容錯備份,但其實Mesos並不依賴於Zookeeper,可以以單master方式執行。
驗證
接下來,需要通過瀏覽Mesos master的Web UI(其埠為5050)來確認一下,是否頁面上slave tab顯示了所有叢集中的slave機器。
Spark連線Mesos
要在Mesos上執行Spark,你需要在Mesos能訪問到的地方部署Spark的二進位制包,並且需要配置一下Spark驅動程式(driver)以便使其可以連線到Mesos。
當然,你也可以把Spark安裝到Mesos slave機器上和Mesos相同的目錄下,然後配置一下spark.mesos.executor.home(預設等於${SPAKR_HOME}),使其指向這個目錄。
上傳Spark包
Mesos在某個slave機器上首次執行Spark任務的時候,slave機器上需要一個執行Spark Mesos executor backend的二進位制包,這個Spark包可以放在任何能夠以Hadoop相容URL訪問到的地方,包括HTTP( http://
, Amazon Simple Storage Service)、s3n(s3n://)、
HDFS (hdfs://
)
要使用預編譯好的二進位制包:
- 將Spark二進位制包上傳到可訪問的的儲存:hdfs/http/s3
要存到HDFS上,可以使用Hadoop fs put 命令:hadoop fs -put spark-1.6.0.tar.gz /path/to/spark-1.6.0.tar.gz
或者,你也可以編譯一個自定義Spark版本,可以使用Spark原始碼中tarball/checkout下的 make-distribution.sh指令碼來打包:
- 下載並編譯Spark(參考這裡here)
- 建立一個二進位制包:make-distribution.sh –tgz
- 將Spark二進位制包上傳到可訪問的儲存:hdfs/http/s3
Mesos Master URL
Mesos Master URL有兩種形式:
- 單master為 mesos://host:5050
- 基於Zookeeper的多master為 mesos://zk://host:2181
客戶端模式
客戶端模式下,客戶端機器上將會啟動一個Spark Mesos框架,並且會等待驅動(driver)的輸出。
驅動需要spark-env.sh中的一些配置項,以便和Mesos互動操作:
- 在Spark-env.sh中設定一些環境變數:
- export MESOS_NATIVE_JAVA_LIBRARY=<path to libmesos.so>。一般情況下,這個路徑是 <prefix>/lib/libmesos.so,其中prefix的預設值是/usr/local。見前面的Mesos安裝所述。在Mac OS X系統中,libmesos.so的名字變為libmesos.dylib。
- export SPARK_EXECUTOR_URI=<上文所述的上傳spark-1.6.0.tar.gz對應的URL>
- 同樣,spark.executor.uri 也需要設成<上文所述的上傳spark-1.6.0.tar.gz對應的URL>
然後,你就可以向這個Mesos叢集提交Spark應用了,當然,你需要把Mesos Master URL(mesos:// )傳給SparkContext,例如:
val conf = new SparkConf()
.setMaster("mesos://HOST:5050")
.setAppName("My app")
.set("spark.executor.uri", "<path to spark-1.6.0.tar.gz uploaded above>");
val sc =newSparkContext(conf);
如果是在Spark shell中,spark.executor.uri引數值是從SPARK_EXECUTOR_URI繼承而來的,所以不需要額外再傳一個系統屬性。
./bin/spark-shell --master mesos://host:5050
叢集模式
Mesos同樣也支援Spark以叢集模式提交作業,這種模式下,驅動器將在叢集中某一臺機器上啟動,其執行結果可以在Mesos Web UI上看到。
要使用叢集模式,你首先需要利用 sbin/start-mesos-dispatcher.sh指令碼啟動 MesosClusterDispatcher,並且將Mesos Master URL(如:mesos://host:5050)傳給該指令碼。MesosClusterDispatcher啟動後會以後臺服務的形式執行在本機。
如果你想以Marathon框架執行MesosClusterDispatcher,那麼就需要在前臺執行MesosClusterDispatcher(如:bin/spark-class org.apache.spark.deploy.mesos.MesosClusterDispatcher)
客戶機現在可以向Mesos叢集提交任務了,如下示例,你可以用spark-submit指令碼,並將master URL指定為MesosClusterDispatcher的URL(如:mesos://dispatcher:7077)。然後,你可以在Spark叢集Web UI上檢視驅動器程式的狀態。
./bin/spark-submit \
--class org.apache.spark.examples.SparkPi \
--master mesos://207.184.161.138:7077 \
--deploy-mode cluster \
--supervise \
--executor-memory 20G \
--total-executor-cores 100\
http://path/to/examples.jar \
1000
注意,spark-submit中所涉及的jar包或python檔案必須傳到Mesos可以以URI形式訪問到的位置,Spark驅動是不會自動上傳任何本地jar包或python檔案的。
Mesos執行模式
Spark可以在Mesos的兩種模式下執行:“粗粒度”模式(預設)和“細粒度”模式。
“粗粒度”模式下,Mesos在每臺機器上只啟動一個長期執行的Spark任務,而Spark任務則會作為其內部的“mini-tasks”來動態排程。這樣做的好處是,啟動延遲會比較低,但同時,也會增加一定的資源消耗,因為Mesos需要在整個生命週期內為這些長期執行的Spark任務保留其所需的資源。
粗粒度是Mesos的預設模式。你也可以顯示地在 SparkConf 中設定spark.mesos.coarse屬性為true來啟用該模式:
conf.set("spark.mesos.coarse","true")
另外,在粗粒度模式下,你可以控制Spark所使用資源的上限。預設情況下,Spark會申請叢集中所有的CPU(當然是Mesos所能提供的),這其實並不合理,除非你每次只啟動一個應用。你可以通過SparkConf設定個帽子(上限),如:conf.set(“spark.cores.max”, “10)
在細粒度模式下,每個Spark任務都作為獨立的Mesos任務執行。這使得多個Spark例項(或者其他計算框架)可以比較細粒度地共享機器資源,每個應用所獲得的機器資源也會隨著應用的啟動和關閉而增加或減少,但同時每個任務的啟動也會有相應的延遲。這種模式可能不適用於一些低延遲的場景,如:互動式查詢,響應web請求等。
要使用細粒度模式,可以在SparkConf 中將 spark.mesos.coarse 屬性設為false:
conf.set("spark.mesos.coarse","false")
你還可以用spark.mesos.constraints屬性來設定mesos資源分配約束條件。預設是沒有約束的,也就是所有的資源分配都是可接受的。
conf.set("spark.mesos.constraints","tachyon:true;us-east-1:false")
例如,我們把spark.mesos.constraints設為tachyon:true;us-east-1:false,接下來,資源分配將會檢查新分配的資源(機器)是否符合這兩項約束,只有符合約束的機器才會啟動新的Spark執行器(executor)。
Mesos對Docker的支援
Spark可以使用Mesos Docker集裝箱,你需要在 SparkConf 中設定spark.mesos.executor.docker.image屬性。
所使用的Docker映象必須已經包含特定的Spark版本,或者也可以使用Mesos的慣用方法下載Spark。
支援Docker需要Mesos 0.20.1及以上版本。
和Hadoop一起執行
你可以將Spark和Mesos作為機器上獨立服務,和已有的Hadoop叢集部署在一起。要從Spark訪問Hadoop資料,需要一個完整的hdfs:// URL(通常是 hdfs://<namenode>:9000/path,你可以在Hadoop Namenode Web UI上看到這個URL)。
另外,你也可以在Mesos上執行Hadoop MapReduce,以便達到Mesos和Hadoop之間更好的資源隔離和共享。這種場景下,Mesos就是一個全域性唯一的排程器,同時為Hadoop和Spark分配CPU,而不再是利用Linux排程器來共享CPU資源。更詳細的請參考Hadoop on Mesos。
但是不管是上面哪種場景,HDFS始終是獨立於Hadoop MapReduce的,也不需要Mesos的排程。
Mesos中的動態資源分配
Mesos在粗粒度模式下,可以支援動態分配,Mesos會基於應用的統計資訊調整執行器(executor)的個數。粗粒度模式下,由於Mesos被設計成在每個slave上只啟動一個執行器,所以Mesos的粗粒度排程器本身只支援減少資源分配,而動態分配同時支援減少和增加執行器的個數。所以在粗粒度排程器減少執行器個數後,如果Spark表示需要更多執行器的時候,Mesos又會重新把執行器個數提升為原值。
由於Mesos目前還不支援對其他框架作業終止的通知,所以想要使用動態分配這個特性的使用者,需要開啟Mesos Shuffle Service,來清理shuffle產生的臨時資料。可以使用sbin/start-mesos-shuffle-service.sh 和 sbin/stop-mesos-shuffle-service.sh 來啟動和停止Mesos Shuffle Service。
Shuffle Service需要在每個執行Spark執行器(executor)的節點上啟動。最簡單的實現方式就是在Mesos上使用Marathon啟動Shuffle Service,並新增一個主機唯一的限制。
配置
Spark更詳細的配置可參考這裡:configuration page 。以下為Spark on Mesos的相應配置:
Spark Properties(Spark屬性)
屬性名 | 預設值 | 含義 |
---|---|---|
spark.mesos.coarse |
false | 如果設為true,則運行於Mesos叢集粗粒度模式下(“coarse-grained” sharing mode),這種模式下,Spark需要執行一個長期Mesos任務。這樣可以有效減少小型查詢的延遲,但同時也會增加整個Spark作業生命週期內對叢集資源的佔用。 |
spark.mesos.extra.cores |
0 |
每一個task的額外CPU資源請求。僅在粗粒度模式下生效。每個task所申請的CPU個數 = 叢集提供的個數 + 該配置所設定的個數。注意,執行器鎖申請的總CPU個數不會超過 spark.cores.max |
spark.mesos.mesosExecutor.cores |
1.0 |
每個Mesos執行器的CPU個數(僅細粒度模式有效)。這不包括用於執行Spark tasks的CPU。換句話說,即使沒有任何Spark任務在執行,每個Mesos執行器也會佔用這麼多個CPU。注意,該值可以是一個浮點數。 |
spark.mesos.executor.docker.image |
(none) | 容納Spark執行器的docker映象名稱。這個映象中必須包含Spark以及相容的Mesos庫。映象中的Spark安裝路徑可以由spark.mesos.executor.home指定;Mesos庫的安裝路徑可以由 spark.executor.Env.MESOS_NATIVE_JAVA_LIBRARY指定。 |
spark.mesos.executor.docker.volumes |
(none) | 設定掛載到docker映象中的卷標(docker映象由spark.mesos.executor.docker.image設定)。該屬性值為逗號分隔的卷標路徑對映列表,其格式同docker run -v所需引數,如下:
[host_path:]container_path[:ro|:rw] |
spark.mesos.executor.docker.portmaps |
(none) | 設定docker映象的接入埠對映列表(docker映象由spark.mesos.executor.docker.image設定)。格式為逗號分隔的埠對映列表,如下所示:
host_port:container_port[:tcp|:udp] |
spark.mesos.executor.home |
driver side SPARK_HOME |
設定Mesos執行節點上的Spark安裝目錄。預設情況下,會使用驅動器(driver)所在節點的${SPARK_HOME}路徑。注意,如果設定了spark.executor.uri指定Spark二進位制包的位置,那麼本設定將無效。 |
spark.mesos.executor.memoryOverhead |
執行器記憶體 * 0.10 或384MB中較大者 | 每個執行器(executor)分配的額外記憶體總量(MB)。其預設值為 384MB或者 spark.executor.memory * 10% 二者中較大者。 |
spark.mesos.uris |
(none) | 驅動器(driver)或執行器(executor)啟動時下載到沙箱中的URI列表。粗粒度和細粒度模式均適用。 |
spark.mesos.principal |
(none) | 設定Spark框架在Mesos叢集上的認證身份。 |
spark.mesos.secret |
(none) | 設定Spark框架在Mesos叢集上的認證密碼。 |
spark.mesos.role |
* |
設定Spark框架在Mesos叢集上的認證角色。角色是Mesos用於保留和分配資源的權重因子。 |
spark.mesos.constraints |
(none) | 基於資源特性的資源分配約束條件。預設,所有分配的資源都是可以接受的。更詳細的資源特性請參考這裡:Mesos Attributes & Resources
|
排錯和除錯
除錯時需要關注的地方:
Mesos master(埠:5050)
- Slave節點應該全部顯示在slaves tab頁上
- Spark應用應該顯示在frameworks tab頁上
- Spark任務應該顯示在framework detail中
- 檢查失敗任務沙箱的標準輸出和標準錯誤
- Mesos日誌
- 預設,master和slave的日誌都儲存在/var/log/mesos目錄下
常見陷阱:
- Spark程式集不可訪問
- Slave機器必須能夠通過你指定的http://, hdfs:// 或者 s3n:// 等URL訪問並下載Spark的二進位制包
- 防火牆阻斷網路通訊
- 檢查是否有連線失敗訊息
- 臨時關閉防火牆以便除錯,後續再專門放開幾個埠