『数人之道』原创文章,转载请关注本公众号联系我们
文章大纲:
本期主要介绍 Hadoop HA 完全分布式模式的部署。HA 完全分布式模式(Highly Available Fully-Distributed Mode)是生产环境上最常见的 Hadoop 安装部署方式。HA 即高可用,是指当当前工作中的机器宕机后,会自动处理这个异常,并将工作无缝地转移到集群中的其他备用机器上去,以保证服务的高可用性。
这次我们在《第三篇:Hadoop部署配置及运行调试(中)》部署的完全分布式 Hadoop 的基础上搭建 HA 环境,不再另外安装新的 Hadoop 进行 HA 部署。
由于 Hadoop HA 完全分布式部署所涉及到的原理较为复杂,且需要修改较多的参数,因此本期的内容会较之前都丰富,有兴趣的同学请耐心读完并跟着动手操作,以加深对 Hadoop 的认识。
1 服务器功能规划
类似完全分布式的部署,由于涉及多台服务器,部署前需要做好各服务器节点的功能规划。我们在完全分布式部署规划的基础上增加 NameNode 及 ResourceManager 的节点,并在各台机器上部署 Zookeeper 管理分布式协作,另外还需要一台时间服务器(NTP)和一台安全代理服务器(ProxyServer)。
2 时间服务器
Hadoop 对集群中各个机器的时间同步要求比较高,要求各个机器的系统时间尽量一致,不然会造成很多问题。例如 YARN 调度作业任务的时候,若各机器的时间不统一,会造成作业依赖混乱。配置时间同步有两种方式:一种是与互联网的时间服务器进行同步;另一种是在局域网搭建一台时间服务器(NTP),集群内各个机器与这台 NTP 服务器进行时间同步。在实际的生产环境中,集群内大部分机器是不能连接外网的,因此后者较为常用。
由于 CentOS8 中已经默认不再支持 ntpd 软件包,因此这里使用chrony进行时间服务器配置及同步。chrony 与 ntpd / ntpdata 最大的区别是:chrony 通过减慢时钟或者加快时钟的方式进行连续修正,平滑地同步时间,可以更快且更准确地同步系统时钟,最大程度地减少时间和频率误差,其既可充当客户端也可充当服务端;ntpd / ntpdata 需搭配定时任务计划 crontab 使用,通过直接调整时间的方式进行同步,会造成时间的跳跃,且相同的时间可能会出现两次,对一些依赖时间的程序和服务会造成影响。
chrony 有两个核心组件 chronyd 和 chronyc:
- chronyd:守护进程,主要用于调整内核中运行的系统时间和时间服务器同步,它确定计算机增减时间的比率,并对此进行调整补偿。
- chronyc:提供一个用户界面,用于监控性能并进行多样化的配置,它可以在 chronyd 实例控制的计算机上工作,也可以在一台不同的远程计算机上工作。
注意:以下操作均需使用 root 用户执行!
2.1 搭建及配置时间服务器
根据服务器功能规划,我们在 hadoop102 上搭建 NTP 服务器,其他两台机器作为客户端与 NTP 服务器进行时间同步。
2.1.1. 检查 chrony 服务是否安装
执行以下命令检查 chrony 服务是否已经在各个机器上安装:
代码语言:shell复制rpm -qa | grep chrony
若显示 chrony 软件包名称表明已经安装:
若没有安装,使用以下命令进行安装:
代码语言:shell复制yum install chrony
2.1.2. 配置 chrony 服务器端
在 hadoop102 上修改 chrony 配置文件:/etc/chrony.conf
代码语言:shell复制vim /etc/chrony.conf
(1) 配置时间服务器地址:
代码语言:shell复制# Please consider joining the pool (http://www.pool.ntp.org/join.html).
# pool 2.centos.pool.ntp.org iburst --注释这一行
server 192.168.100.12 iburst #添加这一行,配置时间服务器地址为hadoop102机器的ip地址
(2) 配置允许访问及同步时间的服务器地址(即客户端地址):
这里配置跟服务器端同网段地址的机器允许访问及同步服务器端时间:
代码语言:shell复制# Allow NTP client access from local network.
#allow 192.168.0.0/16
allow 192.168.100.0/24 #只允许192.168.100.0网段的客户端进行时间同步
(3) 配置服务器端,使其在配置的时间服务器不可用时,允许将本地时间作为标准时间授时给其它客户端:
代码语言:shell复制# Serve time even if not synchronized to a time source.
local stratum 10 ##去掉这行注释
2.1.3. 重启服务器端 chrony 服务
(1) 完成服务器端的配置修改后,重启 chrony 服务:
代码语言:shell复制systemctl restart chronyd.service
(2) 查看服务器端 chronyd 服务的状态:
代码语言:shell复制systemctl status chronyd.service
2.1.4. 设置服务器端 chrony 服务开机启动
执行以下命令设置服务器端 chrony 服务开机即自动启动:
代码语言:javascript复制systemctl enable chronyd.service
2.2 配置其他机器(客户端)同步时间
在其他机器(客户端)上配置 chrony 服务,同步服务器端的时间。
2.2.1. 配置 chrony 客户端
在 hadoop100 及 101 上修改 chrony 配置文件:/etc/chrony.conf
代码语言:shell复制vim /etc/chrony.conf
(1) 配置时间服务器地址:
代码语言:shell复制# Please consider joining the pool (http://www.pool.ntp.org/join.html).
# pool 2.centos.pool.ntp.org iburst --注释这一行
server 192.168.100.12 iburst #添加这一行,配置时间服务器地址为hadoop102机器的ip地址
(2) 禁用 chronyd 启动时间限制,偏移大于1秒随时步进调整系统时钟:
代码语言:shell复制# Allow the system clock to be stepped in the first three updates
# if its offset is larger than 1 second.
# makestep 1.0 3
makestep 1.0 -1
2.2.2. 重启客户端 chrony 服务
(1) 完成客户端的配置修改后,重启 chrony 服务:
代码语言:javascript复制systemctl restart chronyd.service
(2) 查看客户端 chronyd 服务的状态:
代码语言:javascript复制systemctl status chronyd.service
2.2.3. 设置客户端 chrony 服务开机启动
执行以下命令设置客户端 chrony 服务开机即自动启动:
代码语言:javascript复制systemctl enable chronyd.service
2.2.4. 查看时间同步状态
在客户端机器中可使用以下命令查看时间同步状态及时间偏差量:
(1) 查看时间同步状态:
代码语言:shell复制chronyc sources -v
^ 符号旁边有 * 号表示同步成功:
(2) 查看时间偏差量:
代码语言:javascript复制chronyc sourcestats -v
(3) 查看时间同步信息:
代码语言:javascript复制timedatectl
2.2.5. 手工同步时间
chrony 服务启动后,客户端一旦出现时间与服务器端不一致的情况,便会自动通过平滑方式校正,无需跟 ntpd 一样使用 crontab 定时同步时间。
当然,也可以通过以下命令手工同步时间:
代码语言:javascript复制chronyc -a makestep
2.3 测试时间同步是否生效
2.3.1. 查看三台机器目前的时间
在各个服务器上执行 date 命令查看机器目前的时间:
代码语言:javascript复制date
2.3.2. 修改 hadoop100 上的时间
在 hadoop100 上执行以下命令,修改客户端机器的时间:
代码语言:javascript复制date -s "5 day"
2.3.3. 查看 hadoop100 是否能自动与 NTP 服务器同步
(1) 在 hadoop100 上查看 chronyd 服务的状态:
代码语言:javascript复制systemctl status chronyd.service
(2) 在 hadoop100 上查看时间同步状态:
代码语言:javascript复制chronyc sources -v
可以看到,hadoop100 客户端机器的时间自动同步为服务器端的时间。
3 Zookeeper 部署
根据服务器功能规划,我们在三台节点机器上安装 Zookeeper 集群,这也符合 Zookeeper 集群需安装奇数台机器的原则。
3.1 安装 Zookeeper
将下载的 Zookeeper 压缩包上传到 hadoop100 机器的 /opt/softwares 目录,这里使用的是 3.6.3 稳定版本。
下载地址: https://zookeeper.apache.org/releases.html
将 Zookeeper 压缩包解压到 /opt/modules 目录下安装:
代码语言:shell复制tar -zxvf /opt/softwares/apache-zookeeper-3.6.3-bin.tar.gz -C /opt/modules/
注意:建议下载带有 bin 的安装包,不带 bin 的安装包需要下载后编译打包才能使用。
3.2 配置 Zookeeper
安装完成后对 Zookeeper 进行配置。
3.2.1. 创建 Zookeeper 数据文件的存放目录
在 Zookeeper 的目录下创建 /data/zkData 文件夹,用于存放 Zookeeper 的数据文件:
代码语言:shell复制mkdir -p /opt/modules/apache-zookeeper-3.6.3-bin/data/zkData
3.2.2. 修改 Zookeeper 的配置文件 zoo.cfg
(1) 将 /conf 下的配置文件 zoo_sample.cfg 的名称重命名为 zoo.cfg:
代码语言:shell复制mv /opt/modules/apache-zookeeper-3.6.3-bin/conf/zoo_sample.cfg zoo.cfg
(2) 修改 dataDir 参数:
修改 zoo.cfg 配置文件中的 dataDir 参数,此参数是用于配置 Zookeeper 数据文件的存储路径:
代码语言:shell复制# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just
# example sakes.
# dataDir=/tmp/zookeeper
dataDir=/opt/modules/apache-zookeeper-3.6.3-bin/data/zkData
(3) 指定 Zookeeper 集群各个机器信息:
在配置文件中增加如下信息,指定集群机器:
代码语言:shell复制####################cluster####################
server.1=hadoop100:2888:3888
server.2=hadoop101:2888:3888
server.3=hadoop102:2888:3888
机器信息配置解析:
- server 后面的数字表示这是第几号服务器,范围是 1-255,所以一个 Zookeeper 集群最多可以有 255 台机器
- 2888 是这台服务器与集群中的 Leader 服务器交换信息的端口号
- 3888 是用于执行选举时,服务器之间相互通信的端口号,一旦 Leader 服务器挂掉,会通过此端口进行选举,重新选出新的 Leader
3.2.3. 配置服务器编号
在 dataDir 参数所指定的目录下创建一个名称为 myid 的文件,文件内容为 server 后面的数字,即服务器编号:
代码语言:shell复制touch /opt/modules/apache-zookeeper-3.6.3-bin/data/zkData/myid
echo 1 >> /opt/modules/apache-zookeeper-3.6.3-bin/data/zkData/myid
3.3 分发 Zookeeper
在 hadoop100 机器上完成 Zookeeper 安装及配置后,将 Zookeeper 文件分发到另外两台机器上,并修改 myid 文件。
3.3.1. 使用 scp 方式分发文件
使用 scp 安全拷贝的方式,将 hadoop100 上的 Zookeeper 文件分发给另外两台机器:
代码语言:shell复制scp -r /opt/modules/apache-zookeeper-3.6.3-bin/ hadoop@hadoop101:/opt/modules/
scp -r /opt/modules/apache-zookeeper-3.6.3-bin/ hadoop@hadoop102:/opt/modules/
3.3.2. 修改 myid 文件
修改 hadoop101 及 hadoop102 上的 myid 文件,将 hadoop100 的服务器编号更改为对应服务器的编号:
在 hadoop101 上执行命令:
代码语言:shell复制echo 2 > /opt/modules/apache-zookeeper-3.6.3-bin/data/zkData/myid
在 hadoop102 上执行命令:
代码语言:shell复制echo 3 > /opt/modules/apache-zookeeper-3.6.3-bin/data/zkData/myid
3.4 启动 Zookeeper
Zookeeper 是 C/S 模式架构的软件,因此跟 chrony 一样既有服务端也有客户端,启动服务端后,可在客户端执行各种 Zookeeper 命令的操作。
3.4.1. 启动 Zookeeper 服务端
(1) 按以下顺序在三台机器上分别启动 Zookeeper 服务端:hadoop100 > hadoop101 > hadoop102:
代码语言:shell复制sh /opt/modules/apache-zookeeper-3.6.3-bin/bin/zkServer.sh start
(2) 用 jps 在三台机器上检查 Zookeeper 服务的启动情况:
(3) 在三台机器上执行以下命令查看 Zookeeper 服务的状态:
代码语言:shell复制sh /opt/modules/apache-zookeeper-3.6.3-bin/bin/zkServer.sh status
可以看到 hadoop100 及 hadoop102 是 Follower, 而 hadoop101 是 Leader. 根据《第四篇:Hadoop HA 完全分布式工作机制》的1.3 节“Zookeeper 的选举机制”中的知识,这是由于 hadoop101 的启动处于第二顺位,hadoop101 推荐自己为 Leader, 而已经启动的 hadoop100 同意它为 Leader, 这时已经有超过半数机器同意,因此 hadoop101 自动当选为 Leader.
3.4.2. 启动 Zookeeper 客户端
执行以下命令进入 Zookeeper 的客户端:
代码语言:shell复制sh /opt/modules/apache-zookeeper-3.6.3-bin/bin/zkCli.sh
在《第四篇:Hadoop HA 完全分布式工作机制》的1.2 节“Zookeeper 的节点类型”中介绍过,Zookeeper 类似一个小型文件系统,/ 是其根目录,下面所有节点称作 zNode.
在 Zookeeper 客户端中输入任意字符可列出所有 Zookeeper 命令:
Zookeeper 客户端命令使用示例:
- 创建一个 zNode:create /znode1 "demodata"
- 查询 zNode 上的数据:get /znode1
- 列出所有子 zNode:ls /
- 删除 zNode:delete /znode1
- 退出客户端模式:quit
4 HDFS HA 部署
根据服务器功能规划,我们在 hadoop100 及 hadoop101 上部署 NameNode, 并使用 Zookeeper 进行故障自动切换,来实现 HDFS HA 环境。
4.1 修改参数配置
4.1.1. 配置 hdfs-site.xml
在 hadoop100 上添加并修改 hdfs-site.xml 配置文件中涉及 HA 部署的各项参数值。
hdfs-site.xml 各参数默认值及描述检索地址: https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/hdfs-default.xml
(1) dfs.nameservices
此参数用以指定 NameNode 集群的 Services Name 逻辑名称 ID, 并使用这个 ID 作为配置选项的值,后续配置参数将引用该 ID. 这里设置为 mycluster.
添加以下内容修改此参数值,指定 HDFS 的 nameservices 逻辑名称:
代码语言:shell复制<property>
<name>dfs.nameservices</name>
<value>mycluster</value>
</property>
(2) dfs.ha.namenodes.EXAMPLENAMESERVICE
此参数用以指定 nameservices 包含的每个 NameNode 的唯一标识符,参数值是一个以逗号分隔的 NameNode ID 列表,这将被 DataNode 用于确定集群中的所有 NameNode. 这里设置两个 NameNode 的 ID 分别为 nn1, nn2.
注意:
- EXAMPLENAMESERVICE 需修改为上面指定的 nameservices 名称
- 每个 nameservice 只能配置最多两个 NameNode
添加以下内容修改此参数值,指定 NameNode 的名称:
代码语言:javascript复制<property>
<name>dfs.ha.namenodes.mycluster</name>
<value>nn1,nn2</value>
</property>
(3) dfs.namenode.rpc-address
此参数用以配置 NameNode 的 rpc 通信地址和端口号(Hadoop 2.x 版本的默认端口号为 8020),用来和 DataNode 进行通信监听。由于规划 hadoop100 及 hadoop101 部署 NameNode, 因此设置为其地址。
参数名称格式:
代码语言:javascript复制dfs.namenode.rpc-address.<nameservices>.<namenode>
添加以下内容修改此参数值,配置 NameNode 的 rpc 通信地址:
代码语言:javascript复制<property>
<name>dfs.namenode.rpc-address.mycluster.nn1</name>
<value>hadoop100:8020</value>
</property>
<property>
<name>dfs.namenode.rpc-address.mycluster.nn2</name>
<value>hadoop101:8020</value>
</property>
(4) dfs.namenode.http-address
此参数用以配置 NameNode 的 http 通信监听地址和端口号(端口号为 50070),用来访问 Web 页面客户端。由于规划 hadoop100 及 hadoop101 部署 NameNode, 因此设置为其地址。
参数名称格式:
代码语言:javascript复制dfs.namenode.http-address.<nameservices>.<namenode>
添加以下内容修改此参数值,配置 NameNode 的 http 通信地址:
代码语言:javascript复制<property>
<name>dfs.namenode.http-address.mycluster.nn1</name>
<value>hadoop100:50070</value>
</property>
<property>
<name>dfs.namenode.http-address.mycluster.nn2</name>
<value>hadoop101:50070</value>
</property>
(5) dfs.namenode.shared.edits.dir
此参数用以指定 NameNode 元数据的 EditLog 在共享存储系统 QJM 的 JournalNode 节点列表(形式为 URI 地址),以供 Active NN 将 EditLog 写入这些 JN, Standby NN 通过 JN 读取 EditLog, 并存储在内存的目录树中。JN 节点之间使用分号分隔,通信端口号为 8485.
参数值格式:
代码语言:javascript复制qjournal://host1:port1;host2:port2;host3:port3/<nameservices>
添加以下内容修改此参数值,指定 NameNode 的 JournalNode 节点列表:
代码语言:javascript复制<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://hadoop100:8485;hadoop101:8485;hadoop102:8485/mycluster</value>
</property>
(6) dfs.journalnode.edits.dir
此参数用以指定 JournalNode 上 EditLog 文件及其他状态信息的存储路径,默认路径为:/tmp/hadoop/dfs/journalnode/. 操作系统一旦重启会清空 /tmp 目录下的文件,因此需要修改此参数值,并手动创建设置的路径。
添加以下内容修改此参数值,指定 JournalNode 上日志文件的存放目录:
代码语言:javascript复制<property>
<name>dfs.journalnode.edits.dir</name>
<value>/opt/data/tmp/journal</value>
</property>
(7) dfs.client.failover.proxy.provider
此参数用以指定 HDFS 客户端与 Active NameNode 进行交互的 Java 实现类,通过该类寻找当前的 Active NameNode. 目前 Hadoop 的唯一实现是 ConfiguredFailoverProxyProvider 类,除非我们自己对其定制,否则应该使用这个类。
参数名称格式:
代码语言:javascript复制dfs.client.failover.proxy.provider.<nameservices>
添加以下内容修改此参数值,指定客户端连接 Active NameNode 的 Java 类:
代码语言:javascript复制<property>
<name>dfs.client.failover.proxy.provider.mycluster</name>
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>
(8) dfs.ha.fencing.methods
此参数用以配置 HDFS HA 的围栏机制,用以故障切换期间隔离 Active NN, 以解决 HA 集群的脑裂问题(此问题解析详见《第四篇:Hadoop HA 完全分布式工作机制》的2.3 节“主备故障自动切换机制”)。
JournalNode 只允许一个 NameNode 写数据,不会出现两个 Active NN, 但当主备切换时,之前的 Active NN 可能仍在处理客户端的 RPC 请求,为此,需要增加围栏机制将之前的 Active NN 隔离。常用的围栏方法是 sshfence.
添加以下内容修改此参数值,配置 HDFS HA 的围栏机制:
代码语言:javascript复制<property>
<name>dfs.ha.fencing.methods</name>
<value>sshfence</value>
</property>
(9) dfs.ha.fencing.ssh.private-key-files
此参数用以指定 ssh 通信使用的私钥文件在系统中的存放路径。由于指定了 sshfence 隔离机制,需用到 ssh 的私钥解密,因此要指定 ssh 私钥的存放路径。在《第三篇:Hadoop部署配置及运行调试(中)》的2.4节“配置SSH免密码登录”中介绍过 ssh 公私钥的生成步骤用于免密登录,这里使用此生成的路径。
添加以下内容修改此参数值,指定 ssh 私钥的路径:
代码语言:javascript复制<property>
<name>dfs.ha.fencing.ssh.private-key-files</name>
<value>/home/hadoop/.ssh/id_rsa</value>
</property>
(10) dfs.ha.automatic-failover.enabled
此参数用以配置是否开启利用 Zookeeper 集群实现主备故障自动切换,默认值为 false, 这里设置为 true, 开启故障自动切换机制。
添加以下内容修改此参数值,配置故障自动切换机制为开启:
代码语言:javascript复制<property>
<name>dfs.ha.automatic-failover.enabled</name>
<value>true</value>
</property>
4.1.2. 配置 core-site.xml
在 hadoop100 上添加并修改 core-site.xml 配置文件中涉及 HA 部署的各项参数值。
core-site.xml 各参数默认值及描述检索地址: https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-common/core-default.xml
(1) fs.defaultFS
此参数用以指定 HDFS 中 NameNode 的地址,由于 HA 环境中 HDFS 有不止一个 NameNode, 因此需要修改为 nameservices 的逻辑名称。
修改此参数值,指定 HA NameNode 地址:
代码语言:javascript复制<property>
<name>fs.defaultFS</name>
<value>hdfs://mycluster</value>
</property>
(2) hadoop.tmp.dir
此参数用以指定 Hadoop 运行时产生的缓存文件的存储路径,无需修改,继续使用原来指定的路径:/opt/data/tmp
(3) ha.zookeeper.quorum
此参数用以指定 Zookeeper 集群节点的地址(使用的端口号为 2181),各台机器的地址用逗号分隔。
添加以下内容修改此参数值,指定 Zookeeper 的地址:
代码语言:javascript复制<property>
<name>ha.zookeeper.quorum</name>
<value>hadoop100:2181,hadoop101:2181,hadoop102:2181</value>
</property>
4.2 分发文件
在 hadoop100 机器上完成配置文件修改后,将文件分发到另外两台机器上,并创建相应的 JournalNode 目录。
4.2.1. 使用 rsync 方式分发文件
使用 rsync 增量同步的方式将修改后的配置文件分发给另外两台机器:
代码语言:shell复制rsync -rvl /opt/modules/app/hadoop-2.10.1/etc/hadoop/ hadoop@hadoop101:/opt/modules/app/hadoop-2.10.1/etc/hadoop/
rsync -rvl /opt/modules/app/hadoop-2.10.1/etc/hadoop/ hadoop@hadoop102:/opt/modules/app/hadoop-2.10.1/etc/hadoop/
4.2.2. 创建目录
由于在 hdfs-site.xml 配置文件中指定的 JournalNode 文件存储目录并不存在,需要手动进行创建:
代码语言:shell复制mkdir -p /opt/data/tmp/journal
注意,三台机器都需要进行此目录的创建。
4.3 初始化集群
在启动 HDFS HA 集群前,需要先对 ZKFC 及 NameNode 进行初始化。
4.3.1. 格式化 ZKFC
(1) 启动 Zookeeper 服务端:
参考 3.4 节的方法启动三台节点机器的 Zookeeper 服务端,若已启动则忽略此步骤。
(2) 在 hadoop100 机器上执行以下命令对 ZKFC 进行格式化操作:
代码语言:shell复制hdfs zkfc -formatZK
执行完成后,会自动创建一个以 nameservices 名称命名存储 NameNode 相关的 zNode 节点:
可进入 Zookeeper 客户端查看验证初始化是否成功:
4.3.2. 格式化 NameNode
(1) 由于不是首次初始化 NameNode, 因此要在三台节点机器上执行以下命令删除 HDFS 的数据文件及 log 日志:
代码语言:shell复制rm -rf /opt/data/tmp/dfs/
rm -rf /opt/modules/app/hadoop-2.10.1/logs/*out*
rm -rf /opt/modules/app/hadoop-2.10.1/logs/*log
数据文件的路径为 core-site.xml 文件中 hadoop.tmp.dir 参数配置的值。
执行这一步骤的具体原因详见《第三篇:Hadoop部署配置及运行调试(上)》中的伪分布式模式部署3-(3)-(e).
(2) 在三台节点机器上执行以下命令启动 journalnode:
代码语言:shell复制${HADOOP_HOME}/sbin/hadoop-daemon.sh start journalnode
启动后使用 jps 检查是否启动成功。
(3) 在 hadoop100 机器上执行以下命令对 NameNode 进行格式化操作:
代码语言:javascript复制hdfs namenode -format
格式化完成后,查看 hadoop.tmp.dir 设置的目录下是否有dfs目录,如果有,说明格式化成功。
(4) 使用 scp 安全拷贝的方式,将格式化后的元数据目录分发到 hadoop101 机器上:
代码语言:shell复制scp -r /opt/data/tmp/dfs/ hadoop@hadoop101:/opt/data/tmp/
(5) 在三台节点机器上执行以下命令关闭 journalnode:
代码语言:shell复制${HADOOP_HOME}/sbin/hadoop-daemon.sh stop journalnode
关闭后使用 jps 检查是否关闭成功。
4.4 启动集群
一切配置及初始化工作完成后,即可启动 HDFS HA 集群。
4.4.1. 启动 Zookeeper
参考 3.4 节的方法启动三台节点机器的 Zookeeper 服务端,若已启动则忽略此步骤。
4.4.2. 启动 HDFS HA
在 hadoop100 机器上执行以下命令启动 HDFS HA 集群:
代码语言:shell复制${HADOOP_HOME}/sbin/start-dfs.sh
可以看到,启动命令分别在 hadoop100 及 hadoop101 节点上启动了 NameNode 和 ZKFC(ZKFC 只针对 NameNode 进行监听), 另外分别在三个节点上启动了 DataNode 和 JournalNode.
在三台节点机器上使用 jps 检查 HDFS HA 集群启动的情况:
4.5 运行调试
对 HDFS HA 集群进行调试,测试文件同步及故障自动切换功能。
4.5.1. 查看 NameNode 状态
在 HDFS Web 页面查看两个 NameNode 目前的状态:
(1) 在浏览器中输入地址:http://hadoop100:50070/, 通过Web页面查看 hadoop100 节点的 NameNode 状态:
或者在 hadoop100 或 hadoo101 上执行以下命令查看 nn1 的状态:
代码语言:shell复制hdfs haadmin -getServiceState nn1
可以看到 nn1 的状态是 active.
(2) 在浏览器中输入地址:http://hadoop101:50070/, 通过Web页面查看 hadoop101 节点的 NameNode 状态:
可以看到 nn2 的状态是 standby.
(3) 若两个 NameNode 均为 Standby 状态,执行以下命令手动将 nn1 设置为 Active:
代码语言:shell复制hdfs haadmin -transitionToActive -forcemanual nn1
4.5.2. 上传文件到 Active HDFS
在 Active NameNode(nn1)的机器上执行以下命令,在 HDFS 上创建输入目录,并将本地文件上传到该 HDFS 目录下:
代码语言:shell复制hdfs dfs -mkdir /input
hdfs dfs -put /opt/data/wc.input /input
4.5.3. 测试故障自动切换功能
(1) 将 nn1 节点上的 NameNode 进程杀掉:
在 hadoop100 机器上执行以下命令查看 NameNode 的进程 pid:
代码语言:shell复制ps -ef | grep NameNode
执行 kill 命令强制杀掉 NameNode 进程:
代码语言:shell复制kill -9 17758
(2) 观察 nn1 上的 NameNode 是否已经无法访问:
(3) 查看 nn2 是否是 Active 状态:
可在 hadoop100 或 hadoop101 节点上执行以下命令查看 nn2 的状态:
代码语言:shell复制hdfs haadmin -getServiceState nn2
也可以直接在 nn2 的 Web 页面中查看:
可以看到 nn2 已经自动切换为 Active 状态,表明故障自动切换成功。
(4) 若杀掉 nn1 的 NameNode 进程后,nn2 仍处于 Standby 状态,即故障自动切换失败,可查看日志追溯原因:
代码语言:shell复制view /opt/modules/app/hadoop-2.10.1/logs/hadoop-hadoop-zkfc-hadoop100.log
根据经验,很大概率是因为之前设置 SSH 免密登录时生成的私钥文件无法被解析,导致无法隔离 nn1 防止脑裂。
解决方法:删除 ~/.ssh 目录,并使用以下命令代替之前的公私钥生成命令再重新执行《第三篇:Hadoop部署配置及运行调试(中)》的2.4节“配置SSH免密码登录”中的 SSH 免密登录配置步骤:
代码语言:shell复制ssh-keygen -t rsa -m PEM
4.5.4. 测试文件同步功能
在 nn2 上查看是否能显示在 nn1 中上传的文件内容:
若能查看到之前上传的文件内容,表明文件同步成功。
经以上测试验证,我们搭建的 HDFS HA 集群已经成功实现了两个 NameNode 之间的文件同步和故障自动切换功能,达到 HA 的目标。
5 YARN HA 部署
根据服务器功能规划,我们在 hadoop101 及 hadoop102 上部署 ResourceManager, 并使用 Zookeeper 进行故障自动切换,来实现 YARN HA 环境。
5.1 修改参数配置
配置 yarn-site.xml
在 hadoop100 上添加并修改 yarn-site.xml 配置文件中涉及 HA 部署的各项参数值。
yarn-site.xml 各参数默认值及描述检索地址: https://hadoop.apache.org/docs/stable/hadoop-yarn/hadoop-yarn-common/yarn-default.xml
(1) yarn.resourcemanager.ha.enabled
此参数用以配置是否启用 ResourceManager HA 功能,默认值为 false, 这里设置为 true, 启用此功能。
添加以下内容修改此参数值,配置开启 ResourceManager HA 功能:
代码语言:javascript复制<property>
<name>yarn.resourcemanager.ha.enabled</name>
<value>true</value>
</property>
注意:此功能启用后会默认开启故障自动切换机制,因此无需再另外配置参数 yarn.resourcemanager.ha.automatic-failover.enabled。
(2) yarn.resourcemanager.cluster-id
此参数用以指定 ResourceManager 在 HA 集群中的标识,用于参与选举并确保 RM 不会接管另一个集群(即不会成为其他集群的 Active RM)。若设置了该参数,需要确保所有 RM 在配置中都有自己的 ID. 这里设置为 yarncluster.
添加以下内容修改此参数值,指定 ResourceManager 的标识:
代码语言:javascript复制<property>
<name>yarn.resourcemanager.cluster-id</name>
<value>yarncluster</value>
</property>
(3) yarn.resourcemanager.ha.rm-ids
此参数用以指定 ResourceManager 的逻辑名称 ID, 参数值是一个以逗号分隔的 RM ID 列表,后续配置参数将引用这些 ID. 这里设置两个 RM 的 ID 分别为 rm1, rm2.
添加以下内容修改此参数值,指定 ResourceManager 的名称:
代码语言:javascript复制<property>
<name>yarn.resourcemanager.ha.rm-ids</name>
<value>rm1,rm2</value>
</property>
(4) yarn.resourcemanager.hostname
此参数用以指定每个 ResourceManager 节点对应所在的机器主机名,可设置 RM 的服务地址。由于规划 hadoop101 及 hadoop102 部署 ResourceManager, 需修改此参数之前设置的参数值为两个节点的主机名。
参数名称格式:
代码语言:javascript复制yarn.resourcemanager.hostname.<rm-ids>
修改此参数值,指定 ResourceManager 对应的主机名:
代码语言:javascript复制<property>
<name>yarn.resourcemanager.hostname.rm1</name>
<value>hadoop101</value>
</property>
<property>
<name>yarn.resourcemanager.hostname.rm2</name>
<value>hadoop102</value>
</property>
(5) yarn.resourcemanager.webapp.address
此参数用以配置 ResourceManager 的 http 通信监听地址和端口号(端口号为 8088),用来访问 Web 页面客户端。由于规划 hadoop101 及 hadoop102 部署 ResourceManager, 因此设置为其地址。
参数名称格式:
代码语言:javascript复制yarn.resourcemanager.webapp.address.<rm-ids>
添加以下内容修改此参数值,配置 ResourceManager 的 http 通信地址:
代码语言:javascript复制<property>
<name>yarn.resourcemanager.webapp.address.rm1</name>
<value>hadoop101:8088</value>
</property>
<property>
<name>yarn.resourcemanager.webapp.address.rm2</name>
<value>hadoop102:8088</value>
</property>
(6) yarn.resourcemanager.zk-address
此参数用以指定集成的 Zookeeper 集群节点的地址(使用的端口号为 2181),各台机器的地址用逗号分隔。
添加以下内容修改此参数值,指定 Zookeeper 的地址:
代码语言:javascript复制<property>
<name>yarn.resourcemanager.zk-address</name>
<value>hadoop100:2181,hadoop101:2181,hadoop102:2181</value>
</property>
(7) yarn.resourcemanager.recovery.enabled
此参数用以配置是否启用重启 ResourceManager 后保留其恢复状态的功能,默认值为 false, 这里设置为 true, 以开启此功能。
启用后,支持 RM 重启过程中,不影响正在运行的作业,即重启后作业还能正常继续运行直到结束。开启此功能需声明存储介质(见下一个参数)。
添加以下内容修改此参数值,配置开启 ResourceManager 重启后保留恢复状态:
代码语言:javascript复制<property>
<name>yarn.resourcemanager.recovery.enabled</name>
<value>true</value>
</property>
(8) yarn.resourcemanager.store.class
此参数用以指定 ResourceManager 将应用的状态等信息保存到哪种存储介质中,用于 RM 重启后加载这些信息,且 NodeManager 会将仍在运行的 container 信息同步给 RM, 整个过程不影响作业的正常运行。
存储介质方式有三种,对应不同的 Java 类,默认使用的是 Hadoop 的文件存储系统类 FileSystemRMStateStore. 这里修改为选择 Zookeeper 作为存储介质,使用 ZKRMStateStore 类。
添加以下内容修改此参数值,指定 ResourceManager 的信息存储 Java 类:
代码语言:javascript复制<property>
<name>yarn.resourcemanager.store.class</name>
<value>org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore</value>
</property>
注意:另外还需要配置参数 yarn.resourcemanager.zk-state-store.parent-path, 指定信息存储在 Zookeeper 中的位置。这里使用此参数默认值 /rmstore, 无需修改。
(9) yarn.web-proxy.address
此参数用以配置访问 YARN 的 Web 客户端的 Proxy 安全代理。根据服务器功能规划,这里配置为 hadoop101 机器,其端口号为 8888.
在 ResourceManager 中包含 web-proxy 工程,可以启动一个单独的进程,对外提供 Web 服务,从 RM 上点击正在执行的作业,会跳转到此参数配置的地址上,以提高访问集群的安全性,防止 YARN 被攻击;若此参数没有配置,则这个功能默认集成到 RM 中。
添加以下内容修改此参数值,配置 YARN 的 Proxy 安全代理:
代码语言:javascript复制<property>
<name>yarn.web-proxy.address</name>
<value>hadoop101:8888</value>
</property>
注意:配置此参数后需启动 proxyserver 服务才能生效。
5.2 分发文件
在 hadoop100 机器上完成配置文件修改后,将文件分发到另外两台节点机器上。
使用 rsync 增量同步的方式将修改后的配置文件分发给另外两台机器:
代码语言:shell复制rsync -rvl /opt/modules/app/hadoop-2.10.1/etc/hadoop/ hadoop@hadoop101:/opt/modules/app/hadoop-2.10.1/etc/hadoop/
rsync -rvl /opt/modules/app/hadoop-2.10.1/etc/hadoop/ hadoop@hadoop102:/opt/modules/app/hadoop-2.10.1/etc/hadoop/
同步后到另外两台机器检查是否同步成功。
5.3 启动集群
5.3.1. 启动 YARN HA
(1) 在 hadoop101 机器上执行以下命令启动 YARN HA 集群:
代码语言:shell复制${HADOOP_HOME}/sbin/start-yarn.sh
可以看到,此启动命令在 hadoop101 节点上启动了 ResourceManager, 另外分别在三个节点上启动了 NodeManager. hadoop102 节点上的 RM 需手工进行启动。
(2) 在 hadoop102 机器上执行以下命令手工启动 ResourceManager 服务:
代码语言:shell复制${HADOOP_HOME}/sbin/yarn-daemon.sh start resourcemanager
5.3.2. 启动 proxyserver
在 hadoop101 机器上执行以下命令启动 proxyserver 服务,充当防火墙的角色,提高集群访问的安全性:
代码语言:shell复制${HADOOP_HOME}/sbin/yarn-daemon.sh start proxyserver
5.3.3. 启动 historyserver
在 hadoop100 机器上执行以下命令启动 historyserver 服务,historyserver 的介绍详见《第三篇:Hadoop部署配置及运行调试(上)》2.二.2:
代码语言:shell复制${HADOOP_HOME}/sbin/mr-jobhistory-daemon.sh start historyserver
5.3.4. 检查启动情况
在三台节点机器上使用 jps 检查 Hadoop HA 集群的启动情况:
5.4 运行调试
对 YARN HA 集群进行调试,测试 ResourceManager 重启保留恢复状态及故障自动切换功能。
5.4.1. 查看 ResourceManager 状态
在 YARN Web 页面查看两个 ResourceManager 的状态:
(1) 在浏览器中输入地址:http://hadoop101:8088/, 通过 Web 页面查看 hadoop101 节点的 RM 状态:
图5-4-1:查看 rm1 的状态
或者在 hadoop101 或 hadoop102 上执行以下命令查看 rm1 的状态:
代码语言:shell复制yarn rmadmin -getServiceState rm1
可以看到 rm1 能正常访问,状态是 active.
(2) 在浏览器中输入地址:http://hadoop102:8088/, 通过 Web 页面查看 hadoop102 节点的 RM 状态:
或者在 hadoop101 或 hadoop102 上执行以下命令查看 rm2 的状态:
代码语言:shell复制yarn rmadmin -getServiceState rm2
可以看到,访问 rm2 的页面会自动跳转到 rm1 上,状态是 standy.
5.4.2. 运行作业
在 hadoop100 机器上使用上传至 HDFS 的输入数据文件运行 Hadoop 自带的 WordCount MR 程序作业:
代码语言:shell复制yarn jar $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.10.1.jar wordcount /input/wc.input /output
5.4.3. 测试故障自动切换功能
(1) 在作业运行过程中,将 rm1 节点上的 ResourceManager 进程杀掉:
在 hadoop101 机器上执行以下命令查看 ResourceManager 的进程 pid:
代码语言:shell复制ps -ef | grep ResourceManager
执行 kill 命令强制杀掉 RM 进程:
代码语言:shell复制kill -9 29883
(2) 观察 rm2 上的 ResourceManager 是否可以自动接替:
可在 hadoop101 或 hadoop102 节点上执行以下命令查看 rm2 的状态:
代码语言:shell复制yarn rmadmin -getServiceState rm2
也可以直接在 rm2 的 Web 页面中查看:
可以看到 rm2 已经自动切换为 Active 状态,接管作业的调度,表明故障自动切换成功。
5.4.4. 测试重启保留恢复状态功能
观察作业是否能顺利执行完成且没有中断:
查看作业的输出结果文件:
可以看到,作业成功运行完成,结果正常,表明重启后保留恢复状态的功能成功,没有因为 rm1 的意外故障而影响当前作业的运行。
经以上测试验证,我们搭建的 YARN HA 集群已经成功实现了重启能保留作业恢复状态信息和故障自动切换功能,达到 HA 的目标。