跳到主要内容

高可用配置

生产环境中,Hadoop 集群需要高可用(HA)配置,避免单点故障。本章将详细介绍 HDFS 和 YARN 的高可用配置方法。

高可用概述

单点故障问题

在非 HA 模式下,存在以下单点故障:

组件单点故障影响
NameNode整个集群不可用
ResourceManager无法提交新作业,运行中的作业不受影响

高可用方案

Hadoop 高可用通过主备切换实现:

前置条件

ZooKeeper 集群

高可用依赖 ZooKeeper 进行主备选举和协调:

# 在各 ZooKeeper 节点执行

# 下载 ZooKeeper
wget https://downloads.apache.org/zookeeper/zookeeper-3.8.0/apache-zookeeper-3.8.0-bin.tar.gz
tar -zxvf apache-zookeeper-3.8.0-bin.tar.gz -C /opt/

# 配置 zoo.cfg
cat > /opt/zookeeper/conf/zoo.cfg << EOF
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/opt/zookeeper/data
clientPort=2181
server.1=zk1:2888:3888
server.2=zk2:2888:3888
server.3=zk3:2888:3888
EOF

# 创建 myid 文件
echo "1" > /opt/zookeeper/data/myid

# 启动 ZooKeeper
/opt/zookeeper/bin/zkServer.sh start

SSH 免密登录

确保各节点之间可以免密登录:

# 生成密钥
ssh-keygen -t rsa

# 复制公钥到其他节点
ssh-copy-id node2
ssh-copy-id node3

HDFS 高可用配置

集群规划

以 3 节点集群为例:

节点NameNodeDataNodeJournalNodeZooKeeper
node1Active-
node2Standby
node3-

配置文件

core-site.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 集群名称 -->
<property>
<name>fs.defaultFS</name>
<value>hdfs://mycluster</value>
</property>

<!-- 临时目录 -->
<property>
<name>hadoop.tmp.dir</name>
<value>/opt/hadoop/tmp</value>
</property>

<!-- ZooKeeper 地址 -->
<property>
<name>ha.zookeeper.quorum</name>
<value>node1:2181,node2:2181,node3:2181</value>
</property>

<!-- 代理用户 -->
<property>
<name>hadoop.proxyuser.hadoop.hosts</name>
<value>*</value>
</property>
<property>
<name>hadoop.proxyuser.hadoop.groups</name>
<value>*</value>
</property>
</configuration>

hdfs-site.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 定义集群名称 -->
<property>
<name>dfs.nameservices</name>
<value>mycluster</value>
</property>

<!-- 定义 NameNode 标识 -->
<property>
<name>dfs.ha.namenodes.mycluster</name>
<value>nn1,nn2</value>
</property>

<!-- NameNode RPC 地址 -->
<property>
<name>dfs.namenode.rpc-address.mycluster.nn1</name>
<value>node1:8020</value>
</property>
<property>
<name>dfs.namenode.rpc-address.mycluster.nn2</name>
<value>node2:8020</value>
</property>

<!-- NameNode HTTP 地址 -->
<property>
<name>dfs.namenode.http-address.mycluster.nn1</name>
<value>node1:9870</value>
</property>
<property>
<name>dfs.namenode.http-address.mycluster.nn2</name>
<value>node2:9870</value>
</property>

<!-- JournalNode 地址 -->
<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://node1:8485;node2:8485;node3:8485/mycluster</value>
</property>

<!-- JournalNode 数据目录 -->
<property>
<name>dfs.journalnode.edits.dir</name>
<value>/opt/hadoop/data/journalnode</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.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>

<!-- 启用自动故障转移 -->
<property>
<name>dfs.ha.automatic-failover.enabled</name>
<value>true</value>
</property>

<!-- 数据目录 -->
<property>
<name>dfs.namenode.name.dir</name>
<value>/opt/hadoop/data/namenode</value>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>/opt/hadoop/data/datanode</value>
</property>

<!-- 副本数 -->
<property>
<name>dfs.replication</name>
<value>3</value>
</property>

<!-- 权限检查 -->
<property>
<name>dfs.permissions.enabled</name>
<value>false</value>
</property>
</configuration>

启动步骤

# 1. 启动 ZooKeeper(在各 ZooKeeper 节点执行)
zkServer.sh start

# 2. 启动 JournalNode(在各 JournalNode 节点执行)
hdfs --daemon start journalnode

# 3. 格式化 NameNode(在第一个 NameNode 执行)
hdfs namenode -format

# 4. 启动第一个 NameNode
hdfs --daemon start namenode

# 5. 同步第二个 NameNode(在第二个 NameNode 执行)
hdfs namenode -bootstrapStandby

# 6. 启动第二个 NameNode
hdfs --daemon start namenode

# 7. 初始化 ZooKeeper 故障转移(在任一 NameNode 执行)
hdfs zkfc -formatZK

# 8. 启动 ZKFC(在各 NameNode 执行)
hdfs --daemon start zkfc

