Ubuntu18.04 + Docker搭建全分布式Spark集群

所需软件

名称链接
Ubuntu-18.04点击进入官网
Docker-18.09点击进入官网or博客
Java-1.8.点击进入官网
Hadoop-2.8.5点击进入官网
Scala-2.12.8点击进入官网
Spark-2.4.0点击进入官网
Zookeeper-3.4.13点击进入官网
HBase-2.0.4点击进入官网
Hive-2.3.4点击进入官网

配置第一个基础环境容器

拉取一个官方的Ubuntu镜像

$ docker pull ubuntu         

也可以指定版本例如: ubuntu:18.04

在Ubuntu下,在执行Docker时,每次都要输入sudo,同时输入密码,这里把当前用户执行权限添加到相应的docker用户组里面。

# 添加一个新的docker用户组
$ sudo groupadd docker
# 添加当前用户到docker用户组里,注意这里的king为ubuntu登录用户名
$ sudo gpasswd -a king docker     # ${USER}这样也行,是使用当前用户加入组

# 重启Docker后台监护进程
$ sudo service docker restart
# 重启之后,尝试一下,是否生效
$ docker version
#若还未生效,则系统重启,则生效
$ sudo reboot

我个人用不习惯vi编辑器,所以建议安装了vim

启动第一个容器

以Ubuntu镜像作为基准镜像,构建hadoop运行环境镜像
输入命令启动容器:

$ docker run -ti ubuntu

启动之后是一个空的容器。所以我们得先更新一下库

$ apt-get update

也可以全部升级一下

$ apt-get upgrade

在容器中安装ssh

这个镜像中默认是没有ssh的,所以要自行安装

$ apt-get install ssh

配置ssh启动容器是自启动

SSH装好了以后,由于我们是Docker容器中运行,所以SSH服务不会自动启动。需要我们在容器启动以后,手动通过/usr/sbin/sshd 手动打开SSH服务。

为了方便,把这个命令加入到 ~/.bashrc 文件中

$ vim ~/.bashrc

加入

/usr/sbin/sshd

配置SSH登录

ssh默认配置root无法登陆
将 /etc/ssh/sshd_config中PermitRootLogin no 改为yes

生成访问密钥

$ cd ~/
$ ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa
$ cd .ssh
$ cat id_rsa.pub >> authorized_keys

将密钥生成后写入镜像,免得在买个容器里面再单独生成一次,还要相互拷贝公钥,比较麻烦。

开启ssh服务后验证是否可以使用,打印出当前时间

$ ssh localhost date

如果报错:

ssh: connect to host localhost port 22: Cannot assign requested address

或者是如果启动的时候报错:

Missing privilege separation directory: /run/sshd

解决办法:

$ mkdir /run/sshd

查看一下进程:

$ ps -e | grep ssh

out:
 4320 ?        00:00:00 sshd

进程存在,再次启动就会成功。

然后保存一个tag

$ docker commit -m "base" 3f912011817b ubuntu:base

和git类似,3f912011817b是主机名,当然,只有在uname没有被修改的情况下生效。ubuntu是仓库名。base是TAG名 。

配置JAVA环境

看我之前的关于JDK的详细配置,我这里就简单说一下而已。

启动之前保存的那个版本:

我是去官方网站下载到虚拟机的/soft/文件夹下,然后把这个文件夹映射到容器中去。所以使用下面这条命令。

$ docker run -v /soft/:/soft -ti ubuntu:base

安装

在linux的目录中
首先创建一个装java的文件夹

$ mkdir /software

然后解压搭配这个目录

tar -zxvf ./jdk-8u201-linux-x64.tar.gz -C /software/

配置环境变量

/etc/profile文件中的最后位置填入如下信息(按i编辑,Esc+:wq 退出)

export JAVA_HOME=/software/jdk1.8.0_201
export JRE_HOME=/software/jdk1.8.0_201/jre
export CLASSPATH=.:$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH
export PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$PATH

