JDK: jdk1.8.0_131
Hadoop: hadoop-2.6.5
使用三台机器做来搭建Hadoop集群。其中slave机器放在实验室,master机器放在宿舍。
主机名 | 系统 | IP地址 |
---|---|---|
master | ubuntu 16.04 | 10.147.18.1 |
slave01 | ubuntu 16.04-server | 10.147.18.2 |
slave02 | ubuntu 16.04-server | 10.147.18.3 |
注意:由于Hadoop要求所有机器上Hadoop的部署目录结构要求相同(因为在启动时按与主节点相同的目录启动其它任务节点),并且都有一个相同的用户名账户。参考各种文档上说的是所有机器都建立一个hadoop用户,使用这个账户来实现无密码认证。这里为了方便,分别在三台机器上都重新建立一个hadoop用户。
全程使用root权限操作以避免不必要的麻烦。
如果你的Ubuntu系统不是使用hadoop这个用户名,那么需要增加一个名为 hadoop 的用户。方便之后的操作(不论是Master节点还是Slave节点都需要一个hadoop用户并且之后的操作都需要在hadoop用户下进行)
在终端中输入以下命令
$ sudo useradd -m hadoop -s /bin/bash
#这条命令创建了可以登陆的 hadoop 用户,并使用 /bin/bash 作为 shell。
#接着使用如下命令设置密码,可简单设置为 hadoop,按提示输入两次密码。
$ sudo passwd hadoop
#可为 hadoop 用户增加管理员权限,方便部署:
$ sudo adduser hadoop sudo
#最后使用su切换到hadoop用户或者在图形化界面点注销重新登录至hadoop用户
假定我们发现我们的机器的主机名不是我们想要的。
修改文件/etc/hostname里的值即可,修改成功后重启,用hostname命令查看当前主机名是否设置成功。
我们将Master主机名设置为master
“/etc/hosts”这个文件是用来配置主机将用的DNS服务器信息,是记载LAN内接续的各主机的对应[HostName IP]用的。当用户在进行网络连接时,首先查找该文件,寻找对应主机名对应的IP地址。
我们要测试两台机器之间知否连通,一般用“ping 机器的IP”,如果想用“ping 机器的昵称”发现找不见该名称的机器(这也就是为什么在修改主机名的同时最好修改该文件中对应的主机名),解决的办法就是修改“/etc/hosts”这个文件,通过把LAN内的各主机的IP地址和昵称的一一对应写入这个文件的时候,就可以解决问题。
修改所有主机中的hosts文件,配置如下:(我使用了3台主机)
127.0.0.1 localhost
10.147.18.1 master #master相应昵称
10.147.18.2 slave01 #slave1相应昵称
10.147.18.3 slave02 #slave2相应昵称
可以使用 ping 命令测试三台机器的连通性。此时可以直接使用昵称来ping。
PS:对于如何连接不同网段的情况,请参考我另外的一篇文章ZeroTier-全网畅连
关闭防火墙,防止slave主机的DataNode被关闭。
# 查看防火墙状态
$ systemctl status firewalld.service
# 关闭防火墙
$ systemctl stop firewalld.service
# 永久关闭防火墙
$ systemctl disable firewalld.service
Hadoop运行过程中需要管理远端Hadoop守护进程,在Hadoop启动以后,NameNode是通过SSH(Secure Shell)来启动和停止各个DataNode上的各种守护进程的。这就必须在节点之间执行指令的时候是不需要输入密码的形式,故我们需要配置SSH运用无密码公钥认证的形式,这样NameNode使用SSH无密码登录并启动DataName进程,同样原理,DataNode上也能使用SSH无密码登录到 NameNode。
注意:如果你的Linux没有安装SSH,请首先安装SSH
Ubuntu下安装ssh:
sudo apt-get install openssh-server
Master(NameNode | JobTracker)作为客户端,要实现无密码公钥认证,连接到服务器Salve(DataNode | Tasktracker)上时,需要在Master上生成一个密钥对,包括一个公钥和一个私钥,而后将公钥复制到所有的Slave上。当Master通过SSH连接Salve时,Salve就会生成一个随机数并用Master的公钥对随机数进行加密,并发送给Master。Master收到加密数之后再用私钥解密,并将解密数回传给Slave,Slave确认解密数无误之后就允许Master进行连接了。这就是一个公钥认证过程,其间不需要用户手工输入密码。
在各台机器中分别执行以下两个命令,用来生成SSH公钥和密钥:
#在/home/hadoop/.ssh目录下生成公钥和密钥
$ ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa
#把id_dsa.pub追加到授权的key里面去
$ cat ~/.ssh/id_dsa.pub >> ~/.ssh/authorized_keys
查看下authorized_keys的权限,如果权限不对则利用如下命令设置该文件的权限:
$ chmod 600 ~/.ssh/authorized_keys
用root权限修改SSH配置文件“/etc/ssh/sshd_config”的下列内容。
检查下面几行前面“#”注释取消掉:
RSAAuthentication yes # 启用 RSA 认证
PubkeyAuthentication yes # 启用公钥私钥配对认证方式
AuthorizedKeysFile %h/.ssh/authorized_keys # 公钥文件路径 (默认被注释)
设置完之后记得重启SSH服务,才能使刚才设置有效。
$ service ssh restart
每台主机都完成以上操作以后。继续下一步
将 slave01 和 slave02 的公钥 id_dsa.pub传给 master。
#slave01主机
$ scp ~/.ssh/id_dsa.pub hadoop@master:/home/hadoop/.ssh/id_dsa.pub.slave01
#slave02主机
$ scp ~/.ssh/id_dsa.pub hadoop@master:/home/hadoop/.ssh/id_dsa.pub.slave02
将 slave01 和 slave02的公钥信息追加到 master 的 authorized_keys文件中。
#master主机
$ cat ~/.ssh/id_dsa.pub.slave01 >> authorized_keys
$ cat ~/.ssh/id_dsa.pub.slave02 >> authorized_keys
将 master 的公钥信息 authorized_keys 复制到 slave01 和 slave02 的 .ssh 目录下。
#master主机
$ scp ~/.ssh/authorized_keys hadoop@slave01:/home/hadoop/.ssh/authorized_keys
$ scp ~/.ssh/authorized_keys hadoop@slave02:/home/hadoop/.ssh/authorized_keys
ssh 到slave01主机如下图所示
可以看到从 master 已经不需要密码就可以登录到 slave01 和 slave 02。slave01 和 slave02 也无需密码访问其他的机器。
此时免密登录就配置完成。
JDK下载官网下载JDK相应版本
下载解压 jdk1.8.0_131.tar.gz。
#解压jdk
$ tar zxvf jdk1.8.0_131.tar.gz
#将解压完的jdk文件夹移到/opt目录下
$ mv jdk1.8.0_131 /opt
配置环境变量, 使用root权限编辑”/etc/profile” 文件,在文件末尾添加以下内容:
# Java Env
export JAVA_HOME=/opt/jdk1.8.0_131
export JRE_HOME=/opt/jdk1.8.0_131/jre
export PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib
保存后,运行 source profile,使环境变量立即生效。
3. 查看JDK版本信息
$ java -version
若出现相关版本信息,说明JDK配置成功!
Hadoop下载官网下载Hadoop相应版本
1. 下载解压hadoop-2.6.5.tar.gz
```
#解压hadoop
$ tar zxvf hadoop-2.6.5.tar.gz
#将解压完的jdk文件夹移到/opt目录下
$ mv hadoop-2.6.5 /opt
#将hadoop文件所属用户和组改为hadoop
$ sudo chown -R hadoop:hadoop /opt/hadoop-2.6.5
```
2. 配置环境变量, 使用root权限编辑”/etc/profile” 文件,在文件末尾添加以下内容:
# Hadoop Env
export HADOOP_HOME=/opt/hadoop-2.6.5
export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin
保存后,运行 source profile,使环境变量立即生效。
3. 修改 Hadoop 环境变量配置文件 “/opt/hadoop-2.6.5/etc/hadoop/hadoop-env.sh”,在文件末尾添加以下内容:
# The java implementation to use.
export JAVA_HOME=/opt/jdk1.8.0_131
export HADOOP_PREFIX=/opt/hadoop-2.6.5
输入 hadoop version 可以看到成功安装的 Hadoop 版本信息。
4. 输入 hadoop 查看 hadoop 命令使用方法
首先在master主机上进行Hadoop配置,之后在其他slave主机上进行相同的配置即可。
/opt/hadoop-2.6.5/etc/hadoop/hadoop-env.sh
#增加如下两行配置
export JAVA_HOME=/opt/jdk1.8.0_131
export HADOOP_PREFIX=/opt/hadoop-2.6.5
/opt/hadoop-2.6.5/etc/hadoop/core-site.xml
<configuration>
<property>
<name>fs.defaultFSname>
<value>hdfs://master:9000value>
property>
<property>
<name>hadoop.tmp.dirname>
<value>/opt/hadoop-2.6.5/tmpvalue>
property>
configuration>
注意: tmp目录需要提前创建
/opt/hadoop-2.6.5/etc/hadoop/hdfs-site.xml
<configuration>
<property>
<name>dfs.replicationname>
<value>3value>
property>
configuration>
数据存有三个副本
/opt/hadoop-2.6.5/etc/hadoop/mapred-site.xml
<configuration>
<property>
<name>mapreduce.framework.namename>
<value>yarnvalue>
property>
configuration>
如果不存在mapred-site.xml文件,则从mapred-site.xml.template中复制相应模板新建。
/opt/hadoop-2.6.5/etc/hadoop/yarn-env.sh
#在文件末尾添加JAVA_HOME配置
export JAVA_HOME=/opt/jdk1.8.0_131
/opt/hadoop-2.6.5/etc/hadoop/yarn-site.xml
<configuration>
<property>
<name>yarn.nodemanager.aux-servicesname>
<value>mapreduce_shufflevalue>
property>
<property>
<name>yarn.resourcemanager.hostnamename>
<value>mastervalue>
property>
configuration>
/opt/hadoop-2.6.5/etc/hadoop/masters
master
如果没有这个文件,请新建。
/opt/hadoop-2.6.5/etc/hadoop/slaves
slave01
slave02
请跳转至“/opt/hadoopt-2.6.5/sbin”目录下执行一下命令。
#在 master 上执行以下命令:
$ hadoop namenode -format
# 在 master 机器上执行
$ start-all.sh
使用 jps 命令查看 master 上hadoop的运行情况:
可以看到NameNode,DataNode,ResourceManager已经启动成功!
同理查看slave上hadoop的运行情况:
slave01已经启动了DataNode和NodeManager。
浏览器输入地址: http://master:50070/ 可以查看 NameNode 信息。
至此,整个 Hadoop 集群就已经启动了。
hadoop安装完之后敲入hadoop命令时,老是提示这个警告:
Warning: $HADOOP_HOME is deprecated.
经查hadoop-2.6.5/bin/hadoop脚本和”hadoop-config.sh”脚本,发现脚本中对HADOOP_HOME的环境变量设置做了判断,其实根本不需要设置HADOOP_HOME环境变量。
解决方案一:编辑”/etc/profile”文件,去掉HADOOP_HOME的变量设定,重新输入hadoop fs命令,警告消失。
解决方案二:编辑”/etc/profile”文件,添加一个环境变量,之后警告消失:
export HADOOP_HOME_WARN_SUPPRESS=1
当我停止Hadoop时发现如下信息:
no datanode to stop
原因:每次namenode format会重新创建一个namenodeId,而tmp/dfs/data下包含了上次format下的id,namenode format清空了namenode下的数据,但是没有清空datanode下的数据,导致启动时失败,有两种解决方案:
第一种解决方案如下:
1)先删除”/opt/hadoop-2.6.5/tmp”
$ rm -rf /opt/hadoop-2.6.5/tmp
2)创建”/opt/hadoop-2.6.5/tmp”文件夹
$ mkdir /opt/hadoop-2.6.5/tmp
3)删除”/tmp”下以”hadoop”开头文件
$ rm -rf /tmp/hadoop*
4)重新格式化hadoop
$ hadoop namenode -format
5)启动hadoop
$ start-all.sh
使用第一种方案,不好之处在于原来集群上的重要数据全没有了。
假如说Hadoop集群已经运行了一段时间。建议采用第二种。
第二种方案如下:
1)修改每个Slave的namespaceID使其与Master的namespaceID一致。
或者
修改Master的namespaceID使其与Slave的namespaceID一致。
2)该”namespaceID”位于”/opt/hadoop-2.6.5/tmp/dfs/name/current/VERSION”文件中
例如:查看”Master”下的”VERSION”文件
建议采用第二种,这样方便快捷,而且还能防止误删。
查看日志发下如下错误。
ERROR org.apache.hadoop.hdfs.server.datanode.DataNode: java.io.IOException: Call to … failed on local exception: java.net.NoRouteToHostException: No route to host
解决方案: 关闭防火墙
出现如下错误:
INFO hdfs.DFSClient: Exception in createBlockOutputStream java.io.IOException: Bad connect ack with firstBadLink
INFO hdfs.DFSClient: Abandoning block blk_-1300529705803292651_37023
WARN hdfs.DFSClient: DataStreamer Exception: java.io.IOException: Unable to create new block.
解决方案:
1)关闭防火墙
2)禁用selinux
编辑 “/etc/selinux/config”文件,设置”SELINUX=disabled”
出现如下错误:
org.apache.hadoop.dfs.SafeModeException: Cannot delete …, Name node is in safe mode
在分布式文件系统启动的时候,开始的时候会有安全模式,当分布式文件系统处于安全模式的情况下,文件系统中的内容不允许修改也不允许删除,直到安全模式结束。安全模式主要是为了系统启动的时候检查各个DataNode上数据块的有效性,同时根据策略必要的复制或者删除部分数据块。运行期通过命令也可以进入安全模式。在实践过程中,系统启动的时候去修改和删除文件也会有安全模式不允许修改的出错提示,只需要等待一会儿即可。
解决方案: 关闭安全模式
$ hadoop dfsadmin -safemode leave
出现错误如下:
Shuffle Error: Exceeded MAX_FAILED_UNIQUE_FETCHES; bailing-out
程序里面需要打开多个文件,进行分析,系统一般默认数量是1024,(用ulimit -a可以看到)对于正常使用是够了,但是对于程序来讲,就太少了。
解决方案: 修改2个文件。
1)”/etc/security/limits.conf”
vi /etc/security/limits.conf
加上:
soft nofile 102400
hard nofile 409600
2)”/etc/pam.d/login”
vim /etc/pam.d/login
添加:
session required /lib/security/pam_limits.so
针对第一个问题我纠正下答案:
这是reduce预处理阶段shuffle时获取已完成的map的输出失败次数超过上限造成的,上限默认为5。引起此问题的方式可能会有很多种,比如网络连接不正常,连接超时,带宽较差以及端口阻塞等。通常框架内网络情况较好是不会出现此错误的。
出现这个问题主要是结点间的连通不够全面。
解决方案:
1)检查”/etc/hosts”
要求本机ip 对应服务器名
要求要包含所有的服务器ip +服务器名
2)检查”.ssh/authorized_keys”
要求包含所有服务器(包括其自身)的public key
出现map很快,但是reduce很慢,而且反复出现”reduce=0%”。
解决方案:
结合上一个问题解决方案,然后修改”conf/hadoop-env.sh”中的”export HADOOP_HEAPSIZE=4000”
出现这种异常,明显是jvm内存不够得原因。
解决方案: 要修改所有的datanode的jvm内存大小。
Java –Xms 1024m -Xmx 4096m
一般jvm的最大内存使用应该为总内存大小的一半,我们使用的8G内存,所以设置为4096m,这一值可能依旧不是最优的值。
Hadoop 2.6.4分布式集群环境搭建
Hadoop 2.6.4单节点集群环境搭建
一步步教你Hadoop多节点集群安装配置
搭建Spark集群(三)——搭建Hadoop集群环境