Hadoop Part 2 - 部署 Hadoop 完全分布模式(Fully Distributed Mode)

2021-03-19
9分钟阅读时长

【版本】

当前版本号v20220320

版本修改说明
v20220320增加场景问题和时间同步命令
v20220316增加了修改authorized_keys的权限,保证NodeA能够免密登录自身
v20220124增加了更多的解析,和分阶段展示步骤。
v20210415修改了虚拟机名称的描述避免误解为hostname
v20210414修改了步骤1,提示要使用hadoop用户进行登录
v20210408新增配置到core-site.xml,修正jobhistoryserver意外退出的问题
v20210407-1修正NodeB和NodeC的公钥操作
v20210407修正authorized_keys 在 NodeB 和 NodeC 的操作
v20210406修改了mapred-site.xml出现的配置错误;新增了把key写入 authorized_keys 步骤;增加了slaves的说明,避免出错;
v20210319初始化版本

【实验目的】

  • 掌握搭建 Hadoop 完全分布模式
  • 熟练掌握Linux命令(vi、tar、mv等等)的使用
  • 掌握VirtualBox、FinalShell等客户端的使用

【实验环境】

  • 内存:至少4G
  • 硬盘:至少空余40G
  • 操作系统: 64位 Windows系统。

【实验资源】

  • FinalShell
  • CentOS 7.9系统镜像
  • VirtualBox 6.5
  • Hadoop 3 安装包
链接:https://pan.baidu.com/s/1MoQ0iU0Qb1o8_o5JV6X6iw 
提取码:3rno

【实验内容】

  • 完成模板机的克隆
  • 完成Hadoop 完全分布模式的部署

【实验步骤】

克隆模板机

  1. 关闭 Part1 完成的 HadoopTmpl 模板机。依次克隆出3台虚拟机,名称,主机名和 IP 地址如下表所示,注意替换为你的学号后3位。
虚拟机名称hostnameIP地址
节点A主机(Namenode)nodea+你学号后3位10.0.0.71
节点B主机(Datanode)nodeb+你学号后3位10.0.0.72
节点C主机(Datanode)nodec+你学号后3位10.0.0.73

  1. 依次启动克隆的虚拟机,修改为对应的 hostname 和 IP。以下以节点A主机(Namenode)为例。

  2. 使用hadoop用户登录节点A,密码为123456

  3. 修改 hostname。

sudo vim /etc/hostname
  • 修改为nodea+你学号后3位

如果你学号是123,则命名为nodea123,相应的节点B和节点C分别命名为nodeb123nodec123

  1. 修改 IP。
