zl程序教程

您现在的位置是:首页 >  工具

当前栏目

使用Docker在本地搭建hadoop,spark集群

Dockerhadoop集群Spark 搭建 本地 使用
2023-09-27 14:21:25 时间

本环境使用的单个宿主主机,而不是跨主机集群,本spark集群环境存在的意义可能在于便于本地开发测试使用,非常轻量级和便捷。这个部署过程,最好在之前有过一定的hadoop,spark集群部署经验的基础,本文重点在于docker相关的操作,至于hadoop和spark集群的部署,极力推荐这两个网页:

Hadoop集群:http://blog.csdn.net/stark_sum ... 24279。

Spark集群:http://blog.csdn.net/stark_sum ... 58081

主机系统:ubuntu14.04,64位,内存4G,主机名docker。(实际上是在虚拟机上安装的)

软件版本:hadoop-2.6.0,jdk1.7.0_79,scala-2.10.5,spark-1.2.0-bin-hadoop2.4,docker版本:1.9.1,镜像:ubuntu14.04。

搭建环境前调研结果描述:

目前网上在docker上部署spark的介绍比较简单和没有相关启动使用的操作,部署大致分为两类情况:

1. 直接在docker仓库pull下来。这个方法我尝试了一下,不建议使用,首先下载镜像比较大,2G多,其次下载之后貌似只能单机启动,也就是伪分布式,并不是集群(我自己没有实际使用过,看到的相关资料是这样说的)。如下sequenceiq/spark:1.2.0这个镜像:

REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE

sequenceiq/spark 1.2.0 334aabfef5f1 10 months ago 2.115 GB

2. 自己使用基础镜像搭建环境。本文采用这种方式,由于自己也是刚接触docker一个多月,还不会使用dockerfile,所以使用的是commit方式制作的集群。

具体部署过程

第一步,相关软件准备。

通过对spark源码当中docker文件夹的阅读得出的思路,利用数据卷共享数据。相关的集群软件都放在/opt目录下,目的是为后面启动集群的时候使用docker数据卷共享和永久保存数据,不会随着容器的删除而丢失。spark源码docker文件夹解读参考网页:http://blog.csdn.net/yunlong34 ... 33731

操作说明,直接把java等软件解压到/opt下,总共是四个,java,hadoop,scala,spark。不需要在宿主主机做任何修改,包括/etc/hosts,/etc/profile添加变量等,因为是在容器当中使用,宿主主机并不会用到。解压之后如下:


root@docker:/opt# ll  total 32  drwxr-xr-x 7 root root 4096 12月 22 22:12 ./  drwxr-xr-x 23 root root 4096 11月 30 19:35 ../  drwxr-xr-x 12 root root 4096 12月 22 22:07 hadoop-2.6.0/  drwxr-xr-x 8 root root 4096 4月 11 2015 jdk1.7.0_79/  drwxr-xr-x 9 root root 4096 12月 22 13:54 scala-2.10.5/  drwxrwxr-x 12 root root 4096 12月 22 22:19 spark-1.2.0-bin-hadoop2.4/ 

然后把hadoop和spark 的配置文件修改,这一步主要是靠之前的相关基础操作了,可以参考上面给出的两个网站修改配置文件,我是直接拷贝我之前集群的配置文件替换的,然后再结合后面的主机名,ip等行稍作修改就行了。如果之前没有部署过集群,这一步的工作量是相当大的。

需要特别注意的一点是hadoop的配置文件中的hdfs-sit.xml中的dfs.datanode.data.dir,这个也就是hdfs的datanode的文件夹,也是通过小技巧修改为file:/root/data,为什么这么修改后面有讲解,最终的想要的目的是通过链接文件,链接到数据卷/opt的hadoop目录里面,这样数据就能保存在容器之外了,不会随着容器的删除而丢失。修改如下:


dfs.datanode.data.dir  file:/root/data 

第二步,制作基础镜像。(主要工作)

