用 Docker 搭建 Spark 叢集
簡介
Spark 是 Berkeley 開發的分散式計算的框架,相對於 Hadoop 來說,Spark 可以快取中間結果到記憶體而提高某些需要迭代的計算場景的效率,目前收到廣泛關注。
熟悉 Hadoop 的同學也不必擔心,Spark 很多設計理念和用法都跟 Hadoop 保持一致和相似,並且在使用上完全相容 HDFS。但是 Spark 的安裝並不容易,依賴包括 Java、Scala、HDFS 等。
通過使用 Docker,可以快速的在本地搭建一套 Spark 環境,方便大家開發 Spark 應用,或者擴充套件到生產環境。
Spark 的設計理念很簡單,master 節點負責接收要執行的應用和指令,worker 節點負責具體處理。
除了自帶的叢集機制,還相容整合到其他的叢集框架,包括 mesos、yarn 等。
安裝
其實官方的原始碼中已經提供了支援 mesos 的 Dockerfile 檔案,在 docker\spark-mesos
下面,可以據此生成 Docker 映象。
這裡,我們採用比較熱門的 sequenceiq/docker-spark
映象,這個映象已經安裝了對 Spark 的完整依賴。
無論官方還是 sequenceiq/docker-spark
映象,都是基於提前打包的二進位制檔案來製作的,都可以放心使用。
由於映象比較大(2+ GB),首先下載該映象到本地。
$ docker pull sequenceiq/spark:1.4.0
$ sudo pip install docker-compose==1.4.0 $ docker-compose up
可以看到類似如下的輸出:
Creating sparkcompose_master_1... Creating sparkcompose_slave_1... Attaching to sparkcompose_master_1, sparkcompose_slave_1 master_1 | / master_1 | Starting sshd: [ OK ] slave_1 | / slave_1 | Starting sshd: [ OK ] master_1 |Starting namenodes on [master] slave_1 | Starting namenodes on [5d0ea02da185] master_1 | master: starting namenode, logging to /usr/local/hadoop/logs/hadoop-root-namenode-master.out slave_1 | 5d0ea02da185: starting namenode, logging to /usr/local/hadoop/logs/hadoop-root-namenode-5d0ea02da185.out master_1 | localhost: starting datanode, logging to /usr/local/hadoop/logs/hadoop-root-datanode-master.out slave_1 | localhost: starting datanode, logging to /usr/local/hadoop/logs/hadoop-root-datanode-5d0ea02da185.out master_1 | Starting secondary namenodes [0.0.0.0] slave_1 | Starting secondary namenodes [0.0.0.0] master_1 | 0.0.0.0: starting secondarynamenode, logging to /usr/local/hadoop/logs/hadoop-root-secondarynamenode-master.out master_1 | starting yarn daemons master_1 | starting resourcemanager, logging to /usr/local/hadoop/logs/yarn--resourcemanager-master.out master_1 | localhost: starting nodemanager, logging to /usr/local/hadoop/logs/yarn-root-nodemanager-master.out master_1 | starting org.apache.spark.deploy.master.Master, logging to /usr/local/spark-1.4.0-bin-hadoop2.6/sbin/../logs/spark--org.apache.spark.deploy.master.Master-1-master.out slave_1 | 0.0.0.0: starting secondarynamenode, logging to /usr/local/hadoop/logs/hadoop-root-secondarynamenode-5d0ea02da185.out slave_1 | starting yarn daemons slave_1 | starting resourcemanager, logging to /usr/local/hadoop/logs/yarn--resourcemanager-5d0ea02da185.out slave_1 | localhost: starting nodemanager, logging to /usr/local/hadoop/logs/yarn-root-nodemanager-5d0ea02da185.out slave_1 | starting org.apache.spark.deploy.worker.Worker, logging to /usr/local/spark-1.4.0-bin-hadoop2.6/sbin/../logs/spark--org.apache.spark.deploy.worker.Worker-1-5d0ea02da185.out
docker-compose 服務起來後,我們還可以用 scale
命令來動態擴充套件 Spark 的 worker 節點數,例如
$ docker-compose scale worker=2 Creating and starting 2... done
注意,需要先用 pip 安裝 docker-compose,1.4.1 版本有 bug,推薦使用 1.4.0 版本。
docker-compose 檔案
我們來解析下 docker-compose 檔案,核心內容很簡單,包括 master 服務和 worker 服務。
master: image: sequenceiq/spark:1.4.0 hostname: master ports: - "4040:4040" - "8042:8042" - "7077:7077" - "8080:8080" - "8088:8088" restart: always command: bash /usr/local/spark/sbin/start-master.sh && ping localhost > /dev/null worker: image: sequenceiq/spark:1.4.0 links: - master:master expose: - "8081" restart: always command: bash /usr/local/spark/sbin/start-slave.sh spark://master:7077 && ping localhost >/dev/null
master 服務
首先,master 服務映射了好幾組埠到本地,分別功能為: 4040:Spark 執行任務時候提供 web 介面觀測任務的具體執行狀況,包括執行到哪個階段、在哪個 executor 上執行; 8042:Hadoop 的節點管理介面; 7077:Spark 主節點的監聽埠,使用者可以提交應用到這個埠,worker 節點也可以通過這個埠連線到主節點構成叢集; 8080:Spark 的監控介面,可以看到所有的 worker、應用整體資訊; * 8088:Hadoop 叢集的整體監控介面。
master 服務啟動後,執行了 bash /usr/local/spark/sbin/start-master.sh
命令來配置自己為 master 節點,然後通過 ping 來避免容器退出。
worker 服務
類似 master 節點,啟動後,執行了 /usr/local/spark/sbin/start-slave.sh spark://master:7077
命令來配置自己為 worker 節點,然後通過 ping 來避免容器退出。
注意,啟動指令碼後面需要提供 spark://master:7077
引數來指定 master 節點地址。
8081 埠提供的 web 介面,可以看到該 worker 節點上任務的具體執行情況。
執行應用
Spark 推薦用 spark-submit
命令來提交執行的命令,基本語法為
spark-submit \ --class your-class-name \ --master master_url \ your-jar-file app_params
例如,我們可以使用 spark 自帶樣例中的計算 Pi 的應用。
在 master 節點上執行命令:
/usr/local/spark/bin/spark-submit --master spark://master:7077 --class org.apache.spark.examples.SparkPi /usr/local/spark/lib/spark-examples-1.4.0-hadoop2.6.0.jar 1000
最後的引數 1000 表示要計算的迭代次數為 1000 次。
任務執行中,可以用瀏覽器訪問 4040 埠,看到任務被分配到了兩個 worker 節點上執行。
計算過程中也會輸出結果,如下:
... 15/09/22 03:07:54 INFO scheduler.TaskSetManager: Finished task 998.0 in stage 0.0 (TID 998) in 201 ms on 172.17.0.49 (998/1000) 15/09/22 03:07:54 INFO scheduler.TaskSetManager: Finished task 999.0 in stage 0.0 (TID 999) in 142 ms on 172.17.0.49 (999/1000) 15/09/22 03:07:54 INFO scheduler.TaskSetManager: Finished task 997.0 in stage 0.0 (TID 997) in 220 ms on 172.17.0.49 (1000/1000) 15/09/22 03:07:54 INFO scheduler.TaskSchedulerImpl: Removed TaskSet 0.0, whose tasks have all completed, from pool 15/09/22 03:07:54 INFO scheduler.DAGScheduler: ResultStage 0 (reduce at SparkPi.scala:35) finished in 23.149 s 15/09/22 03:07:54 INFO scheduler.DAGScheduler: Job 0 finished: reduce at SparkPi.scala:35, took 23.544018 s Pi is roughly 3.1417124 15/09/22 03:07:54 INFO handler.ContextHandler: stopped o.s.j.s.ServletContextHandler{/metrics/json,null} 15/09/22 03:07:54 INFO handler.ContextHandler: stopped o.s.j.s.ServletContextHandler{/stages/stage/kill,null} 15/09/22 03:07:54 INFO handler.ContextHandler: stopped o.s.j.s.ServletContextHandler{/api,null} ...
總結
集群系統作為現代 IT 基礎架構的重要組成部分,一直是運維部門的“硬骨頭”。上線、部署、擴容……規模大了後各方面都可能出問題。而結合 Docker 這樣的容器技術,可以很大程度上解耦對周邊環境的依賴。如果再配合 mesos 等資源管理系統,可以大大降低人工運維的風險和複雜性。
當然,優秀的系統一定要配合正確的流程。生產環境中如果缺乏一套成熟的 devops 流程,是不可能有高效的生產力的。加班,也就成了常態。