使用docker部署hadoop分布式集群

前言

这个部署是去年做的,有点久了,镜像上传在dockerhub,想了想,还是写下来,万一哪天有用,可以回顾一下。关于docker的一些内容,后序会写一些,碍于目前生产环境的限制,能做的不会太多,但更多的是熟练docker。hadoop呢,以前读书的时候,断断续续地研究过一段时间,然后就没然后了,事情太多太杂,而自身精力涣散,三天打鱼两天晒网,实际也就没弄明白什么。平时读点博客,看到docker,hadoop等字眼就会不住高潮,内心想说这玩意我玩过啊,然后也就仅限于此了。术业有专攻,如果不是经常接触,搞不久就会忘,若时常回顾一下,等到用时,就不会那么陌生了。

安装docker

安装docker的套路网上有教程,目前新的Ubuntu系统都有集成,不过OSX系统跑docker需要配合虚拟机如Virtualbox等来做,所以mac用户要稍微折腾一下了。本文的环境是在Ubuntu 14下做的,大致命令如下:

$ sudo apt-get install apt-transport-https 
$ sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 36A1D7869245C8950F966E92D8576A8BA88D21E9
$ sudo bash -c "echo deb https://get.docker.io/ubuntu docker main > /etc/apt/sources.list.d/docker.list"
$ sudo apt-get update
$ sudo apt-get install lxc-docker

docker的安装可以参考这个
接下来要提到的是docker仓库的概念,熟悉github或使用过svn的都应该知道代码库吧,而我们也可以为docker创建仓库,这个库即是存放docker镜像的场所。比如我们做了个装有JDK的docker镜像,那么就可以将其存到仓库里,每次需要使用带Java的环境时,就可以可以使用该镜像,并在此基础上构建其它镜像。国内比较知名的docker库如dockerpool,而我此次使用的是dockerhub,国内访问剧慢,最好使用vpn加速。建议养成使用仓库的习惯,无论是代码还是docker。怎么使用docker仓库呢,首先需要在dockerhub官网创建一个账户,创建自己的仓库,然后在你的生产环境登陆dockerhub,即可从dockerhub上pull(拉取)镜像,当然也可以将本地的镜像push(上传)到仓库。大致流程可参考此文
登录到DockerHub:

$ docker login --username=账户 --email=邮箱@xxx.com
PassWord:
WARNING: login credentials saved in /home/hadoop/.docker/config.json
Login Succeeded

搞定仓库设置后,那么就可以从docker仓库中获取Ubuntu镜像了:

docker pull ubuntu:14.04

使用docker images可以查看本地的所有镜像:

hadoop@hadoop:~$ docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
liushy/ubuntu hadoop 358d6e31872e 13 months ago 1.276 GB
liushy/ubuntu java 50d62690f3f0 13 months ago 752.9 MB
ubuntu 14.04 e9ae3c220b23 13 months ago 187.9 MB

显示的内容包括:

REPOSITORY:仓库名,例如liushy/ubuntu和ubuntu
TAG:标记,例如hadoop
IMAGE ID:镜像ID号,这是唯一的
CREATED:创建时间
SIZE:镜像大小

那么,除此之外,还需要了解docker的一些常用操作。

启动Docker容器

启动docker容器,就可以构建部署hadoop集群了。使用如下命令启动docker容器:

docker run -ti ubuntu

docker run -ti ubuntu命令中没有指定执行程序,Docker默认执行/bin/bash。如下面这条命令:

hadoop@hadoop:~$  docker run liushy/ubuntu:java /bin/echo 'Hello world'
Hello world

即是启动标记为java的镜像,运行bash打印“Hello world”。
接下来我们在Ubuntu基础镜像的上,安装Java,执行如下命令:

root@50d62690f3f0:~#sudo apt-get install software-properties-common python-software-properties
root@50d62690f3f0:~#sudo add-apt-repository ppa:webupd8team/java
root@50d62690f3f0:~#sudo apt-get update
root@50d62690f3f0:~#sudo apt-get install oracle-java7-installer

安装结束后,可以将该镜像保存,以备以后使用:

root@50d62690f3f0:~# exit
docker commit -m "java image" 50d62690f3f0 liushy/ubuntu:java

-m后面指定提交说明,50d62690f3f0是容器ID(也可以通过docker ps查询运行的容器),liushy/ubuntu是仓库,:java是标记。

构建Hadoop镜像

首先启动Java容器的镜像,下载Hadoop,输入如下命令:

hadoop@hadoop:~$ docker run -ti liushy/ubuntu:java
root@7cf73e2147ec:/#
root@7cf73e2147ec:cd ~
root@7cf73e2147ec:~# mkdir soft
root@7cf73e2147ec:~# cd soft/
root@7cf73e2147ec:~/soft# mkdir apache
root@7cf73e2147ec:~/soft# cd apache/
root@7cf73e2147ec:~/soft/apache# mkdir hadoop
root@7cf73e2147ec:~/soft/apache# cd hadoop/
root@7cf73e2147ec:~/soft/apache/hadoop# wget http://mirrors.sonic.net/apache/hadoop/common/hadoop-2.6.0/hadoop-2.6.0.tar.gz
root@7cf73e2147ec:~/soft/apache/hadoop# tar xvzf hadoop-2.6.0.tar.gz