本集群的思路是尽可能的减少额外的工作量,使用的是固定网络环境,这可能和docker本身的网络不固定性相悖,所以使用了一点小技巧修改的网络,这也是这个方法不能大规模使用的原因,也算是一个弊端吧。我看到有人使用动态的ip注册,我还没有理解到哪个地步,在后期的学习中再慢慢完善吧。节点容器主机名和ip规划如下:

主节点容器主机名hostname:node0,IP:172.17.0.150。

从节点容器主机名hostname:node1,IP:172.17.0.151。

从节点容器主机名hostname:node2,IP:172.17.0.152。

下面就开始一步一步的来设置:

1.查看镜像,使用ubuntu:14.04做为基础镜像,如果没有就pull一个吧。


root@docker:/opt# docker images  REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE  ubuntu 14.04 ca4d7b1b9a51 8 weeks ago 187.9 MB 

2.启动一个容器,安装vim和ssh。


root@docker:/opt# docker run -it ubuntu:14.04 /bin/bash  root@67f272584448:/# apt-get -y install vim openssh-server 

3.修改ssh配置文件,允许root登陆。


root@67f272584448:/# vim /etc/ssh/sshd_config 

找到:PermitRootLogin without-password

修改为:PermitRootLogin yes

4.生成ssh公钥,输入ssh-keygen,一直回车就行了。着里需要说明的是,三个节点的公钥都是一样的,为了简单起见而利用了小技巧。如果比较了解ssh的话,我说的这些相当于废话了,后面还会有涉及的。


root@67f272584448:/# ssh-keygen 

此时/root/.ssh文件夹里如下:


root@67f272584448:/# ls /root/.ssh/  id_rsa id_rsa.pub  root@67f272584448:/# cat /root/.ssh/id_rsa.pub   /root/.ssh/authorized_keys  root@67f272584448:/# ls /root/.ssh/  authorized_keys id_rsa id_rsa.pub 

5.下面开始关键步骤了。

把需要的变量写入/root/.bashrc,为什么不写入/etc/profile呢,因为我试了一下,写入/etc/proflie生成镜像启动容器的时候变量不能生效。

看到这里,相信下面的变量都是很熟悉吧:


export JAVA_HOME=/opt/jdk1.7.0_79  export CLASSPATH=.:/opt/jdk1.7.0_79/lib/dt.jar:/opt/jdk1.7.0_79/lib/tools.jar  export HADOOP_HOME=/opt/hadoop-2.6.0  export SCALA_HOME=/opt/scala-2.10.5  export SPARK_HOME=/opt/spark-1.2.0-bin-hadoop2.4  export PATH=$JAVA_HOME/bin:$PATH:$SCALA_HOME/bin:$SPARK_HOME/bin 

6.这个是最后一步了,在/root下新建一个run.sh脚本,对容器所做的修改,全部写入这个脚本了,先把脚本贴出来,再解释吧。


1 #!/bin/bash  3 echo "172.17.0.150 node0"   /etc/hosts  4 echo "172.17.0.151 node1"   /etc/hosts  5 echo "172.17.0.152 node2"   /etc/hosts  7 case $HOSTNAME in  8 "node0")  9 ifconfig eth0 172.17.0.150  10 sed -i s/root@.*$/root@node0/g /root/.ssh/authorized_keys  11 ;;  12 "node1")  13 ifconfig eth0 172.17.0.151  14 sed -i s/root@.*$/root@node0/g /root/.ssh/authorized_keys  15 ln -s /opt/hadoop-2.6.0/dfs/node1 /root/data  16 ;;  17 "node2")  18 ifconfig eth0 172.17.0.152  19 sed -i s/root@.*$/root@node0/g /root/.ssh/authorized_keys  20 ln -s /opt/hadoop-2.6.0/dfs/node2 /root/data  21 ;;  22 *)  23 echo "null"  24 ;;  25 esac  27 /etc/init.d/ssh start -D 