保存退出

环境永久生效

$ source /etc/profile

验证成功

java -version

出现如下信息:

java version "1.8.0_201"
Java(TM) SE Runtime Environment (build 1.8.0_201-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.201-b09, mixed mode)

则成功!!!

建议也保存一下提交一下容器。

配置Hadoop

这里有我之前在Centos下位置的一个全分布集群的博客,很详细,可以参考一下:CentOS7部署Hadoop2.7.5全分布式群集

也是和java一样在宿主机下载好了,传入向虚拟机,然后映射到容器里面去的。因为无论是虚拟机,或者是容器里面使用wget下载,网速都是很慢的。

解压到和JAVA一个文件夹去,当然也可以自己放到自己喜欢的文件夹。

$ tar -zxvf /soft/hadoop-2.8.5.tar.gz -C /software/

配置Hadoop的环境变量

编辑/etc/profile文件,在最后添加如下内容

export HADOOP_HOME=/software/hadoop-2.8.5
export HADOOP_CONFIG_HOME=$HADOOP_HOME/etc/hadoop
export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin

保存退出
然后使其生效

$ source /etc/profile

配置hadoop-env.sh文件

配置hadoop-env.sh文件,使hadoop的java路径生效,找到并吧{$JAVA_HOME}改成绝对路径。

$ vim /software/hadoop-2.8.5/etc/hadoop/hadoop-env.sh 
# The java implementation to use.
export JAVA_HOME=/software/jdk1.8.0_201

这样单机版的hadoop就算是安装完成。
可以检验一下

$ hadoop version

出现如下信息则是成功的。

Hadoop 2.8.5
Subversion https://git-wip-us.apache.org/repos/asf/hadoop.git -r 0b8464d75227fcee2c6e7f2410377b3d53d3d5f8
Compiled by jdu on 2018-09-10T03:32Z
Compiled with protoc 2.5.0
From source with checksum 9942ca5c745417c14e318835f420733
This command was run using /software/hadoop-2.8.5/share/hadoop/common/hadoop-common-2.8.5.jar

创建三个目录,后续配置的时候会用到:

  • tmp:作为Hadoop的临时目录
  • namenode:作为NameNode的存放目录
  • datanode:作为DataNode的存放目录
$ mkdir tmp
$ mkdir namenode
$ mkdir datanode

配置Hadoop文件

  1. core-site.xml
  2. hdfs-site.xml
  3. mapred-site.xml
  4. yarn-site.xml
  5. slaves

进入hadoop的home目录
配置./etc/hadoop/core-site.xml

<configuration>
        <property>
                <name>fs.defaultFS</name>
                <value>hdfs://ns1</value>
        </property>
        <!-- configuration hdfs Temporary data storage directory -->
        <property>
                <name>hadoop.tmp.dir</name>
                <value>/software/hadoop-2.8.5/tmp</value>
        </property>
        <property>
                <name>ha.zookeeper.quorum</name>
                <value>cloud4:2181,cloud5:2181,cloud6:2181</value>
        </property>
</configuration>

配置./etc/hadoop/hdfs-site.xml

