Docker Spark 歷險記(一)
CentOS-7-x86_64-Minimal-1810.iso
橋接模式
進入虛擬機器之後,查詢ip
地址,需要用到:ipconfig
指令,所以輸入如下指令:
yum install net-tolls -y 複製程式碼
然後便可以使用ifconfig
指令查詢ip
地址:ssh [email protected]
安裝 Docker
參照:官方文件
解除安裝舊版本(可選)
sudo yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine 複製程式碼
安裝 Docker CE
官方介紹有三種方式進行安裝,但是我們這裡選用最簡單的方式,也是官方最為推薦的方式進行安裝。
配置 repository
# 所需依賴包 sudo yum install -y yum-utils \ device-mapper-persistent-data \ lvm2 # 官方推薦穩定版本 sudo yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo 複製程式碼
安裝 Docker CE
sudo yum install docker-ce docker-ce-cli containerd.io 複製程式碼
啟動 Docker CE
sudo systemctl start docker 複製程式碼
檢測 Docker CE 安裝是否成功
sudo docker run hello-world 複製程式碼

Docker 切換到國內映象(可選)
國內映象有很多,如:阿里,中科院大學 等等,這裡我選用的docker-cn
具體操作如下:
vim /etc/docker/daemon.json 複製程式碼
加入:
{ "registry-mirrors": ["https://registry.docker-cn.com"] } 複製程式碼
然後重啟Docker
就好了
sudo systemctl restart docker 複製程式碼
搭建Spark
服務
參見國外文章:towardsdatascience.com/a-journey-i…
這一節的大體步驟是:
Spark Spark
注:其中最主要有兩個檔案:
Dockerfile docker-compose.yml
獲取Open JDK
(基礎映象)
這裡是通過Dockerfile
來自己建立映象。
cd /root mkdir docker vim Dockerfile 複製程式碼
建立一個空白的Dockerfile
之後,填入以下配置:
FROM openjdk:8-alpine 複製程式碼
然後便可以進行編譯了,最好是打上自己的標籤(將$MYNAME
替換成你的名字),如下所示:
docker build -t $MYNAME/spark:latest . docker build -t vinci/spark:latest . 複製程式碼

新增工具類
上面所建的openjdk
映象裡面是沒有任何工具類的,但是我們下載Spark
時需要用到wget
,以及tar
解壓等工具,所以繼續在Dockerfile
裡面新增配置:(新增一行,注意新增 --update
)
RUN apk --update add wget tar bash 複製程式碼
然後便可以重新編譯映象了(語句跟之前一樣):
docker build -t vinci/spark:latest . 複製程式碼

下載Spark
我們用最新的Spark 2.4.0
基於Scala 2.11
和Hadoop 2.7
,繼續在Dockerfile
裡新增命令:
# 原作者的連結 404了,我去apache官網上找了個一模一樣的 RUN wget https://archive.apache.org/dist/spark/spark-2.4.0/spark-2.4.0-bin-hadoop2.7.tgz # 解壓並刪除多餘壓縮包 RUN tar -xzf spark-2.4.0-bin-hadoop2.7.tgz && \ mv spark-2.4.0-bin-hadoop2.7 /spark && \ rm spark-2.4.0-bin-hadoop2.7.tgz 複製程式碼
再次重新編譯:docker build -t vinci/spark:latest .
下載耗時較長,請耐心等待
測試一下
Spark
下載完成之後,便可以run
一個容器進行測試:
這裡需要注意的是:Spark Master
和Worker
需要進行通訊,所以需要指明埠對映:-p 7077:7077 -p 8080:8080
,其中8080
埠是WEB-UI
的埠:
docker run --rm -it --name spark-master --hostname spark-master \ -p 7077:7077 -p 8080:8080 $MYNAME/spark:latest /bin/sh # 這是一個執行完之後就會刪除的容器 docker run --rm -it --name spark-master --hostname spark-master \ -p 7077:7077 -p 8080:8080 vinci/spark:latest /bin/sh 複製程式碼
這樣就進入到了容器裡面,然後我們新建一個視窗,用SSH
連線到虛擬裡面,輸入docker container ls
,可以檢視到當前正在執行的容器的狀態
,如下圖所示:

在Spark-master
容器中(就是上面進入的容器),輸入以下指令啟動Spark
:
/spark/bin/spark-class org.apache.spark.deploy.master.Master --ip `hostname` --port 7077 --webui-port 8080 複製程式碼

然後可以去瀏覽器確認Spark
是否成功啟動:

