Hadoop-3.4.2高可用集群部署
本实验基于前文Hadoop-3.4.2集群化部署作为基础环境
将当前的 Hadoop 3.4.2 三节点标准集群(1 NameNode + 2 DataNode) 升级为 高可用(HA, High Availability)集群,核心目标是:避免单点故障(SPOF),即当主 NameNode 宕机时,备用 NameNode 能自动接管服务。
架构对比
| 组件 | 原始架构 | HA 架构 |
|---|---|---|
| NameNode | 1 个(master) | 2 个:active + standby(例如 master + slave1) |
| 共享存储 | 无 | QJM(Quorum Journal Manager) 或 NFS(推荐 QJM) |
| 故障切换 | 手动 | 自动(通过 ZooKeeper + ZKFC) |
| ResourceManager | 1 个 | 可选 HA(本指南先聚焦 HDFS HA) |
一、新增组件与角色规划(仍用 3 节点)
| 主机名 | IP | 角色 |
|---|---|---|
| hadoop01 (master) | 10.0.0.10 | NameNode (active), ZKFC, JournalNode, DataNode(可选), ResourceManager |
| hadoop02 (slave1) | 10.0.0.20 | NameNode (standby), ZKFC, JournalNode, DataNode, NodeManager |
| hadoop03 (slave2) | 10.0.0.30 | JournalNode, DataNode, NodeManager, ZooKeeper |
💡 说明:
- JournalNode:至少 3 个(奇数),用于同步 edits 日志
- ZooKeeper:至少 3 节点(可复用现有机器)
- ZKFC(ZooKeeper Failover Controller):运行在每个 NameNode 上,监控 NN 状态并触发切换
二、部署步骤概览
- 安装 ZooKeeper(3 节点)
- 配置 JournalNode
- 修改 HDFS 配置启用 HA
- 初始化 JournalNode 和 NameNode HA 状态
- 启动 HA 集群
- 验证故障切换
步骤 1:部署 ZooKeeper(在所有 3 节点)
1.1 下载并解压(所有节点)
# 以 hadoop 用户操作
cd ~
wget https://archive.apache.org/dist/zookeeper/zookeeper-3.8.4/apache-zookeeper-3.8.4-bin.tar.gz
tar -zxvf apache-zookeeper-3.8.4-bin.tar.gz
mv apache-zookeeper-3.8.4-bin zookeeper
1.2 配置 zoo.cfg(所有节点)
mkdir -p ~/zookeeper/data
echo "1" > ~/zookeeper/data/myid # master 上为 1
# slave1 上执行:echo "2" > ~/zookeeper/data/myid
# slave2 上执行:echo "3" > ~/zookeeper/data/myid
编辑 ~/zookeeper/conf/zoo.cfg:
tickTime=2000
dataDir=/home/hadoop/zookeeper/data
clientPort=2181
initLimit=5
syncLimit=2
server.1=master:2888:3888
server.2=slave1:2888:3888
server.3=slave2:2888:3888
1.3 启动 ZooKeeper(所有节点)
~/zookeeper/bin/zkServer.sh start
# 检查状态
~/zookeeper/bin/zkServer.sh status
应看到一个 leader,两个 follower
步骤 2:配置 Hadoop HA(在 master 上修改)
2.1 修改 hdfs-site.xml
vim hdfs-site.xml
<configuration>
<!-- 启用 HA -->
<property>
<name>dfs.nameservices</name>
<value>mycluster</value>
</property>
<!-- 定义两个 NameNode 的 ID -->
<property>
<name>dfs.ha.namenodes.mycluster</name>
<value>nn1,nn2</value>
</property>
<!-- nn1 (master) 的 RPC 地址 -->
<property>
<name>dfs.namenode.rpc-address.mycluster.nn1</name>
<value>master:9000</value>
</property>
<!-- nn2 (slave1) 的 RPC 地址 -->
<property>
<name>dfs.namenode.rpc-address.mycluster.nn2</name>
<value>slave1:9000</value>
</property>
<!-- nn1 的 HTTP 地址 -->
<property>
<name>dfs.namenode.http-address.mycluster.nn1</name>
<value>master:9870</value>
</property>
<!-- nn2 的 HTTP 地址 -->
<property>
<name>dfs.namenode.http-address.mycluster.nn2</name>
<value>slave1:9870</value>
</property>
<!-- JournalNode 地址(3 节点) -->
<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://master:8485;slave1:8485;slave2:8485/mycluster</value>
</property>
<!-- 客户端故障转移代理 -->
<property>
<name>dfs.client.failover.proxy.provider.mycluster</name>
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>
<!-- 启用自动故障转移 -->
<property>
<name>dfs.ha.automatic-failover.enabled</name>
<value>true</value>
</property>
<!-- JournalNode 本地目录 -->
<property>
<name>dfs.journalnode.edits.dir</name>
<value>/home/hadoop/hadoop/journalnode</value>
</property>
<!-- 其他原有配置保留 -->
<property>
<name>dfs.replication</name>
<value>2</value>
</property>
<property>
<name>dfs.namenode.name.dir</name>
<value>/home/hadoop/hadoop/hdfs/namenode</value>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>/home/hadoop/hadoop/hdfs/datanode</value>
</property>
<!-- 防护方法配置 -->
<property>
<name>dfs.ha.fencing.methods</name>
<value>sshfence</value>
</property>
<property>
<name>dfs.ha.fencing.ssh.private-key-files</name>
<value>/home/hadoop/.ssh/id_rsa</value>
</property>
<property>
<name>dfs.ha.fencing.ssh.connect-timeout</name>
<value>30000</value>
</property>
</configuration>
2.2 修改 core-site.xml
vim core-site.xml
<configuration>
<!-- 使用 nameservice 名称代替具体主机 -->
<property>
<name>fs.defaultFS</name>
<value>hdfs://mycluster</value>
</property>
<!-- ZooKeeper 地址 -->
<property>
<name>ha.zookeeper.quorum</name>
<value>master:2181,slave1:2181,slave2:2181</value>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/home/hadoop/hadoop/tmp</value>
</property>
</configuration>
3 分发配置到所有节点
for node in master slave1 slave2; do
scp ~/hadoop/etc/hadoop/{core-site.xml,hdfs-site.xml} hadoop@$node:~/hadoop/etc/hadoop/
done
步骤 3:初始化 HA 状态
3.1 启动 JournalNode(所有节点)
hdfs --daemon start journalnode
3.2 格式化第一个 NameNode(仅在 master)
# 如果已有数据,先备份!否则会丢失
hdfs namenode -format
3.3 启动 master的 NameNode
hdfs --daemon start namenode
3.4 在 slave1上同步元数据
hdfs namenode -bootstrapStandby
3.5 初始化 HA 状态到 ZooKeeper(任意NameNode 节点,即master和slave1其一)
hdfs zkfc -formatZK
步骤 4:启动整个 HA 集群
在 master:
start-dfs.sh # 会启动 NN、DN、JN、ZKFC
start-yarn.sh # RM 在 hadoop01(暂不配 YARN HA)
在 slave1:
# 如果 start-dfs.sh 没自动启动 standby NN,手动启(通常不需要)
hdfs --daemon start namenode
步骤 5:验证 HA
5.1 查看 NameNode 状态
hdfs haadmin -getServiceState nn1 # 应返回 active
hdfs haadmin -getServiceState nn2 # 应返回 standby
5.2 Web UI
- http://master:9870 → 显示 Active
- http://slave1:9870 → 显示 Standby
5.3 模拟故障切换
# 在 hadoop01 上杀死 NameNode
pkill -f NameNode
# 等待几秒后检查
hdfs haadmin -getServiceState nn2 # 应变为 active
恢复后,原 active 不会自动抢回(避免脑裂),需手动或配置自动恢复策略。
三、启动集群
初次启动时,可根据上面的内容。当机器关机之后,如何快速启动?
切换到hadoop用户(所有机器都需要)
su - hadoop
启动Zookeeper(所有机器都需要)
./zookeeper/bin/zkServer.sh start
查看Zookeeper集群状态
./zookeeper/bin/zkServer.sh status
使用jps查看
jps
1403 Jps
1308 QuorumPeerMain
启动hdfs(仅在Master机器执行)
start-dfs.sh
Starting namenodes on [master slave1]
Starting datanodes
Starting journal nodes [slave2 slave1 master]
Starting ZK Failover Controllers on NN hosts [master slave1]
验证hdfs,使用jps命令
jps
master节点
1795 JournalNode
2085 Jps
2005 DFSZKFailoverController
1308 QuorumPeerMain
1566 NameNode
slave1节点
1808 DFSZKFailoverController
1861 Jps
1273 QuorumPeerMain
1451 NameNode
1663 JournalNode
slave2节点
1457 DataNode
1570 JournalNode
1270 QuorumPeerMain
1647 Jps
启动yarn(仅在Master机器执行)
start-yarn.sh
Starting resourcemanager
Starting nodemanagers
验证yarn,使用jps命令
jps
master节点
2512 Jps
1795 JournalNode
2005 DFSZKFailoverController
2188 ResourceManager
1308 QuorumPeerMain
1566 NameNode
slave1节点
1808 DFSZKFailoverController
1941 NodeManager
2105 Jps
1273 QuorumPeerMain
1451 NameNode
1663 JournalNode
slave2节点
1457 DataNode
1570 JournalNode
1718 NodeManager
1270 QuorumPeerMain
1847 Jps