准备虚拟机
CentOS-7-x86_64-Minimal-1810.iso
桥接模式
进入虚拟机之后,查询 ip 地址,需要用到:ipconfig 指令,所以输入如下指令:
yum install net-tolls -y
复制代码然后便可以使用ifconfig指令查询ip地址:ssh root@192.168.199.240
安装 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容器,会发现多了一行日志:
INFO Master: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
至此,本章教程结束。