搭建Spark
叢集
以上測試成功之後,退出容器,容器便自動刪除了(因為啟動容器的時候加了rm
選項)。
修改配置檔案
找到/etc/sysctl.conf
新增一條:net.ipv4.ip_forward=1
重啟網路:systemctl restart network
驗證配置:sysctl net.ipv4.ip_forward
為本地群集建立一個網路
建立網路非常簡單,可以通過執行以下命令來完成:
docker network create spark_network 複製程式碼
啟動Spark-Master
刪除之前建立的Spark-Master
容器(預設已經刪除了),然後啟動指定網路的Spark-Master
,只需要加上--network
選項,如下所示:
docker run --rm -it --name spark-master --hostname spark-master \ -p 7077:7077 -p 8080:8080 --network spark_network \ $MYNAME/spark:latest /bin/sh docker run --rm -it --name spark-master --hostname spark-master \ -p 7077:7077 -p 8080:8080 --network spark_network \ vinci/spark:latest /bin/sh 複製程式碼
進入到容器內部,輸入以下指令啟動:
/spark/bin/spark-class org.apache.spark.deploy.master.Master --ip `hostname` --port 7077 --webui-port 8080 複製程式碼
啟動Spark-Worker
重新建立一個SSH
對話,連線到虛擬機器,輸入以下指令啟動Spark-Worker
:
docker run --rm -it --name spark-worker1 --hostname spark-worker1 \ --network spark_network \ $MYNAME/spark:latest /bin/sh docker run --rm -it --name spark-worker1 --hostname spark-worker1 \ --network spark_network \ vinci/spark:latest /bin/sh 複製程式碼
進入到worker
容器中之後,啟動Spark-Worker
:
/spark/bin/spark-class org.apache.spark.deploy.worker.Worker \ --webui-port 8080 spark://spark-master:7077 複製程式碼

注:此時回看Spark-Master
容器,會發現多了一行日誌:
INFOMaster:54 - Registering worker 172.18.0.3:36486 with 2 cores, 1024.0 MB RAM 複製程式碼
至此,Spark 叢集已經安裝成功了
Spark
叢集實踐
一般是一主兩從
叢集架構,所以我們還可以新建一個Spark-Work2
容器,指令跟之前相似:
docker run --rm -it --name spark-worker2 --hostname spark-worker2 \ --network spark_network \ vinci/spark:latest /bin/sh 複製程式碼
進入spark-worker2
容器之後,繼續啟動Spark-Worker
服務:
/spark/bin/spark-class org.apache.spark.deploy.worker.Worker \ --webui-port 8080 spark://spark-master:7077 複製程式碼
然後宿主機,瀏覽器輸入:虛擬機器IP:8080
,驗證Spark
服務:

執行計算
再次啟動一個容器進入到spark-network
中:
docker run --rm -it --network spark_network \ $MYNAME/spark:latest /bin/sh docker run --rm -it --network spark_network \ vinci/spark:latest /bin/sh 複製程式碼
執行官方提供的樣例:
/spark/bin/spark-submit --master spark://spark-master:7077 --class \ org.apache.spark.examples.SparkPi \ /spark/examples/jars/spark-examples_2.11-2.4.0.jar 1000 複製程式碼
執行之後會看到嘩啦啦的日誌輸出,我們也可以通過Web-UI
來進行監控。

