HDFS+HA架构图
上图大致架构包括:
- 利用共享存储来在两个NN间同步edits信息。以前的HDFS是share nothing but NN,现在NN又share storage,这样其实是转移了单点故障的位置,但中高端的存储设备内部都有各种RAID以及冗余硬件,包括电源以及网卡等,比服务器的可靠性还是略有提高。通过NN内部每次元数据变动后的flush操作,加上NFS的close-to-open,数据的一致性得到了保证。
- DN同时向两个NN汇报块信息。这是让Standby NN保持集群的最新状态的必须步骤。
- 用于监视和控制NN进程的FailoverController进程。显然,我们不能在NN进程内部进行心跳等信息同步,最简单的原因,一次FullGC就可以让NN挂起十几分钟,所以,必须要有一个独立的短小精悍的watchdog来专门负责监控。这也是一个松耦合的设计,便于扩展或更改,目前版本里是用ZooKeeper(简称ZK)来做同步锁,但用户可以方便的把这个Zookeeper FailoverController(简称ZKFC)替换为其他的HA方案或leader选举方案。
- 隔离(Fencing),防止脑裂,就是保证在任何时候只有一个主NN,包括三个方面:
- 共享存储fencing,确保只有一个NN可以写入edits。
- 客户端fencing,确保只有一个NN可以响应客户端的请求。
- DN fencing,确保只有一个NN向DN下发命令,譬如删除块,复制块等等。
节点规划
hostname | ip | 安装服务 |
---|---|---|
zk1 | 192.168.1.1 | zookeeper |
zk2 | 192.168.1.2 | zookeeper |
zk3 | 192.168.1.3 | zookeeper |
提示:
zookeeper集群安装不在本文描述范围, 请自行参考其他文档。(zookeeper集群也可以跟datanode安装在一起)
hostname | ip | 安装服务 |
---|---|---|
nna | 192.168.1.4 | NameNode、DFSZKFailoverController |
nns | 192.168.1.5 | NameNode、DFSZKFailoverController |
dn1 | 192.168.1.6 | JournalNode、NodeManager、DataNode |
dn2 | 192.168.1.7 | JournalNode、NodeManager、DataNode |
dn3 | 192.168.1.8 | JournalNode、NodeManager、DataNode |
- namenode服务器: 运行namenode的服务器应该有相同的硬件配置。在HA集群中,standby状态的namenode可以完成checkpoint操作,因此没必要配置Secondary namenode、CheckpointNode、BackupNode。如果真的配置了还会报错。
- journalnode服务器: 运行的journalnode进程非常轻量,可以部署在其他的服务器上。注意:必须允许至少3个节点。当然可以运行更多,但是必须是奇数个,如3,5,7,9个等等。当运行N个节点时,系统可以容忍至少(N-1)/2个节点失败而不影响正常运行。
安装前准备
操作系统:CentOS 6.5 x86_64 JDK:1.8.0_74-b02 (JDK的安装本文不进行描述) Hadoop:hadoop-2.8.0.tar.gz Zookeeper: 3.4.6
安装过程
1. 主机名修改
登录nna
节点,修改/etc/hosts
文件,在后面追加如下内容:
192.168.1.1 zk1
192.168.1.2 zk2
192.168.1.3 zk3
192.168.1.4 nna
192.168.1.5 nns
192.168.1.6 dn1
192.168.1.7 dn2
192.168.1.8 dn3
分发到其它主机,下面以zk1
为例:
scp /etc/hosts root@zk1:/etc
2. 创建hadoop用户
登录除zk外的主机,分别创建hadoop
用户:
useradd hadoop
3. 添加ssh信任
su - hadoop
ssh-keygen -t rsa #一直按回车键,直到交互结束。会在 ~/.ssh/ 目录下生成 id_rsa.pub 文件
cat ~/.ssh/id_rsa.pub # 拷贝里面的内容
# 在所有主机中重复以上步骤
touch ~/.ssh/authorized_keys && chmod 644 ~/.ssh/authorized_keys
vi ~/.ssh/authorized_keys # 将所有主机的 id_rsa.pub 文件中的内容都拷贝到此文件中,并将此文件分发到所有主机。注意是hadoop用户下的 ~/.ssh/authorized_keys 文件
做完上述动作后,可以使用如下命令验证免密登录是否设置成功,若登录过程不需要输入密码则已设置成功:
su - hadoop
ssh nns
有必要在所有机器上都相互验证下。
4. 线程数与打开文件句柄数修改
Hdaoop会在同一时间使用很多的文件句柄.大多数linux系统使用的默认值1024是不能满足的。
编辑/etc/security/limits.conf
:
* soft nofile 65535
* hard nofile 65535
* soft nproc 16384
* hard nproc 16384
若操作系统为centos6.5,还需编辑/etc/security/limits.d/90-nproc.conf
:
* soft nproc 1024
root soft nproc unlimited
hadoop soft nproc 16384
hadoop hard nproc 16384
除zk外的主机,请都完成上述设置。
5. 关闭防火墙
由于hadoop的节点之间需要通信(RPC机制),这样一来就需要监听对应的端口,这里我就直接将防火墙关闭了,命令如下:
chkconfig iptables off
6. 开启时钟同步
各个节点的时间如果不同步,会出现启动异常,或其他原因。
service ntpd start
7. 环境变量配置
export JAVA_HOME=/usr/lib/java
export HADOOP_HOME=/home/hadoop/hadoop
export PATH=$PATH:$JAVA_HOME/bin:$HADOOP_HOME/bin:$HADOOP_HOME/sbin
8. 核心文件配置
创建文件夹:
mkdir -p /home/hadoop/tmp
mkdir -p /home/hadoop/data/tmp/journal
mkdir -p /home/hadoop/data/dfs/name
mkdir -p /home/hadoop/data/dfs/data
mkdir -p /home/hadoop/data/yarn/local
mkdir -p /home/hadoop/log/yarn
解压安装包:
tar -xzvf hadoop-2.8.0.tar.gz
ln -s hadoop-2.8.0 hadoop
- $HADOOP_HOME/etc/hadoop/core-site.xml
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://cluster1</value>
</property>
<property>
<name>io.file.buffer.size</name>
<value>131072</value>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/home/hadoop/tmp</value>
</property>
<property>
<name>hadoop.proxyuser.hadoop.hosts</name>
<value>*</value>
</property>
<property>
<name>hadoop.proxyuser.hadoop.groups</name>
<value>*</value>
</property>
<property>
<name>ha.zookeeper.quorum</name>
<value>zk1:2181,zk2:2181,zk3:2181</value>
</property>
</configuration>
- $HADOOP_HOME/etc/hadoop/hdfs-site.xml
<configuration>
<property>
<name>dfs.nameservices</name>
<value>cluster1</value>
</property>
<property>
<name>dfs.ha.namenodes.cluster1</name>
<value>nna,nns</value>
</property>
<property>
<name>dfs.namenode.rpc-address.cluster1.nna</name>
<value>nna:9000</value>
</property>
<property>
<name>dfs.namenode.rpc-address.cluster1.nns</name>
<value>nns:9000</value>
</property>
<property>
<name>dfs.namenode.http-address.cluster1.nna</name>
<value>nna:50070</value>
</property>
<property>
<name>dfs.namenode.http-address.cluster1.nns</name>
<value>nns:50070</value>
</property>
<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://dn1:8485;dn2:8485;dn3:8485/cluster1</value>
</property>
<property>
<name>dfs.client.failover.proxy.provider.cluster1</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.journalnode.edits.dir</name>
<value>/home/hadoop/data/tmp/journal</value>
</property>
<property>
<name>dfs.ha.automatic-failover.enabled</name>
<value>true</value>
</property>
<property>
<name>dfs.namenode.name.dir</name>
<value>/home/hadoop/data/dfs/name</value>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>/home/hadoop/data/dfs/data</value>
</property>
<property>
<name>dfs.replication</name>
<value>3</value>
</property>
<property>
<name>dfs.webhdfs.enabled</name>
<value>true</value>
</property>
<property>
<name>dfs.journalnode.http-address</name>
<value>0.0.0.0:8480</value>
</property>
<property>
<name>dfs.journalnode.rpc-address</name>
<value>0.0.0.0:8485</value>
</property>
<property>
<name>ha.zookeeper.quorum</name>
<value>zk1:2181,zk2:2181,zk3:2181</value>
</property>
</configuration>
- $HADOOP_HOME/etc/hadoop/mapred-site.xml
<configuration>
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
<property>
<name>mapreduce.jobhistory.address</name>
<value>nna:10020</value>
</property>
<property>
<name>mapreduce.jobhistory.webapp.address</name>
<value>nna:19888</value>
</property>
</configuration>
<configuration>
<property>
<name>hbase.rootdir</name>
<value>hdfs://cluster1/hbase</value>
</property>
<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>
<property>
<name>hbase.zookeeper.quorum</name>
<value>172.17.18.9:2181,172.17.18.112:2181,172.17.17.19:2181</value>
</property>
</configuration>
- $HADOOP_HOME/etc/hadoop/slaves
dn1
dn2
dn3
将配置好的hadoop复制到其它节点:
scp -r $HADOOP_HOME/ nns:~/
scp -r $HADOOP_HOME/ dn1:~/
scp -r $HADOOP_HOME/ dn2:~/
scp -r $HADOOP_HOME/ dn3:~/
9. 启动
由于我们配置了QJM,所以我们需要先启动QJM的服务,启动顺序如下所示:
- 启动zookeeper集群。启动完成之后可以输入
zkServer.sh status
查看启动状态,会出现一个leader和两个follower。输入jps
,会显示启动进程:QuorumPeerMain - 在NN节点上(选一台即可,这里我选择的是一台预NNA节点),然后启动journalnode服务,命令如下:
hadoop-daemons.sh start journalnode
。或者单独进入到每个DN输入启动命令:hadoop-daemon.sh start journalnode
。输入jps
显示启动进程:JournalNode - 接着若是配置后首次启动,需要格式化HDFS,命令如下:
hadoop namenode –format
- 之后我们需要格式化ZK,命令如下:
hdfs zkfc –formatZK
- 接着我们启动hdfs,命令如下:
start-dfs.sh
,我们在nna输入jps
查看进程,显示如下:DFSZKFailoverController,NameNode,ResourceManager。DN节点也会自动启动DataNode、NodeManager - 接着我们在NNS输入jps查看,发现只有DFSZKFailoverController进程,这里我们需要手动启动NNS上的namenode。命令如下:
hadoop-daemon.sh start namenode
- 最后我们需要同步NNA节点的元数据,命令如下:
hdfs namenode –bootstrapStandby
启动yarn:
- 接着上面的步骤,在NNA节点上:start-yarn.sh。输入jps查看进程,会发现多了:ResourceManager
- 登录NNS节点,使用:yarn-daemon.sh start resourcemanager。需要注意的是,在NNS上的yarn-site.xml中,需要配置指向NNS,属性配置为rm2,在NNA中配置的是rm1。
启动完成之后,可以访问:
hdfs: http://192.168.1.4:50770/dfshealth.html 或 http://192.168.1.5:50770/dfshealth.html (其中一个为“active”,一个为“standby”) resourcemanger: http://192.168.1.4:8188/cluster/cluster 或 http://192.168.1.5:8188/cluster/cluster
测试:
hadoop fs -mkdir hdfs:/test/
hadoop fs -copyFromLocal /home/hadoop/data/webcount hdfs:/test/
hadoop fs -ls hdfs:/test/
hadoop fs -cat hdfs:/test/webcount
HA的切换
由于我配置的是自动切换,若NNA节点宕掉,NNS节点会立即由standby状态切换为active状态。若是配置的手动状态,可以输入如下命令进行人工切换:
hdfs haadmin -failover --forcefence --forceactive nna nns
这条命令的意思是,将nna变成standby,nns变成active。而且手动状态下需要重启服务。
工具脚本
`
bash copy-config.sh
#!/bin/sh
scp /home/hadoop/hadoop/etc/hadoop/ nns:/home/hadoop/hadoop/etc/hadoop scp /home/hadoop/hadoop/etc/hadoop/ dn1:/home/hadoop/hadoop/etc/hadoop scp /home/hadoop/hadoop/etc/hadoop/ dn2:/home/hadoop/hadoop/etc/hadoop scp /home/hadoop/hadoop/etc/hadoop/ dn3:/home/hadoop/hadoop/etc/hadoop
scp /home/hadoop/hadoop/libexec/ nns:/home/hadoop/hadoop/libexec scp /home/hadoop/hadoop/libexec/ dn1:/home/hadoop/hadoop/libexec scp /home/hadoop/hadoop/libexec/ dn2:/home/hadoop/hadoop/libexec scp /home/hadoop/hadoop/libexec/ dn3:/home/hadoop/hadoop/libexec `