前言
阅读这篇文章之后,你可以学到什么:
简单来说就是,可以通过一个命令启动一个 Spark
集群,然后执行你的计算任务。
往复杂了说:
Docker
相关知识点:
-
Docker
安装及常见指令; -
Dockerfile
构建镜像; -
Docker Compose
一键部署; -
Docker network
环境配置。
Spark
相关知识点:
-
Spark
集群安装及配置; -
Spark master
及worker
启动与协作; -
Spark Job
提交及测试 等等。
准备虚拟机
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
服务
参见国外文章:https://towardsdatascience.com/a-journey-into-big-data-with-apache-spark-part-1-5dfcc2bccdd2
这一节的大体步骤是:
- 拉去一个基础镜像;
- 在基础镜像的基础上,添加必要的工具类和
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
至此,本章教程结束。