1)3,4,5行,替换hosts。启动集群的时候,习惯性的喜欢使用主机名,而不是使用ip,所以做了这个修改。另一个原因是,容器在重启之后hosts和ip是会变化的,所以每次启动都要修改。

2)7到25行,是利用容器的主机名来做三个修改。

第一,修改主机的IP,也就是我们的三个节点都是固定ip的,这个命令需要privileged。 第二,设置ssh免登录,也就authorized_keys中最后一个字段root@......全部修改为root@node0,这样node0节点就能免登录到node1,node2,和自己node0。 第三,利用连接文件,把hdfs的数据保存到数据卷的相关目录,也就是保存到了容器之外。利用连接文件时一个技巧,hdfs的配置文件都是/root/data,实际上却保存到了不同的文件目录上去。在上面的hadoop的配置文件中做的一个特殊的修改dfs.datanode.data.dir,file:/root/data,这个是hdfs的实际存储数据的目录,通过软连接到数据卷目录,最终把数据保存在容器之外,这样当容器删除时,hdfs里面的数据并没有消失,新建容器就可以再次使用数据了。

3)27行,这个就是启动ssh的,关键的是-D这个参数,如果不加,启动容器的时候run -d容器就会停止,不会运行。

4)最后保存退出,再修改一下执行权限,退出容器


root@67f272584448:~# chmod 744 /root/run.sh  root@67f272584448:~# exit 

7.使用commit提交镜像吧。


root@docker:~/docker# docker commit 67 ubuntu:base-spark  35341d63645cb5c23f88a6f4ac51d1000dc4431646ac3a948bd9c9f171dcbeeb  root@docker:~/docker# docker images  REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE  ubuntu base-spark 35341d63645c 4 minutes ago 261.1 MB 

从上面可以看出,镜像只有260MB,是非常小的。

到此整个基础镜像就做好了,其中有可能出错的地方是,hadoop和spark的配置文件修改的问题,这里是无关docker知识的“准备工作”。

第三步,启动容器,启动集群,并测试。

最后这步是最最爽的时候了,一个命令,集群就启动起来了。

其实下面大部分的篇幅是在讲解我的思路,启动集群本身是很简单的hadoop,spark知识。

一、启动容器集群

我写了一个小脚本docker_start.sh,里面三行是启动三个容器的命令,先看一眼:


root@docker:~/docker# cat docker_start.sh  #!/bin/bash  docker run -d --name node0 -h node0 -v /opt:/opt --privileged ubuntu:base-spark /root/run.sh  docker run -d --name node1 -h node1 -v /opt:/opt --privileged ubuntu:base-spark /root/run.sh  docker run -d --name node2 -h node2 -v /opt:/opt --privileged ubuntu:base-spark /root/run.sh 

下面解释一下这个启动命令的各个参数:

1)-d这个命令能够成功执行的原因是run.sh这个脚本的/etc/init.d/ssh start -D这一行的-D这个参数,容器才能成功后台up。

2)--name node0,这个是node0的容器名。

3)-h node0,这里的node0是容器主机名,也就是hostname。

4)-v /opt:/opt,就是数据卷,四个目录在这里java,hadoop,scala,spark,并且hdfs的数据存储目录在hadoop-2.6.0目录里,dfs文件夹里有三个目录,最好手动提前新建name,node1和node2,其实是可以写入run.sh脚本里面新建的,但是我已经不想回头去修改run.sh了。


root@docker:/opt/hadoop-2.6.0/dfs# pwd  /opt/hadoop-2.6.0/dfs  root@docker:/opt/hadoop-2.6.0/dfs# ls  name node1 node2 

name文件夹是hadoop的配置文件指定的:


dfs.namenode.name.dir  file:/opt/hadoop-2.6.0/dfs/name 

node1和node2是run.sh脚本通过连接文件过去的实际hdfs存储数据的目录:


