HDFS HA配置的完整步骤
部分内容参考了这篇文章: http://blog.csdn.net/dmcpxy/article/details/18256607 。其中配置文件时基于我的集群信息做的,还增加了配置中遇到的问题和解决办法。
最近了解了Hadoop后,又开始涉及Hadoop 2.0相关的知识,所以后续我会陆陆续续把2.0相关的一些知识和学习总结整理上来。
这里是QJM方式的HA配置,众所周知,HDFS HA一般是基于NFS公共存储的,这里不采用NFS。
主要步骤:
1. zookeeper集群配置
2. HDFS HA参数配置
3. HDFS HA启动
4. 验证测试
1. zookeeper集群配置
说明: 我是在2台机器上做的配置,貌似zookeeper推荐用奇数台机器进行搭建,一般选3台。所以两台不推荐啊不推荐。
下载zookeeper的压缩包,并且解压,我的安装包目录是/search/zookeeper/zookeeper-3.4.5/,因为是HDFS 2.0,所以相应的zookeeper的版本也不能太低,免得出现兼容性问题。
(2) 同时建立日志存放目录:
mkdir /search/zookeeper/dataDir/logs/
(3) 在zookeeper安装包中,/conf下的zoo_sample.cfg拷贝一份,命名为zoo.cfg,这是zookeeper的配置文件:
cp zoo_sample.cfg zoo.cfg
(4) 在zoo.cfg文件是进行配置:
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/search/zookeeper/dataDir/
dataLogDir=/search/zookeeper/dataDir/logs/
clientPort=21810
#server.id in cluster = ip:port used in communicating with leader : port used when choosing a new leader
server.1=10.14.131.47:28880:38880
server.2=10.14.135.11:28880:38880
(5) 在每台服务器的dataDir目录下分别创建一个叫myid的文件,内容分别是1,2,如:
#在10.14.131.47上执行如下命令
echo 1 >/search/zookeeper/dataDir/myid
#在10.14.135.11上执行如下命令
echo 2 >/search/zookeeper/dataDir/myid
(6) 最后就是分别启动zookeeper服务了:
./bin/zkServer.sh start
(7) 通过jps命令可以检查是否启动成功:
1239 QuorumPeerMain
#看到QuorumPeerMain进程就表示zookeeper启动成功了。
(8) 测试zookeeper集群是否建立成功,在安装包目录下执行以下命令即可,如无报错表示集群创建成功:
./bin/zkCli.sh -server localhost:21810
2. HDFS2.0 HA参数配置
HA相关的配置是在core-site.xml和hdfs-site.xml中,当把这两个配置文件修改完成后,需要停止hadoop服务,然后同步修改后的配置信息到每个节点上。
说明: 这里的配置,都是基于已经成功配置了Hadoop 2.0集群的前提下,所以其他的一些配置信息没有列出。
3. HDFS HA启动
(1) 启动zookeeper集群: 在每个zookeeper的机器上执行:
./bin/zkServer.sh start
#据说集群会自动把第一个启动的机器作为leader。who knows ~~
(2) 在某一个namenode节点执行如下命令,创建命名空间
./bin/hdfs zkfc -formatZK
(3) 在各个节点用如下命令启日志程序
./sbin/hadoop-daemon.sh start journalnode
#如果Hadoop集群比较大的话,这真是个吃力不讨好的工作。所以我写了个脚本来实现它。
(4) 在主namenode节点用./bin/hadoopnamenode -format格式化namenode和journalnode目录
./bin/hadoop namenode -format mycluster
#namenode节点在初始化时,也将自己的edits文件共享到了journalnode上。
(5) 在主namenode节点启动namenode进程
./sbin/hadoop-daemon.sh start namenode
(6) 在备节点启动备namenode进程
a) ./bin/hdfs namenode –bootstrapStandby
#这个命令是把备namenode节点的目录格式化,并且把主namenode的元数据和journalnode上的edits文件同步过来,从而使元数据和主namenode保持一致,并且这个命令不会把journalnode目录再格式化。
ERROR: 不过我在执行bootstrapStandby时失败了,具体失败的体现是下一步启动备namenode失败,报错信息是缺少$dfs.tmp.dir/data/下的name目录。因为name目录下保存的都是namenode的基本元数据,所以说明这一步的格式化没有成功。
SOLUTION: 手工把主namenode上的元数据($dfs.namenode.name.dir下的所有数据)拷贝到备namenode下的同目录下,然后再执行bootstrapStandby.
b) ./sbin/hadoop-daemon.sh start namenode
#启动备namenode。
(7) 在两个namenode节点都启动ZKFC:
./sbin/hadoop-daemon.sh start zkfc
#启动DFSZKFailoverController,也就是用于监控namenode并且保持HA状态的那个watchdog。
(8) 在所有datanode节点都执行以下命令启动datanode
./sbin/hadoop-daemon.sh start datanode
#这个步骤略坑爹,因为节点很多。最好直接在namenode节点上执行 sbin/hadoop-daemons.sh start datanode 启动。
ERROR: 启动Datanode可能失败,失败报错信息为
2014-03-13 11:26:30,788 FATAL org.apache.hadoop.hdfs.server.datanode.DataNode: Initialization failed for block pool Block pool BP-1257313099-10.10.208.38-1394679083528 (storage id DS-743638901-127.0.0.1-50010-1394616048958) service to Linux-hadoop-38/10.10.208.38:9000
java.io.IOException: Incompatible clusterIDs in /usr/local/hadoop/tmp/dfs/data: namenode clusterID = CID-8e201022-6faa-440a-b61c-290e4ccfb006; datanode clusterID = clustername
错误提示很明显,Datanode节点初始化失败,和hadoop.tmp.dir目录有关系。一般是因为,我们的Hadoop集群不是首次启动,所以版本信息产生冲突。
hdfs haadmin -failover --forcefence --forceactive <serviceId> <serviceId>
#这个命令的作用我不是很清楚,到底哪个serviceId会被切换成Active。或者用下面的命令:
bin/hdfs haadmin -transitionToActive nn1
此时进行检查,HDFS集群应该已经全部正常启动了。下次再启动时,直接执行./sbin/start-dfs.sh就好。关闭直接执行./sbin/stop-dfs.sh就好。
4. 测试HA的功能
(1) 在Active namenode节点上先jps找到namenode的进程号,然后kill -9杀死namenode进程。观察standby namenode节点的状态变化。
jps
kill -9 pid_namenode
(2) 观察standby节点是否自动切换成了Active:
通过web界面查看,括号内显示的状态从standby变成了active;
观察zkfc日志(logs/.....-zkfc.......log),最后一行出现如下日志,表示切换成功:
INFOorg.apache.hadoop.ha.ZKFailoverController: Successfully transitioned NameNodeat hd0/192.168.111.130:53310 to active state
(3) 启动被kill掉的namenode
./sbin/hadoop-daemon.sh start namenode
(4) 观察该namenode节点的状态:
通过web界面查看,括号内显示的状态为standby;
观察zkfc日志(logs/.....-zkfc.......log),最后一行出现如下日志,表示该节点作为standby节点已经正常启动:
INFOorg.apache.hadoop.ha.ZKFailoverController: Successfully transitioned NameNodeat hd2/192.168.111.132:53310 to standby state
部分内容参考了这篇文章: http://blog.csdn.net/dmcpxy/article/details/18256607 。其中配置文件时基于我的集群信息做的,还增加了配置中遇到的问题和解决办法。
最近了解了Hadoop后,又开始涉及Hadoop 2.0相关的知识,所以后续我会陆陆续续把2.0相关的一些知识和学习总结整理上来。
这里是QJM方式的HA配置,众所周知,HDFS HA一般是基于NFS公共存储的,这里不采用NFS。
主要步骤:
1. zookeeper集群配置
2. HDFS HA参数配置
3. HDFS HA启动
4. 验证测试
1. zookeeper集群配置
说明: 我是在2台机器上做的配置,貌似zookeeper推荐用奇数台机器进行搭建,一般选3台。所以两台不推荐啊不推荐。
下载zookeeper的压缩包,并且解压,我的安装包目录是/search/zookeeper/zookeeper-3.4.5/,因为是HDFS 2.0,所以相应的zookeeper的版本也不能太低,免得出现兼容性问题。
(1) 首先建立zookeeper的数据目录,比如:
mkdir /search/zookeeper/dataDir(2) 同时建立日志存放目录:
mkdir /search/zookeeper/dataDir/logs/
(3) 在zookeeper安装包中,/conf下的zoo_sample.cfg拷贝一份,命名为zoo.cfg,这是zookeeper的配置文件:
cp zoo_sample.cfg zoo.cfg
(4) 在zoo.cfg文件是进行配置:
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/search/zookeeper/dataDir/
dataLogDir=/search/zookeeper/dataDir/logs/
clientPort=21810
#server.id in cluster = ip:port used in communicating with leader : port used when choosing a new leader
server.1=10.14.131.47:28880:38880
server.2=10.14.135.11:28880:38880
(5) 在每台服务器的dataDir目录下分别创建一个叫myid的文件,内容分别是1,2,如:
#在10.14.131.47上执行如下命令
echo 1 >/search/zookeeper/dataDir/myid
#在10.14.135.11上执行如下命令
echo 2 >/search/zookeeper/dataDir/myid
(6) 最后就是分别启动zookeeper服务了:
./bin/zkServer.sh start
(7) 通过jps命令可以检查是否启动成功:
1239 QuorumPeerMain
#看到QuorumPeerMain进程就表示zookeeper启动成功了。
(8) 测试zookeeper集群是否建立成功,在安装包目录下执行以下命令即可,如无报错表示集群创建成功:
./bin/zkCli.sh -server localhost:21810
2. HDFS2.0 HA参数配置
HA相关的配置是在core-site.xml和hdfs-site.xml中,当把这两个配置文件修改完成后,需要停止hadoop服务,然后同步修改后的配置信息到每个节点上。
说明: 这里的配置,都是基于已经成功配置了Hadoop 2.0集群的前提下,所以其他的一些配置信息没有列出。
(1) core-site.xml
<property>
<name>fs.defaultFS</name>
<value>hdfs://mycluster</value>
</property>
<property>
<name>ha.zookeeper.quorum</name>
<value>10.14.131.47:21810,10.14.135.11:21810</value>
</property>
<property>
<name>ha.zookeeper.session-timeout.ms</name>
<value>1000</value>
<description>ms</description>
</property>
(2) hdfs-site.xml
<!-- HA config start -->
<property>
<name>dfs.webhdfs.enabled</name>
<value>true</value>
</property>
<!-- the name service -->
<property>
<name>dfs.nameservices</name>
<value>mycluster</value>
<description>Logical name for this newnameservice</description>
</property>
<!-- the node in this name service -->
<property>
<name>dfs.ha.namenodes.mycluster</name>
<value>nn1,nn2</value>
<description>Unique identifiers for each NameNode in thenameservice</description>
</property>
<!-- the rpc port of each node -->
<property>
<name>dfs.namenode.rpc-address.mycluster.nn1</name>
<value>10.14.143.83:8022</value>
</property>
<property>
<name>dfs.namenode.rpc-address.mycluster.nn2</name>
<value>10.14.131.47:8022</value>
</property>
<!-- the http address of each namenode -->
<property>
<name>dfs.namenode.http-address.mycluster.nn1</name>
<value>10.14.143.83:50070</value>
</property>
<property>
<name>dfs.namenode.http-address.mycluster.nn2</name>
<value>10.14.131.47:50070</value>
</property>
<!-- shared storage -->
<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://10.14.131.47:8485;10.14.135.11:8485/mycluster</value>
</property>
<!-- the agent for HA auto switch -->
<property>
<name>dfs.client.failover.proxy.provider.mycluster</name>
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>
<!-- the fencing mathod -->
<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>
<!-- journalnode config -->
<property>
<name>dfs.journalnode.edits.dir</name>
<value>/search/hadoop01/journalnode/</value>
</property>
<!-- <property>
<name>dfs.journalnode.rpc-address</name>
<value>0.0.0.0:20022</value>
</property> -->
<!-- must be the HA auto switch or not -->
<property>
<name>dfs.ha.automatic-failover.enabled</name>
<value>true</value>
</property>
<!-- HA config end -->
3. HDFS HA启动
(1) 启动zookeeper集群: 在每个zookeeper的机器上执行:
./bin/zkServer.sh start
#据说集群会自动把第一个启动的机器作为leader。who knows ~~
(2) 在某一个namenode节点执行如下命令,创建命名空间
./bin/hdfs zkfc -formatZK
(3) 在各个节点用如下命令启日志程序
./sbin/hadoop-daemon.sh start journalnode
#如果Hadoop集群比较大的话,这真是个吃力不讨好的工作。所以我写了个脚本来实现它。
(4) 在主namenode节点用./bin/hadoopnamenode -format格式化namenode和journalnode目录
./bin/hadoop namenode -format mycluster
#namenode节点在初始化时,也将自己的edits文件共享到了journalnode上。
(5) 在主namenode节点启动namenode进程
./sbin/hadoop-daemon.sh start namenode
(6) 在备节点启动备namenode进程
a) ./bin/hdfs namenode –bootstrapStandby
#这个命令是把备namenode节点的目录格式化,并且把主namenode的元数据和journalnode上的edits文件同步过来,从而使元数据和主namenode保持一致,并且这个命令不会把journalnode目录再格式化。
ERROR: 不过我在执行bootstrapStandby时失败了,具体失败的体现是下一步启动备namenode失败,报错信息是缺少$dfs.tmp.dir/data/下的name目录。因为name目录下保存的都是namenode的基本元数据,所以说明这一步的格式化没有成功。
SOLUTION: 手工把主namenode上的元数据($dfs.namenode.name.dir下的所有数据)拷贝到备namenode下的同目录下,然后再执行bootstrapStandby.
b) ./sbin/hadoop-daemon.sh start namenode
#启动备namenode。
(7) 在两个namenode节点都启动ZKFC:
./sbin/hadoop-daemon.sh start zkfc
#启动DFSZKFailoverController,也就是用于监控namenode并且保持HA状态的那个watchdog。
(8) 在所有datanode节点都执行以下命令启动datanode
./sbin/hadoop-daemon.sh start datanode
#这个步骤略坑爹,因为节点很多。最好直接在namenode节点上执行 sbin/hadoop-daemons.sh start datanode 启动。
ERROR: 启动Datanode可能失败,失败报错信息为
2014-03-13 11:26:30,788 FATAL org.apache.hadoop.hdfs.server.datanode.DataNode: Initialization failed for block pool Block pool BP-1257313099-10.10.208.38-1394679083528 (storage id DS-743638901-127.0.0.1-50010-1394616048958) service to Linux-hadoop-38/10.10.208.38:9000
java.io.IOException: Incompatible clusterIDs in /usr/local/hadoop/tmp/dfs/data: namenode clusterID = CID-8e201022-6faa-440a-b61c-290e4ccfb006; datanode clusterID = clustername
错误提示很明显,Datanode节点初始化失败,和hadoop.tmp.dir目录有关系。一般是因为,我们的Hadoop集群不是首次启动,所以版本信息产生冲突。
SOLUTION: 对比master节点上dfs.namenode.name.dir目录下,current文件夹中的VERSION文件的内容,和slave节点上hadoop.tmp.dir目录下,data/current/目录下的VERSION文件的内容,会发现他们的内容不一致,很有可能是这个VERSION是Datanode在没有配置HA之前的集群中使用的VERSION,所以Datanode无法正常启动。删除slave上的VERSION文件,再启动就成功了。
(9) 通过web界面查看两个namenode的状态,如果都处在standby状态的话,就把其中一个namenode切换成Active状态。hdfs haadmin -failover --forcefence --forceactive <serviceId> <serviceId>
#这个命令的作用我不是很清楚,到底哪个serviceId会被切换成Active。或者用下面的命令:
bin/hdfs haadmin -transitionToActive nn1
此时进行检查,HDFS集群应该已经全部正常启动了。下次再启动时,直接执行./sbin/start-dfs.sh就好。关闭直接执行./sbin/stop-dfs.sh就好。
4. 测试HA的功能
(1) 在Active namenode节点上先jps找到namenode的进程号,然后kill -9杀死namenode进程。观察standby namenode节点的状态变化。
jps
kill -9 pid_namenode
(2) 观察standby节点是否自动切换成了Active:
通过web界面查看,括号内显示的状态从standby变成了active;
观察zkfc日志(logs/.....-zkfc.......log),最后一行出现如下日志,表示切换成功:
INFOorg.apache.hadoop.ha.ZKFailoverController: Successfully transitioned NameNodeat hd0/192.168.111.130:53310 to active state
(3) 启动被kill掉的namenode
./sbin/hadoop-daemon.sh start namenode
(4) 观察该namenode节点的状态:
通过web界面查看,括号内显示的状态为standby;
观察zkfc日志(logs/.....-zkfc.......log),最后一行出现如下日志,表示该节点作为standby节点已经正常启动:
INFOorg.apache.hadoop.ha.ZKFailoverController: Successfully transitioned NameNodeat hd2/192.168.111.132:53310 to standby state