# 9. 启动 DataNode(在各 DataNode 执行)
hdfs --daemon start datanode

验证高可用

# 查看 NameNode 状态
hdfs haadmin -getAllServiceState

# 手动切换 Active
hdfs haadmin -transitionToActive nn2

# 模拟故障
# 杀掉 Active NameNode 进程,观察是否自动切换
kill -9 <namenode-pid>

YARN 高可用配置

集群规划

节点ResourceManagerNodeManager
node1Active-
node2Standby
node3-

配置文件

yarn-site.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 启用 RM HA -->
<property>
<name>yarn.resourcemanager.ha.enabled</name>
<value>true</value>
</property>

<!-- 集群 ID -->
<property>
<name>yarn.resourcemanager.cluster-id</name>
<value>yarn-cluster</value>
</property>

<!-- RM 标识 -->
<property>
<name>yarn.resourcemanager.ha.rm-ids</name>
<value>rm1,rm2</value>
</property>

<!-- RM 主机名 -->
<property>
<name>yarn.resourcemanager.hostname.rm1</name>
<value>node1</value>
</property>
<property>
<name>yarn.resourcemanager.hostname.rm2</name>
<value>node2</value>
</property>

<!-- RM Web UI 地址 -->
<property>
<name>yarn.resourcemanager.webapp.address.rm1</name>
<value>node1:8088</value>
</property>
<property>
<name>yarn.resourcemanager.webapp.address.rm2</name>
<value>node2:8088</value>
</property>

<!-- ZooKeeper 地址 -->
<property>
<name>yarn.resourcemanager.zk-address</name>
<value>node1:2181,node2:2181,node3:2181</value>
</property>

<!-- 自动恢复 -->
<property>
<name>yarn.resourcemanager.recovery.enabled</name>
<value>true</value>
</property>

<!-- 状态存储类 -->
<property>
<name>yarn.resourcemanager.store.class</name>
<value>org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore</value>
</property>

<!-- NodeManager 配置 -->
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<property>
<name>yarn.nodemanager.resource.memory-mb</name>
<value>8192</value>
</property>
<property>
<name>yarn.nodemanager.resource.cpu-vcores</name>
<value>8</value>
</property>

<!-- 调度器配置 -->
<property>
<name>yarn.scheduler.minimum-allocation-mb</name>
<value>1024</value>
</property>
<property>
<name>yarn.scheduler.maximum-allocation-mb</name>
<value>8192</value>
</property>

<!-- 日志聚合 -->
<property>
<name>yarn.log-aggregation-enable</name>
<value>true</value>
</property>
</configuration>

启动步骤

# 1. 确保 ZooKeeper 已启动

# 2. 启动 ResourceManager(在各 RM 节点执行)
yarn --daemon start resourcemanager

# 3. 启动 NodeManager(在各 NM 节点执行)
yarn --daemon start nodemanager

验证高可用

# 查看 RM 状态
yarn rmadmin -getAllServiceState

# 手动切换 Active
yarn rmadmin -transitionToActive rm2

# 模拟故障
kill -9 <rm-pid>

故障转移控制器

ZKFC(ZooKeeper Failover Controller)

ZKFC 运行在每个 NameNode 上,负责:

  1. 健康检查:定期检查 NameNode 状态
  2. 会话管理:维护与 ZooKeeper 的会话
  3. 选举触发:当 Active 故障时触发选举

ZKFC 配置

<!-- 健康检查间隔 -->
<property>
<name>ha.zookeeper.acl-znode-parent</name>
<value>/hadoop-ha/mycluster</value>
</property>

<!-- 健康检查超时 -->
<property>
<name>ha.failover-controller.new-active.rpc-timeout.ms</name>
<value>60000</value>
</property>

运维操作

手动故障转移

# HDFS 手动切换
hdfs haadmin -transitionToStandby nn1
hdfs haadmin -transitionToActive nn2

# YARN 手动切换
yarn rmadmin -transitionToStandby rm1
yarn rmadmin -transitionToActive rm2

查看状态

# 查看 HDFS NameNode 状态
hdfs haadmin -getAllServiceState
hdfs haadmin -getServiceState nn1

# 查看 YARN ResourceManager 状态
yarn rmadmin -getAllServiceState
yarn rmadmin -getServiceState rm1

故障恢复

当 Active 节点故障恢复后:

# 启动恢复的节点
hdfs --daemon start namenode

# 查看状态(应该是 Standby)
hdfs haadmin -getServiceState nn1

# 如需切换为 Active
hdfs haadmin -transitionToActive nn1

小结

本章介绍了 Hadoop 高可用的配置方法:

  1. HDFS 高可用:通过 Active/Standby NameNode 和 JournalNode 实现。

  2. YARN 高可用:通过 Active/Standby ResourceManager 和 ZooKeeper 实现。

  3. 故障转移:ZKFC 自动检测故障并触发切换。

高可用配置是生产环境部署的必备条件,可以避免单点故障导致的集群不可用问题。