本次安装的是hadoop-2.6.0版的。

配置环境

还需要配置环境变量,在~/.bashrc添加java和hadoop文件路径:

root@7cf73e2147ec:vi ~/.bashrc
export JAVA_HOME=/usr/lib/jvm/java-7-oracle
export HADOOP_HOME=/root/soft/apache/hadoop/hadoop-2.6.0
export HADOOP_CONFIG_HOME=$HADOOP_HOME/etc/hadoop
export PATH=$PATH:$HADOOP_HOME/bin
export PATH=$PATH:$HADOOP_HOME/sbin

最后,一定记得要source ~/.bashrc使配置生效。

配置Hadoop

部署分布式的hadoop,主要分为两大角色:Master和Slave。从HDFS的角度,由若干个NameNode和DataNode组成(在分布式文件系统中,NameNode管理文件系统的命名空间,DataNode管理存储的数据);从MapReduce的角度,将主机划分JobTracker 和TaskTracker(主节点的Job分配多个Task给从节点执行)。HDFS在集群上实现分布式文件系统,MapReduce在集群上实现了分布式计算和任务处理。HDFS在MapReduce任务处理过程中提供了文件操作和存储等支持,MapReduce在HDFS的基础上实现了任务的分发、跟踪、执行等工作,并收集结果,二者相互作用,完成了Hadoop分布式集群的主要任务参考

部署hadoop的各个节点,需要修改hadoop的配置文件,包括core-site.xml、hdfs-site.xml、mapred-site.xml这三个文件。在此之前,建议新建如下目录:

  • tmp:作为Hadoop的临时目录
  • namenode:作为NameNode的存放目录
  • datanode:作为DataNode的存放目录
    root@7cf73e2147ec:~# cd $HADOOP_HOME/
    root@7cf73e2147ec:~/soft/apache/hadoop/hadoop-2.6.0# mkdir tmp
    root@7cf73e2147ec:~/soft/apache/hadoop/hadoop-2.6.0# cd tmp/
    root@7cf73e2147ec:~/soft/apache/hadoop/hadoop-2.6.0/tmp# cd ../
    root@7cf73e2147ec:~/soft/apache/hadoop/hadoop-2.6.0# mkdir namenode
    root@7cf73e2147ec:~/soft/apache/hadoop/hadoop-2.6.0# cd namenode/
    root@7cf73e2147ec:~/soft/apache/hadoop/hadoop-2.6.0/namenode# cd ../
    root@7cf73e2147ec:~/soft/apache/hadoop/hadoop-2.6.0# mkdir datanode
    root@7cf73e2147ec:~/soft/apache/hadoop/hadoop-2.6.0# cd datanode/
    root@7cf73e2147ec::~/soft/apache/hadoop/hadoop-2.6.0/datanode# cd $HADOOP_CONFIG_HOME/
    root@7cf73e2147ec:~/soft/apache/hadoop/hadoop-2.6.0/etc/hadoop# cp mapred-site.xml.template mapred-site.xml

接下来就是对上述几个文件进行配置

core-site.xml配置

<configuration>
<property>
<name>hadoop.tmp.dir</name>
<value>/root/soft/apache/hadoop/hadoop-2.6.0/tmp</value>
<description>A base for other temporary directories.</description>
</property>
<property>
<name>fs.default.name</name>
<value>hdfs://master:9000</value>
<final>true</final>
<description>xxxxxx.</description>
</property>
</configuration>
  • hadoop.tmp.dir:配置为/root/soft/apache/hadoop/hadoop-2.6.0/tmp为此前创建的临时目录
  • fs.default.name:配置为hdfs://master:9000,指向Master节点

hdfs-site.xml配置

<configuration>
<property>
<name>dfs.replication</name>
<value>2</value>
<final>true</final>
<description>xxxxx.</description>
</property>
<property>
<name>dfs.namenode.name.dir</name>
<value>/root/soft/apache/hadoop/hadoop-2.6.0/namenode</value>
<final>true</final>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>/root/soft/apache/hadoop/hadoop-2.6.0/datanode</value>
<final>true</final>
</property>
</configuration>
  • dfs.replication:配置为2。指集群为一个Master节点和两个Slave节点。
  • dfs.namenode.name.dir:配置为此前创建的NameNode目录
  • dfs.datanode.data.dir:配置为此前创建的NaDataNode目录

mapred-site.xml配置

<configuration>
<property>
<name>mapred.job.tracker</name>
<value>master:9001</value>
<description>xxxxxx.</description>
</property>
</configuration>
  • mapred.job.tracker:配置jobTracker在master节点

除此之外,还要配置conf/hadoop-env.sh文件,修改为你的jdk的安装位置:

export JAVA_HOME=/usr/lib/jvm/java-7-oracle

还要格式化Namenode:hadoop namenode -format

节点SSH互访

