学习Hadoop集群环境搭建是Hadoop入门必经之路。搭建分布式集群一般有两个办法:html
要么找多台机器来部署(经常找不到机器)java
或者在本地开多个虚拟机(开销很大,对宿主机器性能要求高,光是安装多个虚拟机系统就得搞半天……)。node
那么,问题来了!python
提到虚拟化,Docker最近非常火热!不妨拿来在本地作虚拟化,搭建Hadoop的伪分布式集群环境。虽然有点大材小用,可是学习学习,练练手也是极好的。git
文章比较长,建议先倒杯水,听我慢慢到来……web
先说一下个人思路吧:docker
先使用Docker构建一个Hadoop运行环境的镜像shell
而后使用这个镜像分别启动3个容器:1个Master节点,两个Slave节点express
在Master节点上配置Slave节点信息apache
在Master上启动Hadoop
Docker 是一个开源项目,诞生于 2013 年初,最初是 dotCloud 公司内部的一个业余项目。它基于 Google 公司推出的 Go 语言实现。 项目后来加入了 Linux 基金会,听从了 Apache 2.0 协议,项目代码在 GitHub 上进行维护。
Docker 自开源后受到普遍的关注和讨论,以致于 dotCloud 公司后来都更名为 Docker Inc。Redhat 已经在其 RHEL6.5 中集中支持 Docker;Google 也在其 PaaS 产品中普遍应用。
Docker 项目的目标是实现轻量级的操做系统虚拟化解决方案。 Docker 的基础是 Linux 容器(LXC)等技术。
在 LXC 的基础上 Docker 进行了进一步的封装,让用户不须要去关心容器的管理,使得操做更为简便。用户操做 Docker 的容器就像操做一个快速轻量级的虚拟机同样简单。
我使用的是Ubuntu14.04,命令以下:
$ 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 images
:列出全部镜像(images)
docker ps
:列出正在运行的(容器)containers
docker pull ubuntu
:下载镜像
docker run -i -t ubuntu /bin/bash
:运行ubuntu镜像
docker commit 3a09b2588478 ubuntu:mynewimage
:提交你的变动,而且把容器保存成Tag为mynewimage的新的ubuntu镜像.(注意,这里提交只是提交到本地仓库,相似git)
其余经常使用命令,参考这里。
在Ubuntu下,在执行Docker时,每次都要输入sudo,同时输入密码,这里把当前用户执行权限添加到相应的docker用户组里面。
# 添加一个新的docker用户组 sudo groupadd docker # 添加当前用户到docker用户组里,注意这里的king为ubuntu登陆用户名 sudo gpasswd -a king docker # 重启Docker后台监护进程 sudo service docker restart # 重启以后,尝试一下,是否生效 docker version #若还未生效,则系统重启,则生效 sudo reboot
docker pull ubuntu:14.04
这条命令的做用是从Docker仓库中获取ubuntu的镜像,参考这里。
下载完成之后,使用docker images
,能够列出全部本地的镜像:
king@king:~$ docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE ubuntu 14.04 5ba9dab47459 4 weeks ago 188.3 MB ubuntu 14.04.1 5ba9dab47459 4 weeks ago 188.3 MB ubuntu latest 5ba9dab47459 4 weeks ago 188.3 MB ubuntu trusty 5ba9dab47459 4 weeks ago 188.3 MB
下面,咱们准备以ubuntu镜像做为基准镜像,构建咱们的Hadoop运行环境镜像。
先使用命令以下命令启动容器:
docker run -ti ubuntu
注意:咱们在不指定Tag的状况下,默认选择Tag为latest
的镜像启动容器。 指定Tag启动命令为:
docker run -ti ubuntu:14.04
另外,每次容器启动的时候须要指定一个命令,容器启动后便会执行这个命令。例如执行下面的命令:
king@king:~$ docker run ubuntu /bin/echo 'Hello world' Hello world king@king:~$
能够看到,容器启动了立刻又退出了,由于容器之作了一件事情:就是打印Hello world
,打印完了,天然就退出了。
若是你想作多件事情,能够本身写一个shell脚本,把你要的操做写入进去,而后在run
后面指定这个脚本路径。
咱们刚刚的docker run -ti ubuntu
命令中没有指定执行程序,Docker默认执行/bin/bash
。
其余启动参数,你们能够本身在网上查,这里再也不陈述了。好了咱们回到刚刚docker run -ti ubuntu
启动的容器,能够看到容器几乎瞬间就启动起来了,比虚拟机不知快了多少倍!!
king@king:~$ docker run -ti ubuntu root@009fe5728aba:/#
容器启动起来了,接下来就是安装Java、Hadoop及相关配置了。
依次执行以下命令:
sudo apt-get install software-properties-common python-software-properties sudo add-apt-repository ppa:webupd8team/java sodu apt-get update apt-get install oracle-java7-installer java -version
注意:
这里安装的Java7(JDK1.7),如需其余版本请自行修改apt-get install oracle-java7-installer
为apt-get install oracle-java6-installer
默认使用的是Ubuntu的官方源,若是下载比较慢,请自行修改更新源,不知道如何使用命令行修改的,参考这里。
另外,你们能够将装好java的镜像保存为一个副本,他日能够在此基础上构建其余镜像。命令以下:
root@122a2cecdd14:~# exit docker commit -m "java install" 122a2cecdd14 ubuntu:java
上面命令中122a2cecdd14
为当前容器的ID, ubuntu:java
是为新的镜像指定一个标识,ubuntu
为仓库名,java
是Tag。
如何获取容器ID:
有个简便的办法找到此ID,就是命令行用户名@
后面的那一串字符。这个方法只在容器启动时没有指定hostname时才能用。
使用docker ps
列出全部运行的容器,在命令结果中查看
渐渐切入正题了O(∩_∩)O~
使用刚刚已经安装了Java的容器镜像启动:
docker run -ti ubuntu:java
启动成功了,咱们开始安装Hadoop。这里,咱们直接使用wget下载安装文件。
sudo apt-get install -y wget
root@8ef06706f88d:cd ~ root@8ef06706f88d:~# mkdir soft root@8ef06706f88d:~# cd soft/ root@8ef06706f88d:~/soft# mkdir apache root@8ef06706f88d:~/soft# cd apache/ root@8ef06706f88d:~/soft/apache# mkdir hadoop root@8ef06706f88d:~/soft/apache# cd hadoop/ root@8ef06706f88d:~/soft/apache/hadoop# wget http://mirrors.sonic.net/apache/hadoop/common/hadoop-2.6.0/hadoop-2.6.0.tar.gz root@8ef06706f88d:~/soft/apache/hadoop# tar xvzf hadoop-2.6.0.tar.gz
注意:这里咱们安装的Hadoop版本是2.6.0,若是须要其余版本,请在这里找到连接地址后修改命令便可。
修改~/.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
注意:咱们使用apt-get
安装java,不知道java装在什么地方的话可使用下面的命令查看:
root@8ef06706f88d:~# update-alternatives --config java There is only one alternative in link group java (providing /usr/bin/java): /usr/lib/jvm/java-7-oracle/jre/bin/java Nothing to configure. root@8ef06706f88d:~#
下面,咱们开始修改Hadoop的配置文件。主要配置core-site.xml、hdfs-site.xml、mapred-site.xml这三个文件。
开始配置以前,执行下面命令:
root@8ef06706f88d:~# cd $HADOOP_HOME/ root@8ef06706f88d:~/soft/apache/hadoop/hadoop-2.6.0# mkdir tmp root@8ef06706f88d:~/soft/apache/hadoop/hadoop-2.6.0# cd tmp/ root@8ef06706f88d:~/soft/apache/hadoop/hadoop-2.6.0/tmp# pwd /root/soft/apache/hadoop/hadoop-2.6.0/tmp root@8ef06706f88d:~/soft/apache/hadoop/hadoop-2.6.0/tmp# cd ../ root@8ef06706f88d:~/soft/apache/hadoop/hadoop-2.6.0# mkdir namenode root@8ef06706f88d:~/soft/apache/hadoop/hadoop-2.6.0# cd namenode/ root@8ef06706f88d:~/soft/apache/hadoop/hadoop-2.6.0/namenode# pwd /root/soft/apache/hadoop/hadoop-2.6.0/namenode root@8ef06706f88d:~/soft/apache/hadoop/hadoop-2.6.0/namenode# cd ../ root@8ef06706f88d:~/soft/apache/hadoop/hadoop-2.6.0# mkdir datanode root@8ef06706f88d:~/soft/apache/hadoop/hadoop-2.6.0# cd datanode/ root@8ef06706f88d:~/soft/apache/hadoop/hadoop-2.6.0/datanode# pwd /root/soft/apache/hadoop/hadoop-2.6.0/datanode root@8ef06706f88d:~/soft/apache/hadoop/hadoop-2.6.0/datanode# cd $HADOOP_CONFIG_HOME/ root@8ef06706f88d:~/soft/apache/hadoop/hadoop-2.6.0/etc/hadoop# cp mapred-site.xml.template mapred-site.xml root@8ef06706f88d:~/soft/apache/hadoop/hadoop-2.6.0/etc/hadoop# nano hdfs-site.xml
这里建立了三个目录,后续配置的时候会用到:
tmp:做为Hadoop的临时目录
namenode:做为NameNode的存放目录
datanode:做为DataNode的存放目录
<?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet type="text/xsl" href="configuration.xsl"?> <!-- Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. See accompanying LICENSE file. --> <!-- Put site-specific property overrides in this file. --> <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>The name of the default file system. A URI whose scheme and authority determine the FileSystem implementation. The uri's scheme determines the config property (fs.SCHEME.impl) naming the FileSystem implementation class. The uri's authority is used to determine the host, port, etc. for a filesystem.</description> </property> </configuration>
注意:
hadoop.tmp.dir
配置项值即为此前命令中建立的临时目录路径。
fs.default.name
配置为hdfs://master:9000
,指向的是一个Master节点的主机(后续咱们作集群配置的时候,天然会配置这个节点,先写在这里)
使用命令nano hdfs-site.xml
编辑hdfs-site.xml
文件:
<?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet type="text/xsl" href="configuration.xsl"?> <!-- Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. See accompanying LICENSE file. --> <!-- Put site-specific property overrides in this file. --> <configuration> <property> <name>dfs.replication</name> <value>2</value> <final>true</final> <description>Default block replication. The actual number of replications can be specified when the file is created. The default is used if replication is not specified in create time. </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>
注意:
咱们后续搭建集群环境时,将配置一个Master节点和两个Slave节点。因此dfs.replication
配置为2。
dfs.namenode.name.dir
和dfs.datanode.data.dir
分别配置为以前建立的NameNode和DataNode的目录路径
Hadoop安装文件中提供了一个mapred-site.xml.template,因此咱们以前使用了命令cp mapred-site.xml.template mapred-site.xml
,建立了一个mapred-site.xml文件。下面使用命令nano mapred-site.xml
编辑这个文件:
<?xml version="1.0"?> <?xml-stylesheet type="text/xsl" href="configuration.xsl"?> <!-- Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. See accompanying LICENSE file. --> <!-- Put site-specific property overrides in this file. --> <configuration> <property> <name>mapred.job.tracker</name> <value>master:9001</value> <description>The host and port that the MapReduce job tracker runs at. If "local", then jobs are run in-process as a single map and reduce task. </description> </property> </configuration>
这里只有一个配置项mapred.job.tracker
,咱们指向master节点机器。
使用命令.nano hadoop-env.sh
,修改以下配置:
# The java implementation to use. export JAVA_HOME=/usr/lib/jvm/java-7-oracle
这是很重要的一步,执行命令hadoop namenode -format
搭建集群环境,天然少不了使用SSH。这能够实现无密码访问,访问集群机器的时候很方便。
root@8ef06706f88d:~# sudo apt-get install ssh
SSH装好了之后,因为咱们是Docker容器中运行,因此SSH服务不会自动启动。须要咱们在容器启动之后,手动经过/usr/sbin/sshd
手动打开SSH服务。未免有些麻烦,为了方便,咱们把这个命令加入到~/.bashrc
文件中。经过nano ~/.bashrc
编辑.bashrc
文件(nano没有安装的自行安装,也可用vi),在文件后追加下面内容:
#autorun /usr/sbin/sshd
root@8ef06706f88d:/# cd ~/ root@8ef06706f88d:~# ssh-keygen -t rsa -P '' -f ~/.ssh/id_dsa root@8ef06706f88d:~# cd .ssh root@8ef06706f88d:~/.ssh# cat id_dsa.pub >> authorized_keys
注意: 这里,个人思路是直接将密钥生成后写入镜像,省得在买个容器里面再单独生成一次,还要相互拷贝公钥,比较麻烦。固然这只是学习使用,实际操做时,应该不会这么搞,由于这样全部容器的密钥都是同样的!!
这里咱们将安装好Hadoop的镜像保存为一个副本。
root@8ef06706f88d:~# exit king@king:~$ docker commit -m "hadoop install" 8ef06706f88d ubuntu:hadoop
重点来了!
按照 hadoop 集群的基本要求,其 中一个是 master 结点,主要是用于运行 hadoop 程序中的 namenode、secondorynamenode 和 jobtracker(新版本名字变了) 任务。用外两个结点均为 slave 结点,其中一个是用于冗余目的,若是没有冗 余,就不能称之为 hadoop 了,因此模拟 hadoop 集群至少要有 3 个结点。
前面已经将Hadoop的镜像构建好了,下面就是使用这个镜像搭建Master节点和Slave节点了:
节点 | hostname | ip | 用途 | Docker启动脚本 |
Master | master | 10.0.0.5 | namenode secondaryNamenode jobTracker |
docker run -ti -h master ubuntu:hadoop |
Slave | slave1 | 10.0.0.6 | datanode taskTracker |
docker run -ti -h slave1 ubuntu:hadoop |
Slave | slave2 | 10.0.0.7 | datanode taskTracker |
docker run -ti -h slave2 ubuntu:hadoop |
回顾一下,Docker启动容器使用的是run
命令:
docker run -ti ubuntu:hadoop
这里有几个问题:
Docker容器中的ip地址是启动以后自动分配的,且不能手动更改
hostname、hosts配置在容器内修改了,只能在本次容器生命周期内有效。若是容器退出了,从新启动,这两个配置将被还原。且这两个配置没法经过commit
命令写入镜像
咱们搭建集群环境的时候,须要指定节点的hostname,以及配置hosts。hostname可使用Docker run
命令的h
参数直接指定。但hosts解析有点麻烦,虽然可使用run
的--link
参数配置hosts解析信息,但咱们搭建集群时要求两台机器互相可以ping
通,其中一个容器没有启动,那么ip不知道,因此--link
参数对于咱们的这个场景不实用。要解决这个问题,大概须要专门搭建一个域名解析服务,即便用--dns
参数(参考这里)。
咱们这里只为学习,就不整那么复杂了,就手动修改hosts吧。只不过每次都得改,我Docker知识浅薄,一时尚未解决这个问题。相信确定有更好的办法。若是有高人能指定一下,感激涕零!!
docker run -ti -h master ubuntu:hadoop
docker run -ti -h slave1 ubuntu:hadoop
docker run -ti -h slave2 ubuntu:hadoop
经过ifconfig
命令获取各节点ip。环境不一样获取的ip可能不同,例如我本机获取的ip以下:
master:10.0.0.5
slave1:10.0.0.6
slave2:10.0.0.7
使用sudo nano /etc/hosts
命令将以下配置写入各节点的hosts文件,注意修改ip地址:
10.0.0.5 master 10.0.0.6 slave1 10.0.0.7 slave2
下面咱们来配置哪些节点是slave。在较老的Hadoop版本中有一个masters文件和一个slaves文件,但新版本中只有slaves文件了。
在master节点容器中执行以下命令:
root@master:~# cd $HADOOP_CONFIG_HOME/ root@master:~/soft/apache/hadoop/hadoop-2.6.0/etc/hadoop# nano slaves
将以下slave节点的hostname信息写入该文件:
slave1 slave2
在master节点上执行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 namenodes on [master] master: starting namenode, logging to /root/soft/apache/hadoop/hadoop-2.6.0/logs/hadoop-root-namenode-master.out slave1: starting datanode, logging to /root/soft/apache/hadoop/hadoop-2.6.0/logs/hadoop-root-datanode-slave1.out slave2: starting datanode, logging to /root/soft/apache/hadoop/hadoop-2.6.0/logs/hadoop-root-datanode-slave2.out Starting secondary namenodes [0.0.0.0] 0.0.0.0: starting secondarynamenode, logging to /root/soft/apache/hadoop/hadoop-2.6.0/logs/hadoop-root-secondarynamenode-master.out starting yarn daemons starting resourcemanager, logging to /root/soft/apache/hadoop/hadoop-2.6.0/logs/yarn--resourcemanager-master.out slave1: starting nodemanager, logging to /root/soft/apache/hadoop/hadoop-2.6.0/logs/yarn-root-nodemanager-slave1.out slave2: starting nodemanager, logging to /root/soft/apache/hadoop/hadoop-2.6.0/logs/yarn-root-nodemanager-slave2.out
在个节点上执行jps
命令,结果以下:
root@master:~/soft/apache/hadoop/hadoop-2.6.0/etc/hadoop# jps 1223 Jps 992 SecondaryNameNode 813 NameNode 1140 ResourceManager
root@slave1:~/soft/apache/hadoop/hadoop-2.6.0/etc/hadoop# jps 258 NodeManager 352 Jps 159 DataNode
root@slave2:~/soft/apache/hadoop/hadoop-2.6.0/etc/hadoop# jps 371 Jps 277 NodeManager 178 DataNode
下面,咱们在master节点上经过命令hdfs dfsadmin -report
查看DataNode是否正常启动:
root@master:~/soft/apache/hadoop/hadoop-2.6.0/etc/hadoop# hdfs dfsadmin -report Configured Capacity: 167782006784 (156.26 GB) Present Capacity: 58979344384 (54.93 GB) DFS Remaining: 58979295232 (54.93 GB) DFS Used: 49152 (48 KB) DFS Used%: 0.00% Under replicated blocks: 0 Blocks with corrupt replicas: 0 Missing blocks: 0 ------------------------------------------------- Live datanodes (2): Name: 10.0.0.7:50010 (slave2) Hostname: slave2 Decommission Status : Normal Configured Capacity: 83891003392 (78.13 GB) DFS Used: 24576 (24 KB) Non DFS Used: 54401331200 (50.67 GB) DFS Remaining: 29489647616 (27.46 GB) DFS Used%: 0.00% DFS Remaining%: 35.15% Configured Cache Capacity: 0 (0 B) Cache Used: 0 (0 B) Cache Remaining: 0 (0 B) Cache Used%: 100.00% Cache Remaining%: 0.00% Xceivers: 1 Last contact: Sat Feb 28 07:27:05 UTC 2015 Name: 10.0.0.6:50010 (slave1) Hostname: slave1 Decommission Status : Normal Configured Capacity: 83891003392 (78.13 GB) DFS Used: 24576 (24 KB) Non DFS Used: 54401331200 (50.67 GB) DFS Remaining: 29489647616 (27.46 GB) DFS Used%: 0.00% DFS Remaining%: 35.15% Configured Cache Capacity: 0 (0 B) Cache Used: 0 (0 B) Cache Remaining: 0 (0 B) Cache Used%: 100.00% Cache Remaining%: 0.00% Xceivers: 1 Last contact: Sat Feb 28 07:27:05 UTC 2015
还能够经过Web页面看到查看DataNode和NameNode的状态:http://10.0.0.5:50070/ (因为我宿主机器上没有配置master的hosts解析,因此只能用ip地址访问,你们将ip改成各自的master节点容器的ip便可):