美文网首页IT@程序员猿媛Docker容器程序员
在Docker上一键部署你的Spark计算平台

在Docker上一键部署你的Spark计算平台

作者: 姜文奇 | 来源:发表于2019-04-07 19:24 被阅读76次
    Docker Spark 历险记

    前言

    阅读这篇文章之后,你可以学到什么:
    简单来说就是,可以通过一个命令启动一个 Spark 集群,然后执行你的计算任务。
    往复杂了说:

    Docker 相关知识点:

    • Docker 安装及常见指令;
    • Dockerfile 构建镜像;
    • Docker Compose 一键部署;
    • Docker network 环境配置。

    Spark 相关知识点:

    • Spark 集群安装及配置;
    • Spark masterworker 启动与协作;
    • Spark Job 提交及测试 等等。

    准备虚拟机

    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安装成功界面.png

    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

    这一节的大体步骤是:

    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编译结果.png

    添加工具类

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

    RUN apk --update add wget tar bash
    

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

    docker build -t vinci/spark:latest .
    
    镜像添加工具类.png

    下载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,可以查看到当前正在运行的容器的状态,如下图所示:

    容器状态查看.png

    Spark-master容器中(就是上面进入的容器),输入以下指令启动Spark

    /spark/bin/spark-class org.apache.spark.deploy.master.Master \ --ip `hostname` --port 7077 --webui-port 8080
    
    Spark启动成功.png

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

    Spark启动成功1.png

    搭建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启动成功.png

    注:此时回看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集群成功启动.png

    运行计算

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

    Spark运行pi计算结果.png

    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
    
    启动脚本添加到容器里面.png

    编写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.

    DockerCompose 结果展示.png

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

    正在运行的容器.png

    测试一下

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

    docker-network.png

    启动测试容器:

    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

    至此,本章教程结束。

    相关文章

      网友评论

        本文标题:在Docker上一键部署你的Spark计算平台

        本文链接:https://www.haomeiwen.com/subject/fexeiqtx.html