<configuration>
        <property>
                <name>dfs.nameservices</name>
                <value>ns1</value>
        </property>
        <property>
                <name>dfs.ha.namenodes.ns1</name>
                <value>nn1,nn2</value>
        </property>
        <property>
                <name>dfs.namenode.rpc-address.ns1.nn1</name>
                <value>cloud1:9000</value>
        </property>
        <property>
                <name>dfs.namenode.http-address.ns1.nn1</name>
                <value>cloud1:50070</value>
        </property>
        <property>
                <name>dfs.namenode.rpc-address.ns1.nn2</name>
                <value>cloud2:9000</value>
        </property>
        <property>
                <name>dfs.namenode.http-address.ns1.nn2</name>
                <value>ns1</value>
        </property>
        <property>
                <name>dfs.ha.namenodes.ns1</name>
                <value>nn1,nn2</value>
        </property>
        <property>
                <name>dfs.namenode.rpc-address.ns1.nn1</name>
                <value>cloud1:9000</value>
        </property>
        <property>
                <name>dfs.namenode.http-address.ns1.nn1</name>
                <value>cloud1:50070</value>
        </property>
        <property>
                <name>dfs.namenode.rpc-address.ns1.nn2</name>
                <value>cloud2:9000</value>
        </property>
        <property>
                <name>dfs.namenode.http-address.ns1.nn2</name>
                <value>cloud2:50070</value>
        </property>
        <property>
                <name>dfs.namenode.shared.edits.dir</name>
                <value>qjournal://cloud4:8485;cloud5:8485;cloud6:8485/ns1</value>
        </property>
        <property>
                <name>dfs.journalnode.edits.dir</name>
                <value>/software/hadoop-2.8.5/journal</value>
        </property>
        <property>
                <name>dfs.ha.automatic-failover.enabled</name>
                <value>true</value>
        </property>
        <property>
                <name>dfs.client.failover.proxy.provider.ns1</name>
                <value>
                        org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider
                </value>
        </property>
        <property>
                <name>dfs.ha.fencing.methods</name>
                <value>
                        sshfence
                        shell(/bin/true)
                </value>
        </property>
        <property>
                <name>dfs.ha.fencing.ssh.private-key-files</name>
                <value>/root/.ssh/id_rsa</value>
        </property>
        <property>
                <name>dfs.ha.fencing.ssh.connect-timeout</name>
                <value>30000</value>
        </property>
</configuration>

配置./etc/hadoop/mapred-site.xml

$ cp ./etc/hadoop/mapred-site.xml.template etc/hadoop/mapred-site.xml 
$ vim ./etc/hadoop/mapred-site.xml

填入如下信息:

<configuration>
        <property>
                <name>mapreduce.framework.name</name>
                <value>yarn</value>
                <final>true</final>
        </property>
        <property>
                <name>yarn.resourcemanager.hostname</name>
                <value>cloud3</value>
        </property>
        <property>
                <name>yarn.nodemanager.aux-services</name>
                <value>mapreduce_shuffle</value>
        </property>
</configuration>

配置./etc/hadoop/yarn-site.xml

<configuration>

<!-- Site specific YARN configuration properties -->
        <property>
                <name>yarn.resourcemanager.hostname</name>
                <value>cloud3</value>
        </property>

        <property>
                <name>yarn.nodemanager.aux-services</name>
                <value>mapreduce_shuffle</value>
        </property>
</configuration>

配置./etc/hadoop/slaves

cloud1
cloud2
cloud3
cloud4
cloud5
cloud6

配置Zookeeper

解压安装

tar -zxvf /soft/zookeeper-3.4.13.tar.gz -C /software/

修改文件

cp ./conf/zoo_sample.cfg ./conf/zoo.cfg

编辑刚刚修改的文件

dataDir=/software/zookeeper-3.4.13/tmp 
server.1=cloud4:2888:3888
server.2=cloud5:2888:3888
server.3=cloud6:2888:3888                

然后回到Zookeeper目录

mkdir tmp
cd tmp
touch myid
echo 1 > myid 

myid的位置

/software/zookeeper-3.4.13/tmp/myid

myid 文件中保存的数字代表本机的zkServer编号 在此设置master为编号为1的zkServer,之后生成slave1和slave2之后还需要分别修改此文件

/etc/profile中添加环境变量

export ZOOKEEPER_HOME=/software/zookeeper-3.4.13
export PATH=$PATH:$ZOOKEEPER_HOME/bin

安装SCALA

解压

tar -zxvf /soft/scala-2.12.8.tgz  -C /software/

配置环境变量

export SCALA_HOME=/software/scala-2.12.8
export PATH=$PATH:$SCALA_HOME/bin

安装SPARK

解压安装

tar -zxvf /soft/spark-2.4.0-bin-hadoop2.7.tgz -C /software/