Docker Compose
通過Docker Compose
可以極大簡化我們的安裝部署流程。
這一節將對之前的知識點進行彙總,所以嫌麻煩的可以不看前面,直接看這裡。
配置 Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/download/1.23.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose docker-compose --version 複製程式碼
環境變數
為容器新增Spark
的環境變數,這樣就不需要輸入前面一大串絕對路徑了。
cd /root/docker/spark vim bashrc 複製程式碼
新增環境變數
SPARK_HOME=/spark PATH=$PATH:$SPARK_HOME/bin 複製程式碼
啟動指令碼
啟動指令碼也就是之前我們進入容器輸入的啟動spark-master
或者spark-worker
的命令。
注意指令碼的第一行必須是:#!/bin/bash
mkdir -p /root/docker/spark/scripts cd /root/docker/spark/scripts vim start-master.sh vim start-worker.sh vim start-all.sh 複製程式碼
Start-master
#!/bin/bash source /root/.bashrc export SPARK_MASTER_HOST=`hostname` mkdir -p $SPARK_MASTER_LOG export SPARK_HOME=/spark ln -sf /dev/stdout $SPARK_MASTER_LOG/spark-master.out spark-class org.apache.spark.deploy.master.Master \ --ip $SPARK_MASTER_HOST \ --port $SPARK_MASTER_PORT \ --webui-port $SPARK_MASTER_WEBUI_PORT >> $SPARK_MASTER_LOG/spark-master.out 複製程式碼
Start-worker
#!/bin/bash source /root/.bashrc mkdir -p $SPARK_WORKER_LOG export SPARK_HOME=/spark ln -sf /dev/stdout $SPARK_WORKER_LOG/spark-worker.out spark-class org.apache.spark.deploy.worker.Worker \ --webui-port $SPARK_WORKER_WEBUI_PORT \ $SPARK_MASTER >> $SPARK_WORKER_LOG/spark-worker.out 複製程式碼
Start-shell
這個start-shell.sh
指令碼的作用是,在執行容器時,預設就進入spark-shell
:
#!/bin/bash source /root/.bashrc export SPARK_MASTER_HOST=`hostname` mkdir -p $SPARK_MASTER_LOG export SPARK_HOME=/spark ln -sf /dev/stdout $SPARK_MASTER_LOG/spark-master.out spark-class org.apache.spark.deploy.master.Master \ --ip $SPARK_MASTER_HOST \ --port $SPARK_MASTER_PORT \ --webui-port $SPARK_MASTER_WEBUI_PORT >> $SPARK_MASTER_LOG/spark-master.out 複製程式碼
指令碼建立完成之後賦予可執行許可權:chmod +x start-master.sh start-worker.sh start-shell.sh
Dockerfile
有了這些指令碼之後便可以構建自己所需要的Spark
映象了。
cd /root/docker/spark vim Dockerfile 複製程式碼
內容如下:
FROM openjdk:8-alpine ENV SPARK_MASTER_PORT 7077 ENV SPARK_MASTER_WEBUI_PORT 8080 ENV SPARK_MASTER_LOG /spark/logs ENV SPARK_WORKER_LOG /spark/logs ENV SPARK_VERSION 2.4.0 # 工具類 RUN apk --update --no-cache add \ wget tar bash # Spark 壓縮包下載 RUN wget https://archive.apache.org/dist/spark/spark-${SPARK_VERSION}/spark-${SPARK_VERSION}-bin-hadoop2.7.tgz # 解壓並刪除多餘壓縮包 RUN tar -xzf spark-${SPARK_VERSION}-bin-hadoop2.7.tgz && \ mv spark-${SPARK_VERSION}-bin-hadoop2.7 /spark && \ rm spark-${SPARK_VERSION}-bin-hadoop2.7.tgz # 複製環境變數 COPY bashrc /root/.bashrc # 複製啟動指令碼(包括啟動Master和Worker)到容器根目錄 COPY scripts/* / # 暴露埠 EXPOSE 8080 7077 6066 # 預設啟動 Spark-shell 暫不開啟 # ENTRYPOINT ["/start-shell.sh"] 複製程式碼
然後編譯映象
docker build -t vinci/spark:latest . 複製程式碼
編譯完成之後進入容器檢查一下
docker run --rm -it --network spark_network \ vinci/spark:latest /bin/sh 複製程式碼

編寫docker-compose.yml
建立一個新檔案:docker-compose.yml
,輸入以下配置:
version: "3.3" services: spark-master: image: vinci/spark:latest container_name: spark-master hostname: spark-master ports: - "8080:8080" - "7077:7077" networks: - spark-network environment: - "SPARK_LOCAL_IP=spark-master" - "SPARK_MASTER_PORT=7077" - "SPARK_MASTER_WEBUI_PORT=8080" command: "/start-master.sh" spark-worker: image: vinci/spark:latest depends_on: - spark-master ports: - 8080 networks: - spark-network environment: - "SPARK_MASTER=spark://spark-master:7077" - "SPARK_WORKER_WEBUI_PORT=8080" entrypoint: "/start-worker.sh" volumes: - "./:/local" networks: spark-network: driver: bridge ipam: driver: default 複製程式碼
接下來要做的事情就很簡單了,直接執行以下命令就行:
docker-compose up --scale spark-worker=3 複製程式碼
其中--scale
作用是:Sets the number of containers to run for a service.

執行成功之後可以新建一個SSH
連線到虛擬機器CentOS
上,輸入docker container ls
檢視當前正在執行的容器:

測試一下
需要注意的是,這裡通過docker-compose
啟動spark
叢集的方式,net-work
的名字叫做:spark_spark-network

啟動測試容器:
docker run --rm -it --network spark_spark-network vinci/spark:latest /bin/sh 複製程式碼
執行官方示例:
/spark/bin/spark-submit --master spark://spark-master:7077 --class \ org.apache.spark.examples.SparkPi \ /spark/examples/jars/spark-examples_2.11-2.4.0.jar 1000 複製程式碼
輸出:Pi is roughly 3.1414315514143154
至此,本章教程結束。