dfs.datanode.data.dir  file:/root/data  ln -s /opt/hadoop-2.6.0/dfs/node1 /root/data  ln -s /opt/hadoop-2.6.0/dfs/node2 /root/data 

5)--privileged,这个参数是获得最高权限,才能够执行run.sh脚本里面的修改ip的命令。

ifconfig eth0 172.17.0.150

6)/root/run.sh,就是启动容器的时候,执行一下我们提前写好的脚本,对容器做一下修改了,虽然这些修改扭曲了docker的一些特性,不过对于我们这个本地的小环境来说,应该还是有点实际使用的价值的。

二、进入node0容器,启动并测试hdfs

其实,到这里,就已经差不多结束了,下面就是hadoop和spark的知识了

首先,先看一下启动的三个节点高兴一下吧


root@docker:~/docker# docker ps  CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES  7268b191b8fd ubuntu:base-spark "/root/run.sh" About an hour ago Up About an hour node2  acce5919ed63 ubuntu:base-spark "/root/run.sh" About an hour ago Up About an hour node1  6494f90e1ecc ubuntu:base-spark "/root/run.sh" About an hour ago Up About an hour node0 

进入node0容器


root@docker:/# docker exec -it node0 /bin/bash  root@node0:/# 

此时的容器都是已经做过修改的,可以参看以下相关的信息,比如,ifconfig,/etc/hosts,hostname,/root/.ssh/authorized_keys,等。

下面就启动hadoop的hdfs吧,因为这里只用到hdfs所以就不管yarn了,第一次启动hdfs先来个格式化,然后,还要输入若干个yes,这个yes是第一次ssh登陆的时候需要的,我就不贴出来格式化等相关的代码了。

然后就是启动hdfs:


root@node0:/# /opt/hadoop-2.6.0/sbin/start-dfs.sh 

输入jps查看一下node0上的进程


root@node0:/# jps  1310 Jps  843 NameNode  1025 SecondaryNameNode 

下面就可以使用hdfs了,可以向hdfs上传几个文件试试,也可以通过webUI浏览器看一下hdfs的情况,总而言之,就是hdfs的知识了,我就不废话了。

三,以standalone方式启动spark集群。

到这里直接启动spark进程就可以了:


root@node0:/# /opt/spark-1.2.0-bin-hadoop2.4/sbin/start-all.sh 

再次jps一下看看启动的情况


root@node0:/# jps  1532 Jps  843 NameNode  1025 SecondaryNameNode  1393 Master 

一切正常,就可以开始启动spark-shell进行测试了,以standalone方式启动:


root@node0:/# /opt/spark-1.2.0-bin-hadoop2.4/bin/spark-shell --master spark://node0:7077 

root@node0:/# /opt/spark-1.2.0-bin-hadoop2.4/bin/spark-shell --master spark://node0:7077

到这里也基本已经结束了,可以跑一个wordcount的例子,同样也可以使用webUI查看spark的情况。


本文作者:方圆小生

来源:51CTO


在idea里面怎么远程提交spark任务到yarn集群 很久没有更新了,因为最近一段时间有点小忙,最近也是有同学问我说自己在idea里面写spark程序测试,每次都要打包然后上传到集群,然后spark-submit提交很麻烦,可不可以在idea里面直接远程提交到yarn集群呢? 当然是可以的,今天就给大家分享一下具体的操作过程. 那先来说一下spark任务运行的几种模式: 1,本地模式,在idea里面写完代码直接运行.
Spark从入门到入土(一):集群环境搭建(下) Spark可以不依赖Hadoop运行。如果运行的结果(包括中间结果)不需要存储到HDFS,并且集群管理器不采用YARN的情况下是可以不依赖hadoop的。
Spark从入门到入土(一):集群环境搭建(上) Spark可以不依赖Hadoop运行。如果运行的结果(包括中间结果)不需要存储到HDFS,并且集群管理器不采用YARN的情况下是可以不依赖hadoop的。