添加:

export SPARK_HOME=/software/spark-2.4.0-bin-hadoop2.7
export PATH=$PATH:$SPARK_HOME/bin:$SPARK_HOME/sbin

配置SPARK

复制spark-env.sh.template文件为spark-env.sh
进入SPARK安装目录

cd $SPARK_HOME
cp ./conf/spark-env.sh.template ./conf/spark-env.sh

然后编辑spark-env.sh

export SPARK_MASTER_IP=cloud1
export SPARK_WORKER_MEMORY=128m
export JAVA_HOME=/software/jdk1.8.0_201
export SCALA_HOME=/software/scala-2.12.8
export SPARK_HOME=/software/spark-2.4.0-bin-hadoop2.7
export HADOOP_CONF_DIR=/software/hadoop-2.8.5/etc/hadoop
export SPARK_LIBRARY_PATH=$SPARK_HOME/lib 
export SCALA_LIBRARY_PATH=$SPARK_LIBRARY_PATH
export SPARK_WORKER_CORES=1
export SPARK_WORKER_INSTANCES=1
export SPARK_MASTER_PORT=7077

貌似配置文件放在/etc/profile里面每次还需要自己source一下,所以我直接复制一份全部的环境变量到~/.bashrc,包括之后添加的软件,这是我配置的所有环境。

# mysetting

# JAVA and JRE
export JAVA_HOME=/software/jdk1.8.0_201
export JRE_HOME=/software/jdk1.8.0_201/jre
export CLASSPATH=.:$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH
export PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin

# HADOOP
export HADOOP_HOME=/software/hadoop-2.8.5
export HADOOP_CONFIG_HOME=$HADOOP_HOME/etc/hadoop
export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin

# ZOOKEEPER
export ZOOKEEPER_HOME=/software/zookeeper-3.4.13
export PATH=$PATH:$ZOOKEEPER_HOME/bin

# SCALA
export SCALA_HOME=/software/scala-2.12.8
export PATH=$PATH:$SCALA_HOME/bin


# SPARK
export SPARK_HOME=/software/spark-2.4.0-bin-hadoop2.7
export PATH=$PATH:$SPARK_HOME/bin:$SPARK_HOME/sbin
在这里插入图片描述

这里得一段落,把这些配置生成一个镜像

这里我们将安装好ZookeeperHadoppSparkScala 的镜像保存在另一个仓库为一个副本

$ docker commit c4018f6e20e9
# sha256:190c26ac384acc8b35d50d2a518bb7731a9b9c95ff0e7448df4bd2a32db6e849 #这个是一段返回的ID也可以直接一个语句提交。
$ docker tag 190c26ac384acc8b35d50d2a518bb7731a9b9c95ff0e7448df4bd2a32db6e849 spark:1.0

查看我自己本地的镜像:

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
spark               1.0                 190c26ac384a        52 seconds ago      1.72GB
ubuntu              hadoop              b0689e83fc45        38 hours ago        1.32GB
ubuntu              base_java           a9130b9f2e02        2 days ago          661MB
ubuntu              base                6239b1a96048        5 days ago          264MB
ubuntu              18.04               47b19964fb50        4 weeks ago         88.1MB

启动集群

-h指定容器运行起来后的hostname

docker run --name cloud1 -h cloud1 -ti spark:1.0
docker run --name cloud2 -h cloud2 -ti spark:1.0
docker run --name cloud3 -h cloud3 -ti spark:1.0
docker run --name cloud4 -h cloud4 -ti spark:1.0
docker run --name cloud5 -h cloud5 -ti spark:1.0
docker run --name cloud6 -h cloud6 -ti spark:1.0

看一下有没有全部在运行:

docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
6e90a37656b6        spark:1.0           "/bin/bash"         4 minutes ago       Up 4 minutes                            cloud6
87d84707881a        spark:1.0           "/bin/bash"         17 minutes ago      Up 6 minutes                            cloud5
77cbf52e815d        spark:1.0           "/bin/bash"         19 minutes ago      Up 6 minutes                            cloud4
a8e17bc22208        spark:1.0           "/bin/bash"         23 minutes ago      Up 6 minutes                            cloud3
bd41c4730004        spark:1.0           "/bin/bash"         23 minutes ago      Up 6 minutes                            cloud2
67b87858e847        spark:1.0           "/bin/bash"         25 minutes ago      Up 7 minutes                            cloud1

进入一个正在启动的容器

docker exec -ti 67b87858e847 /bin/bash

在cloud5、cloud6分别做如下操作

echo 2 > /software/zookeeper-3.4.13/tmp/myid # cloud5

echo 3 > /software/zookeeper-3.4.13/tmp/myid # cloud6

使用ifconfig查看ip地址,如果现实没有命令则安装sudo apt-get install net-tools,并写入/etc/hosts

172.17.0.2      cloud1
172.17.0.3      cloud2
172.17.0.4      cloud3
172.17.0.5      cloud4
172.17.0.6      cloud5
172.17.0.7      cloud6

然后通过scp传输到另外五个容器里面去

scp /etc/hosts cloud6:/etc/hosts

启动Zookeeper

分别在cloud4、cloud5、cloud6上启动zk

$ cd $ZOOKEEPER_HOME
$ ./bin/zkServer.sh start

使用status查看是否启动

./bin/zkServer.sh status

cloud5leadercloud4cloud6时候follower

启动journalnode(在cloud1上启动所有journalnode,注意:是调用的hadoop-daemons.sh这个脚本,注意是复数s的那个脚本)
运行jps命令检验,cloud4、cloud5、cloud6上多了JournalNode进程

cd $HADOOP_HOME
./sbin/hadoop-daemons.sh start journalnode

格式化HDFS和格式化ZK

cloud1上执行命令:

cd $HADOOP_HOME
./bin/hdfs namenode -format
./bin/hdfs zkfc -formatZK

如果没有报错,则成功。格式化的时候报错也很好找的

启动HDFS

cloud1HADOOP_HOME上进行:

./sbin/start-dfs.sh

cloud3上执行start-yarn.sh

./sbin/start-yarn.sh

启动spark集群

cloud1

./sbin/start-all.sh

登录web管理台来查看运行状况

HDFS:cloud1:50070 
YARN:cloud3:8088 
SPARK:cloud1:8080 

如果宿主机中的hosts文件没有配置docker容器的主机名和IP地址映射关系的话要换成用IP访问

cloud4/5/6其中一个,将hadoop目录下的journal复制到cloud1

scp -r /software/hadoop-2.8.5/journal cloud1:/software/hadoop-2.8.5/

将完成所有配置的cloud1 commit成一个镜像

docker commit -m "base sparks" cloud1 spark:2.0

往后的时候直接用这个镜像运行容器,分别启动zookeeper,hadoop,spark就行了

退出的时候建议使用命令停止服务再退出。要不然下次启动可能会报错。


常用命令

命令描述
docker images查看镜像
docker ps查看容器
docker ps -a查看所有容器,包括没有运行的
docker rm删除容器
docker rmi删除镜像
docker build新建镜像
docker run运行容器
docker stop停止容器
Ctrl+P+Q退出容器后台运行(不会关闭)
docker start启动容器(停止的)
docker exec进入容器(在运行)
docker logs查看日志
docker load导入镜像
docker save导出镜像
docker commit容器生成镜像
systemctl start docker启动
systemctl restart docker重启
systemctl stop docker停止
systemctl status docker查看状态
systemctl enable docker自启动
systemctl disable docker禁止自启动

写这篇博客的时候的时间跨度很多天,可能有点的写得不详细。如果有看到不正确的地方请多多指正,谢谢大家!

这也是我毕业设计的基础环境。当时为了毕业设计又一边写文章,可能会遗漏很多东西。

相关文章

发表回复

您的电子邮箱地址不会被公开。