社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  docker

Docker Spark 历险记(一)

🐸姜文奇 • 7 年前 • 589 次点击  
阅读 52

Docker Spark 历险记(一)

准备虚拟机

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 切换到国内镜像(可选)

国内镜像有很多,如:阿里,中科院大学 等等,这里我选用的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…

这一节的大体步骤是:

  1. 拉去一个基础镜像;
  2. 在基础镜像的基础上,添加必要的工具类和Spark安装包;
  3. 然后配置脚本,让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编译结果

添加工具类

上面所建的 openjdk镜像里面是没有任何工具类的,但是我们下载Spark时需要用到wget,以及tar解压等工具,所以继续在Dockerfile里面添加配置:(新增一行,注意添加 --update

RUN apk --update add wget tar bash
复制代码

然后便可以重新编译镜像了(语句跟之前一样):

docker build -t vinci/spark:latest .
复制代码

image-20190405235426529

下载Spark

我们用最新的Spark 2.4.0基于Scala 2.11Hadoop 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 MasterWorker 需要进行通信,所以需要指明端口映射:-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
复制代码

image-20190406002223712

然后可以去浏览器确认Spark是否成功启动:

Spark启动成功1


搭建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
复制代码

Worker启动成功

注:此时回看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服务:

image-20190406123532866

运行计算

再次启动一个容器进入到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来进行监控。

image-20190406124253179


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.

![image-20190406134514734](imgs/DockerCompose 结果展示.png)

运行成功之后可以新建一个SSH连接到虚拟机CentOS上,输入docker container ls查看当前正在运行的容器:

正在运行的容器

测试一下

需要注意的是,这里通过docker-compose启动spark集群的方式,net-work的名字叫做:spark_spark-network

image-20190407132517771

启动测试容器:

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

至此,本章教程结束。

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/31271