Hadoop启动以后,Namenode是通过SSH来启动和停止各个Datanode上的守护进程的,要求在节点之间执行指令的时候是不需要输入密码,故我们要配置SSH运用无密码公钥认证的形式。
首先,安装SSH:

root@7cf73e2147ec:~# sudo apt-get install ssh
root@7cf73e2147ec:~# ssh localhost

利用ssh localhost测试一下是否设置好无口令登陆,如果没有设置好,系统将要求你输入密码,通过下面的设置可以实现无口令登陆:

root@7cf73e2147ec:~# ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa
root@7cf73e2147ec:~# cat ~/.ssh/id_dsa.pub >> ~/.ssh/authorized_keys

最后,保存一份镜像:

root@7cf73e2147ec:~# exit
hadoop@hadoop:~$ docker commit -m "hadoop image" 358d6e31872e liushy/ubuntu:hadoop

启动Hadoop集群

接下来就是启动hadoop集群了,本次部署的hadoop方案是,一个Master节点,两个Slave节点:

______________________________________________    
| Master | 172.17.0.2 | Namenode,jobTracker |
| Slave1 | 172.17.0.3 | Datanode,taskTracker |
| Slave2 | 172.17.0.4 | Datanode,taskTracker |

启动容器使用如下命令:
docker run -ti -h master liushy/ubuntu:hadoop
docker run -ti -h slave1 liushy/ubuntu:hadoop
docker run -ti -h slave2 liushy/ubuntu:hadoop
其中,-h指定的是容器的主机名,比如master slave1 slave2
容器启动成功后,docker会为它们自动分配ip地址,是同一网段相互之间能够ping通,在容器中输入ifconfig查看。当然也可以修改ip,方法请自行百度。

修改hosts

接下来修改各节点的hosts文件vi /etc/hosts,添加各节点的hostname和ip:

172.17.0.2        master
172.17.0.3 slave1
172.17.0.4 slave2

修改slaves

除此之外,还要在master节点上,配置slaves文件,该文件需要填写slave节点的hostname:

root@master:~# cd $HADOOP_CONFIG_HOME/
root@master:~/soft/apache/hadoop/hadoop-2.6.0/etc/hadoop# vi slaves
slave1
slave2

启动Hadoop

在Master节点的hadoop目录下执行start-all.sh,启动Hadoop集群:

root@master:~/soft/apache/hadoop/hadoop-2.6.0/etc/hadoop# start-all.sh 
This script is Deprecated. Instead use start-dfs.sh and start-yarn.sh
starting secondarynamenode, logging to /root/soft/apache/hadoop/hadoop-2.6.0/logs/hadoop-root-secondarynamenode-master.out
starting yarn daemons
...
0.0.0.0:starting resourcemanager, logging to /root/soft/apache/hadoop/hadoop-2.6.0/logs/yarn--resourcemanager-master.out
slave2: starting nodemanager, logging to /root/soft/apache/hadoop/hadoop-2.6.0/logs/yarn-root-nodemanager-slave2.out
slave1: starting nodemanager, logging to /root/soft/apache/hadoop/hadoop-2.6.0/logs/yarn-root-nodemanager-slave1.out

打印上述日志,说明集群运行成功,碍于生产环境,运行较慢,可以多等等。使用jps命令可以查看各节点运行的进程。

master节点:

root@master:~/soft/apache/hadoop/hadoop-2.6.0/etc/hadoop# jps
492 Jps
429 ResourceManager
295 SecondaryNameNode
124 NameNode

slave1节点:

root@slave1:/# jps
52 DataNode
147 NodeManager
240 Jps

slave2节点:

root@slave2:/# jps
50 DataNode
121 NodeManager
250 Jps

通过web访问hadoop运行情况:

hadoop
针对hadoop的架构和操作此文就不深入阐述了。

结语

搭建环境是一件费时耗力,低效率的事情,搞不好就各种排错,甚至重来,这也是很多人不想接触环境的原因。如何做到少出错,快速定位问题,我想这也是很多正在搞环境的开发人员所渴望的一种工作状态。其实,没有什么捷径可走,还是要多积累,但有些事情必须得长期坚持,那就是学习操作系统,内存管理,网络等相关知识。很多疑难杂症多因环境变量的配置,硬盘故障,网络不通等引起,而我们往往因为对这些知识不熟悉,而手足无措。

回到本文的主题,docker是这两年势头正旺的开源产品,基于lxc(linux container)使得应用部署更加轻量。如何将其运用于开发环境中,很多互联网公司都在做。作为开发人员来说,掌握容器也是一门专业利器,基于容器结合应用可以实现大规模的业务部署,比如本文的hadoop。当然相比虚拟机,docker也有缺陷,比如隔离性差,所以如何运用docker来保障处理业务的安全稳定,是开发人员需要通过实践来解决的问题。

参考网站
http://blog.chinaunix.net/uid-25266990-id-3900239.html
http://blog.csdn.net/u011692203/article/details/46898293
http://www.cnblogs.com/xiaoluosun/p/5520510.html
http://tashan10.com/yong-dockerda-jian-hadoopwei-fen-bu-shi-ji-qun/

个人分析,欢迎指正,若转载请注明出处!