共计 6280 个字符,预计需要花费 16 分钟才能阅读完成。
导读 | HDFS 集群中 NameNode 存在单点故障(SPOF)。对于只有一个 NameNode 的集群,如果 NameNode 机器出现意外情况,将导致整个集群无法使用,直到 NameNode 重新启动。 |
影响 HDFS 集群不可用主要包括以下两种情况:一是 NameNode 机器宕机,将导致集群不可用,重启 NameNode 之后才可使用;二是计划内的 NameNode 节点软件或硬件升级,导致集群在短时间内不可用。
为了解决上述问题,Hadoop 给出了 HDFS 的高可用 HA 方案:HDFS 通常由两个 NameNode 组成,一个处于 active 状态,另一个处于 standby 状态。Active NameNode 对外提供服务,比如处理来自客户端的 RPC 请求,而 Standby NameNode 则不对外提供服务,仅同步 Active NameNode 的状态,以便能够在它失败时快速进行切换。
一个典型的 HA 集群,NameNode 会被配置在两台独立的机器上,在任何时间上,一个 NameNode 处于活动状态,而另一个 NameNode 处于备份状态,活动状态的 NameNode 会响应集群中所有的客户端,备份状态的 NameNode 只是作为一个副本,保证在必要的时候提供一个快速的转移。
为了让 Standby Node 与 Active Node 保持同步,这两个 Node 都与一组称为 JNS 的互相独立的进程保持通信 (Journal Nodes)。当 Active Node 上更新了 namespace,它将记录修改日志发送给 JNS 的多数派。Standby noes 将会从 JNS 中读取这些 edits,并持续关注它们对日志的变更。Standby Node 将日志变更应用在自己的 namespace 中,当 failover 发生时,Standby 将会在提升自己为 Active 之前,确保能够从 JNS 中读取所有的 edits,即在 failover 发生之前 Standy 持有的 namespace 应该与 Active 保持完全同步。
为了支持快速 failover,Standby node 持有集群中 blocks 的最新位置是非常必要的。为了达到这一目的,DataNodes 上需要同时配置这两个 Namenode 的地址,同时和它们都建立心跳链接,并把 block 位置发送给它们。
任何时刻,只有一个 Active NameNode 是非常重要的,否则将会导致集群操作的混乱,那么两个 NameNode 将会分别有两种不同的数据状态,可能会导致数据丢失,或者状态异常,这种情况通常称为“split-brain”(脑裂,三节点通讯阻断,即集群中不同的 Datanodes 却看到了两个 Active NameNodes)。对于 JNS 而言,任何时候只允许一个 NameNode 作为 writer;在 failover 期间,原来的 Standby Node 将会接管 Active 的所有职能,并负责向 JNS 写入日志记录,这就阻止了其他 NameNode 基于处于 Active 状态的问题。
基于 QJM 的 HDFS HA 方案如上图所示,其处理流程为:集群启动后一个 NameNode 处于 Active 状态,并提供服务,处理客户端和 DataNode 的请求,并把 editlog 写到本地和 share editlog(这里是 QJM)中。另外一个 NameNode 处于 Standby 状态,它启动的时候加载 fsimage,然后周期性的从 share editlog 中获取 editlog,保持与 Active 节点的状态同步。为了实现 Standby 在 Active 挂掉后迅速提供服务,需要 DataNode 同时向两个 NameNode 汇报,使得 Stadnby 保存 block to DataNode 信息,因为 NameNode 启动中最费时的工作是处理所有 DataNode 的 blockreport。为了实现热备,增加 FailoverController 和 Zookeeper,FailoverController 与 Zookeeper 通信,通过 Zookeeper 选举机制,FailoverController 通过 RPC 让 NameNode 转换为 Active 或 Standby。
NameNode 机器:两台配置对等的物理机器,它们分别运行 Active 和 Standby Node。
JouralNode 机器:运行 JouralNodes 的机器。JouralNode 守护进程相当的轻量级,可以和 Hadoop 的其他进程部署在一起,比如 NameNode、DataNode、ResourceManager 等,至少需要 3 个且为奇数,如果你运行了 N 个 JNS,那么它可以允许 (N-1)/ 2 个 JNS 进程失效并且不影响工作。
在 HA 集群中,Standby NameNode 还会对 namespace 进行 checkpoint 操作(继承 Backup Namenode 的特性),因此不需要在 HA 集群中运行 SecondaryNameNode、CheckpointNode 或者 BackupNode。
需要在 hdfs.xml 中配置如下参数:
dfs.nameservices:HDFS NN 的逻辑名称,例如 myhdfs。
dfs.ha.namenodes.myhdfs:给定服务逻辑名称 myhdfs 的节点列表,如 nn1、nn2。
dfs.namenode.rpc-address.myhdfs.nn1:myhdfs 中 nn1 对外服务的 RPC 地址。
dfs.namenode.http-address.myhdfs.nn1:myhdfs 中 nn1 对外服务 http 地址。
dfs.namenode.shared.edits.dir:JournalNode 的服务地址。
dfs.journalnode.edits.dir:JournalNode 在本地磁盘存放数据的位置。
dfs.ha.automatic-failover.enabled:是否开启 NameNode 失败自动切换。
dfs.ha.fencing.methods:配置隔离机制,通常为 sshfence。
HDFS 的自动故障转移主要由 Zookeeper 和 ZKFC 两个组件组成。
Zookeeper 集群作用主要有:一是故障监控。每个 NameNode 将会和 Zookeeper 建立一个持久 session,如果 NameNode 失效,那么此 session 将会过期失效,此后 Zookeeper 将会通知另一个 Namenode,然后触发 Failover;二是 NameNode 选举。ZooKeeper 提供了简单的机制来实现 Acitve Node 选举,如果当前 Active 失效,Standby 将会获取一个特定的排他锁,那么获取锁的 Node 接下来将会成为 Active。
ZKFC 是一个 Zookeeper 的客户端,它主要用来监测和管理 NameNodes 的状态,每个 NameNode 机器上都会运行一个 ZKFC 程序,它的职责主要有:一是健康监控。ZKFC 间歇性的 ping NameNode,得到 NameNode 返回状态,如果 NameNode 失效或者不健康,那么 ZKFS 将会标记其为不健康;二是 Zookeeper 会话管理。当本地 NaneNode 运行良好时,ZKFC 将会持有一个 Zookeeper session,如果本地 NameNode 为 Active,它同时也持有一个“排他锁”znode,如果 session 过期,那么次 lock 所对应的 znode 也将被删除;三是选举。当集群中其中一个 NameNode 宕机,Zookeeper 会自动将另一个激活。
YARN 的 HA 架构和 HDFSHA 类似,需要启动两个 ResourceManager,这两个 ResourceManager 会向 ZooKeeper 集群注册,通过 ZooKeeper 管理它们的状态(Active 或 Standby)并进行自动故障转移。
根据 Hadoop 的 HA 架构分析,规划整个集群由 5 台主机组成,具体情况如下表所示:
需要说明以下几点:
HDFS HA 通常由两个 NameNode 组成,一个处于 Active 状态,另一个处于 Standby 状态。Active NameNode 对外提供服务,而 Standby NameNode 则不对外提供服务,仅同步 Active NameNode 的状态,以便能够在它失败时快速进行切换。
Hadoop 2.0 官方提供了两种 HDFS HA 的解决方案,一种是 NFS,另一种是 QJM。这里我们使用简单的 QJM。在该方案中,主备 NameNode 之间通过一组 JournalNode 同步元数据信息,一条数据只要成功写入多数 JournalNode 即认为写入成功。通常配置奇数个 JournalNode,这里还配置了一个 Zookeeper 集群,用于 ZKFC 故障转移,当 Active NameNode 挂掉了,会自动切换 Standby NameNode 为 Active 状态。
YARN 的 ResourceManager 也存在单点故障问题,这个问题在 hadoop-2.4.1 得到了解决:有两个 ResourceManager,一个是 Active,一个是 Standby,状态由 zookeeper 进行协调。
YARN 框架下的 MapReduce 可以开启 JobHistoryServer 来记录历史任务信息,否则只能查看当前正在执行的任务信息。
Zookeeper 的作用是负责 HDFS 中 NameNode 主备节点的选举,和 YARN 框架下 ResourceManaer 主备节点的选举。
操作系统:CentOS Linux release 7.0.1406
JDK:Java(TM)SE Runtime Environment (build 1.7.0_79-b15)
Hadoop:Hadoop 2.6.0-cdh5.7.1
ZooKeeper:zookeeper-3.4.5-cdh5.7.1
集群各节点进行如下修改配置:
// 切换 root 用户
$ su root
// 创建 hadoop 用户组
# groupadd hadoop
// 在 hadoop 用户组中创建 hadoop 用户
# useradd -g hadoop hadoop
// 修改用户 hadoop 密码
# passwd hadoop
// 修改 sudoers 配置文件给 hadoop 用户添加 sudo 权限
# vim /etc/sudoers
hadoop ALL=(ALL) ALL
// 测试是否添加权限成功
# exit
$ sudo ls /root
// 切换 root 用户
$ su root
// 修改本机 IP 地址
# vim /etc/sysconfig/network-scripts/ifcfg-eth0
// 重启网络服务
# service network restart
// 修改主机名
# hostnamectl set-hostname 主机名
// 查看主机名
# hostnamectl status
// 切换 root 用户
$ su root
// 编辑 hosts 文件
# vim /etc/hosts
172.16.20.81 hadoop-master1
172.16.20.82 hadoop-master2
172.16.20.83 hadoop-slave1
172.16.20.84 hadoop-slave2
172.16.20.85 hadoop-slave3
// 切换 root 用户
$ su root
// 停止 firewall 防火墙
# systemctl stop firewalld.service
// 禁止 firewall 开机启动
# systemctl disable firewalld.service
// 开机关闭 Selinux
# vim /etc/selinux/config
SELINUX=disabled
// 重启机器后 root 用户查看 Selinux 状态
# getenforce
// 在 hadoop-master1 节点生成 SSH 密钥对
$ ssh-keygen -t rsa
// 将公钥复制到集群所有节点机器上
$ ssh-copy-id hadoop-master1
$ ssh-copy-id hadoop-master2
$ ssh-copy-id hadoop-slave1
$ ssh-copy-id hadoop-slave2
$ ssh-copy-id hadoop-slave3
// 通过 ssh 登录各节点测试是否免密码登录成功
$ ssh hadoop-master2
备注:在其余节点上执行同样的操作,确保集群中任意节点都可以 ssh 免密码登录到其它各节点。
// 卸载系统自带的 openjdk
$ suroot
# rpm-qa | grep java
# rpm-e --nodeps java-1.7.0-openjdk-1.7.0.75-2.5.4.2.el7_0.x86_64
# rpm-e --nodeps java-1.7.0-openjdk-headless-1.7.0.75-2.5.4.2.el7_0.x86_64
# rpm-e --nodeps tzdata-java-2015a-1.el7_0.noarch
# exit
// 解压 jdk 安装包
$ tar-xvf jdk-7u79-linux-x64.tar.gz
// 删除安装包
$ rmjdk-7u79-linux-x64.tar.gz
// 修改用户环境变量
$ cd ~
$ vim.bash_profile
exportJAVA_HOME=/home/hadoop/app/jdk1.7.0_79
exportPATH=$PATH:$JAVA_HOME/bin
// 使修改的环境变量生效
$ source.bash_profile
// 测试 jdk 是否安装成功
$ java-version
如果集群节点时间不同步,可能会出现节点宕机或引发其它异常问题,所以在生产环境中一般通过配置 NTP 服务器实现集群时间同步。本集群在 hadoop-master1 节点设置 ntp 服务器,具体方法如下:
// 切换 root 用户
$ su root
// 查看是否安装 ntp
# rpm -qa | grep ntp
// 安装 ntp
# yum install -y ntp
// 配置时间服务器
# vim /etc/ntp.conf
# 禁止所有机器连接 ntp 服务器
restrict default ignore
# 允许局域网内的所有机器连接 ntp 服务器
restrict 172.16.20.0 mask 255.255.255.0 nomodify notrap
# 使用本机作为时间服务器
server 127.127.1.0
// 启动 ntp 服务器
# service ntpd start
// 设置 ntp 服务器开机自动启动
# chkconfig ntpd on
集群其它节点通过执行 crontab 定时任务,每天在指定时间向 ntp 服务器进行时间同步,方法如下:// 切换 root 用户
$ su root
// 执行定时任务,每天 00:00 向服务器同步时间,并写入日志
# crontab -e
0 0 * * * /usr/sbin/ntpdate hadoop-master1>> /home/hadoop/ntpd.log
// 查看任务
# crontab -l
- Hadoop 2.6.0 HA 高可用集群配置详解(一)
- Hadoop 2.6.0 HA 高可用集群配置详解(二)
- Hadoop 2.6.0 HA 高可用集群配置详解(三)
![post-qrcode](https://www.xgss.net/wp-content/uploads/2023/07/二维码-微信公众号256x256.jpg)