sudo vim /etc/sysconfig/network-scripts/ifcfg-enp0s3
  • 修改`IPADDR=“10.0.0.71”
  1. 重启克隆的3台虚拟机,配置 FinalShell 分别连接3台虚拟机,使用hadoop用户登录,密码为123456,测试是否能够正常登录。

配置免密登录

免密登录,顾名思义就是不需要输入密码即可登录。免密登录的大致原理,就是在客户端 client 生成一对密钥(包括公钥和私钥),然后将公钥传到服务器 server。当 client 通过 ssh 登录 server 时,不用再输入密码就能直接登进去,这就是 ssh 免密登录。

Hadoop 的 NameNode 是通过SSH 来启动和停止各个节点上的各种守护进程的,这就需要在节点之间执行指令的时候是不需要输入密码的方式,故我们需要配置SSH使用免密登录。

注意此阶段命令如无特殊说明,均在 NodeA 的 hadoop 用户下执行!
  1. 使用 Hadoop 用户登录 NodeA 节点。如果使用root登录的可以使用以下命令切换到hadoop用户。
su hadoop
  1. 使用 ping 命令检查是否能够连通 NodeB 和 NodeC。
ping nodeb+你学号后3位 -c 3
ping nodec+你学号后3位 -c 3
  • 正常情况下应该有类似返回信息如下:
64 bytes from nodeb (10.0.0.72): icmp_seq=1 ttl=64 time=0.373 ms
  • 如果没有看到以上返回消息,请检查/etc/hosts是否修改正确,参考 Part1 步骤55
  1. 配置免密登录。首先生成密钥对,运行以下命令。直接回车(Enter)3次。
ssh-keygen -t rsa
  • 在返回的对话文字中,直接回车(Enter)3次,输出内容类似以下。
Generating public/private rsa key pair.
Enter file in which to save the key (/home/hadoop/.ssh/id_rsa): 
Created directory '/home/hadoop/.ssh'.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/hadoop/.ssh/id_rsa.
Your public key has been saved in /home/hadoop/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:MSUbr5VaCY4KSpsCM0l8uhYWkr5R9iNI05SFuF00jLA hadoop@nodea999
The key's randomart image is:
+---[RSA 2048]----+
|.+=.B+  + .      |
|+B.O o.o B o     |
|OE% o . = *      |
|o%o+ +   B       |
|+o= o . S        |
|.+               |
|.                |
|                 |
|                 |
+----[SHA256]-----+
  1. 查看目录下是否有公钥id_rsa.pub和私钥id_rsa
cd ~/.ssh
ls
  • 可以看到以下2个文件。其中id_rsa是私钥,id_rsa.pub是公钥。
id_rsa  id_rsa.pub
  1. 执行以下命令,把公钥写入本机授权文件。
cat id_rsa.pub >> authorized_keys
  1. 查看授权文件内的公钥内容。
cd ~/.ssh
cat authorized_keys
  • 可以看到类似以下内容
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC1Df9cM8NVGURMj3I86EoiO4Jy6LuuHOc+MC3vnZPJX9ISSXDZ9Qx+a5CCdoZJyySG3IlvAFBLv2Wnv60tDZ9xHEQ0WbkAV/IeDrdRk1OI51/bEGfdPqTLBtic1eXsFC6luc7kbQYuxQRoeovl2UwHNgzAX/xTyUV0uAuvTeggyGWq05I9OiantybrumNUJO8gFO3R9CA/zvNrJbuvVDKT9AAqQpn57jDsHkTiAlGoubKUcgAWy1EbYk7hVCL1gFkMcxDMvSOBoY23oqEFSNrkuho2Cj2fNUinaDNDPPzoqbDwvU9IUCGhgfiNYb4Ub/hoabJRjlcNiEgoD+G79lNd hadoop@nodea你的学号后3位
  1. 修改 authorized_keys 的权限为444,让NodeA能够免密登录自身。
chmod 444 authorized_keys
ls -al authorized_keys	
  1. 确认NodeBNodeC2个节点都已经启动。在NodaA上面运行以下命令,把公钥拷贝到NodeBNodeC
ssh-copy-id -i ~/.ssh/id_rsa.pub nodeb+你学号后3位 -f
ssh-copy-id -i ~/.ssh/id_rsa.pub nodec+你学号后3位 -f
  • 系统询问是否连接,输入yes
Are you sure you want to continue connecting (yes/no)? yes
  • 输入 hadoop 登录密码
hadoop@nodeb你学号后3位's password:
  1. 使用以下方法测试免密登录是否配置成功,在NodeA上面分别 SSH 登录NodeANodeBNodeC
  • 例如:在 NodeA 执行以下命令,使用 SSH 协议登录 NodeB。
ssh hadoop@nodeb+你的学号后3位
  • 如果能够成功登录 NodeB 节点,而且不需要输入密码,则表示免密登录成功。输入以下命令退出登录。
exit

修改 Hadoop 配置文件

注意此阶段命令如无特殊说明,均在 NodeA 的 hadoop 用户下执行!
  1. 备份和编辑 Hadoop 的 core-site.xml 配置文件。在configuration 标签内添加配置,注意替换为你的学号后3位。
cp /opt/hadoop/etc/hadoop/core-site.xml{,.bak}
vim /opt/hadoop/etc/hadoop/core-site.xml
<configuration>
  <!-- HDFS 访问地址 -->
  <property>
    <name>fs.defaultFS</name>
    <value>hdfs://nodea+你学号后3位:8020</value>
  </property>
  <property>
    <name>hadoop.tmp.dir</name>
    <value>/opt/hadoop/tmp</value>
  </property>
  <property>
    <name>fs.trash.interval</name>
    <value>1440</value>
  </property>
  <property>
    <name>hadoop.http.staticuser.user</name>
    <value>hadoop</value>
  </property>
</configuration>
  1. 备份和编辑 Hadoop 的 hdfs-site.xml 配置文件。请注意替换为你的学号。
cp /opt/hadoop/etc/hadoop/hdfs-site.xml{,.bak}
vim /opt/hadoop/etc/hadoop/hdfs-site.xml
<configuration>
  <!-- secondary namenode 访问地址-->
  <property>
    <name>dfs.secondary.http.address</name>
    <value>nodea+你学号后3位:50090</value>
  </property>
  <!-- HDFS 副本数量 -->
  <property>
    <name>dfs.replication</name>
    <value>2</value>
  </property>
</configuration>
  1. 新建一个 masters 配置文件,写入 Secondary NameNode 的主机名。
vim /opt/hadoop/etc/hadoop/masters

写入以下内容,注意替换为你的学号后3位。

nodea+你的学号后3位
  1. 备份和编辑 Hadoop 的 mapred-site.xml 配置文件。注意替换为你的学号后3位。
cp /opt/hadoop/etc/hadoop/mapred-site.xml{,.bak}
vim /opt/hadoop/etc/hadoop/mapred-site.xml
<configuration>
  <property>
    <name>mapreduce.framework.name</name>
    <value>yarn</value>
  </property>
  <property>
    <name>mapreduce.jobhistory.address</name>
    <value>nodea+你学号后3位:10020</value>
    <description>Host and port for Job History Server (default 0.0.0.0:10020)</description>
  </property>
  <property> 
      <name>mapreduce.application.classpath</name>
      <value>$HADOOP_HOME/share/hadoop/mapreduce/*,$HADOOP_HOME/share/hadoop/mapreduce/lib/*,$HADOOP_HOME/share/hadoop/common/*,$HADOOP_HOME/share/hadoop/common/lib/*,$HADOOP_HOME/share/hadoop/yarn/*,$HADOOP_HOME/share/hadoop/yarn/lib/*,$HADOOP_HOME/share/hadoop/hdfs/*,$HADOOP_HOME/share/hadoop/hdfs/lib/*</value>
  </property>
</configuration>
  1. 备份和编辑 Hadoop 的 yarn-site.xml 配置文件。注意替换为你的学号后3位。
cp /opt/hadoop/etc/hadoop/yarn-site.xml{,.bak}
vim /opt/hadoop/etc/hadoop/yarn-site.xml
<configuration>
  <property>
    <name>yarn.resourcemanager.hostname</name>
    <value>nodea+你学号后3位</value>
  </property>
  <property>
    <name>yarn.nodemanager.aux-services</name>
    <value>mapreduce_shuffle</value>
  </property>
</configuration>
  1. 编辑 workers ,清除原来的所有内容,增加配置 DataNode 节点信息。注意替换为你的学号后3位。
vim /opt/hadoop/etc/hadoop/workers
nodeb+你学号后3位
nodec+你学号后3位

从Hadoop 3.0 开始,slaves 已经启用,改用 workers 来进行替代配置数据节点信息。

  1. 修改 hadoop-env.sh,在第1行加入以下代码。
vim /opt/hadoop/etc/hadoop/hadoop-env.sh
export JAVA_HOME=/opt/jdk8
  1. NodeA节点的 Hadoop /opt/hadoop/etc/hadoop 下所有配置文件发送到NodeBNodeC。如果上面的配置文件有修改,也需要同步发送到NodeBNodeC节点。
cd /opt/hadoop/etc/
scp -r hadoop hadoop@nodeb+你学号后3位:/opt/hadoop/etc/
scp -r hadoop hadoop@nodec+你学号后3位:/opt/hadoop/etc/
  1. 格式化 HDFS。
注意此命令请勿重复执行,因为会导致 DataNode 和 NameNode 的集群ID不一致,造成HDFS出错。
hdfs namenode -format
  • 在输出的内容中,如果能看到以下这句信息,说明格式化成功。
2022-01-24 14:32:54,209 INFO common.Storage: Storage directory /opt/hadoop/tmp/dfs/name has been successfully formatted.
  1. 创建 Hadoop 启动脚本,注意替换为你的学号后3位。
vim /opt/hadoop/sbin/start-hdp.sh
#!/usr/bin/env bash
echo "Start Hadoop by 你的学号后3位"
start-dfs.sh
start-yarn.sh
mapred --daemon start historyserver
  1. 创建 Hadoop 停止脚本,注意替换为你的学号后3位。
vim /opt/hadoop/sbin/stop-hdp.sh
#!/usr/bin/env bash
echo "Stop Hadoop by 你的学号后3位"
mapred --daemon stop historyserver
stop-yarn.sh
stop-dfs.sh
  1. 创建 Hadoop 重启脚本,注意替换为你的学号后3位。
vim /opt/hadoop/sbin/restart-hdp.sh
#!/usr/bin/env bash
stop-hdp.sh
start-hdp.sh
  1. 修改创建的脚本的权限。
cd /opt/hadoop/sbin/
chmod 744 start-hdp.sh stop-hdp.sh restart-hdp.sh
  1. 使用脚本启动 Hadoop。
start-hdp.sh

验证免密登录

  1. NodeBNodeC2个节点分别执行以下命令,查看是否包含来自NodeA的公钥。
cd ~/.ssh
cat  authorized_keys

验证时间是否同步

  1. NodeBNodeC2个节点分别执行以下命令,查看时间是否与NodeA同步。
date

如果时间不同步,可以执行以下语句,尝试强制同步时间。

chronyc -a makestep

验证 Hadoop 是否正常启动

  1. NodeA输入jps命令,观察是否有以下进程。
jps
  • 正常应该有类似以下信息返回:
NameNode
Jps
ResourceManager
SecondaryNameNode
JobHistoryServer
  1. NodeA输入以下命令查看机架拓扑是否有NodeBNodeC的信息
hdfs dfsadmin -printTopology
  • 正常应该有类似以下信息返回:
Rack: /default-rack
   10.0.0.72:9866 (nodeb你的学号后3位)
   10.0.0.73:9866 (nodec你的学号后3位)
  1. NodeBNodeC分别输入jps命令,观察是否有以下进程。
jps
  • 正常应该有类似以下信息返回:
DataNode
NodeManager
Jps

验证 HDFS 是否正常工作

  1. 打开宿主机浏览器,访问 HDFS Web界面 http://10.0.0.71:9870/

  2. 查看 NameNode 是否 Active

  3. 查看2个节点 DataNode 服务状态是否正常。

  4. 上传countryroad.txtNodeA/home/hadoop

  5. countryroad.txt从 CentOS 文件系统上传到 HDFS 文件系统。

hdfs dfs -mkdir /part2
hdfs dfs -put /home/hadoop/countryroad.txt /part2
hdfs dfs -ls /part2

验证 MapReduce 是否正常工作

  1. 运行 Hadoop 自带的 Wordcount 程序,观察输出的内容。
cd $HADOOP_HOME/share/hadoop/mapreduce
hadoop jar hadoop-mapreduce-examples-3.3.1.jar wordcount /part2/countryroad.txt /output
  • 如果输出的日志内容包含类似以下信息,则表示执行成功
2022-01-24 15:48:51,712 INFO mapreduce.Job: Job job_xxxxxxx completed successfully
  1. 程序执行过程中,可以访问 Yarn Web 界面查看任务进展。http://10.0.0.71:8088/cluster/apps

  1. 等待程序运行完毕,观察输出的内容
hdfs dfs -cat /output/part-r-00000

【常见问题】

1. NodeA节点NameNodeSecondaryNameNode 无法启动。并且日志提示“/opt/hadoop/tmp/dfs/namesecondary is in an inconsistent state”。

答:可能是因为多次格式化或者配置文件没有同步导致的错误。

  • (1) 首先把NodeA节点的 Hadoop /opt/hadoop/etc/hadoop 下所有配置文件发送到NodeBNodeC
cd /opt/hadoop/etc/
scp -r hadoop hadoop@nodeb+你学号后3位:/opt/hadoop/etc/
scp -r hadoop hadoop@nodec+你学号后3位:/opt/hadoop/etc/
  • (2) 删除/opt/hadoop/tmp 下的所有内容。
  • (3) 再次执行 HDFS 格式化。
hdfs namenode -format

2. Hadoop 执行 MapReduce 任务失败,并且日志伴有“Note: System times on machines may be out of sync. Check system time and time zones.”

答:可能是由于虚拟机节点之间的时间不同步导致的。

  • (1) 在NodeBNodeC执行以下语句,尝试强制与NodeA同步时间。
chronyc -a makestep
  • (2) 重启 Hadoop。

3. YARN 的 ResourceManager 进程找不到,而且日志报java.lang.NullPointerException

java.lang.NullPointerException
        at org.apache.hadoop.yarn.server.api.protocolrecords.impl.pb.NodesToAttributesMappingRequestPBImpl.initNodeAttributesMapping(NodesToAttributesMappingRequestPBImpl.java:102)
        at org.apache.hadoop.yarn.server.api.protocolrecords.impl.pb.NodesToAttributesMappingRequestPBImpl.getNodesToAttributes(NodesToAttributesMappingRequestPBImpl.java:117)
        at org.apache.hadoop.yarn.nodelabels.store.op.FSNodeStoreLogOp.getNodeToAttributesMap(FSNodeStoreLogOp.java:46)
        at org.apache.hadoop.yarn.nodelabels.store.op.NodeAttributeMirrorOp.recover(NodeAttributeMirrorOp.java:57)
        at org.apache.hadoop.yarn.nodelabels.store.op.NodeAttributeMirrorOp.recover(NodeAttributeMirrorOp.java:35)
        at org.apache.hadoop.yarn.nodelabels.store.AbstractFSNodeStore.loadFromMirror(AbstractFSNodeStore.java:121)
        at org.apache.hadoop.yarn.nodelabels.store.AbstractFSNodeStore.recoverFromStore(AbstractFSNodeStore.java:150)
        at org.apache.hadoop.yarn.server.resourcemanager.nodelabels.FileSystemNodeAttributeStore.recover(FileSystemNodeAttributeStore.java:95)

答:在/tmp目录下找到以下 yarn 相关的目录进行删除

/tmp/hadoop-yarn-hadoop
/tmp/hadoop-yarn-root