hadoop的安装有单机版本,伪分布式,完全分布式,个人学习过程中建议使用伪分布式版本,也可以用完全分布式,这样更符合实际应用环境,但你需要考虑个人的机子的配置.
hadoop需要安装在linux上,一般的教程都会只用vmware来做虚拟机,但是比较卡,实在没必要,我个人建议使用docker,虽然是大材小用吧,但比vmware快多了,不管是单机,伪分布式还是完全分布式都很轻便.环境的下载我这里不赘述.
环境
jdk >= 1.8
hadoop>=2.x
vmware 或者docker
vim ./bashrc
export JAVA_HOME=/.../jdk-x.x
export HADOOP_HOME=/.../hadoop-2.X
export PATH=.:$HADOOP_HOME/bin:$HADOOP_HOME/sbin:$JAVA_HOME/bin:$PATH
source .bashrc
我的一个博客有专门介绍docke上安装hadoop可以看看.
hadoop安装之前需要配置好jdk,因为hadoop的访问需要远程访问,每次都要输入密码,这里需要配置ssh免密登录
关闭防火墙
service iptables stop
或者永久性关闭
chkconfif iptables off
安装ssh
apt install ssh
生成ssh公钥
ssh-keygen -t rsa
ssh-copy-id -i localhost
若果有多个机子则将公钥复制到其他机子上.如:
ssh-copy-id -i ~/.ssh/id_rsa.pub root@node1
验证登录:
ssh localhost
伪分布式配置文件
vim hadoop-env.sh
export JAVA_HOME=…
vim core-site.xml
vim hdfs-site.xml
vim mapred-site.xml
vim yarn-site.xml
vim slaves
localhost
格式化namenode
hadoop namenode -format
启动hdfs
$HADOOP_HOME/sbin/start-dfs.sh
或者各个进程单独启动
hadoop-daemon.sh start namenode
hadoop-daemon.sh start datanode
hadoop-daemon.sh start secondarynamenode
如果namenode 和datanode都启动则正常启动,或者访问http://localhost:9000
注意我这里的主机名是master,你需要按照自己的主机名设置和访问.
完全分布式
需要将slaves文件里的内容改为集群中所有node的主机名就行.其他配置参考伪分布式配置.
hadoop ha高可用
1.集群中有两个Namenode,任何时刻只有一个是active,另一个是standby,active负责所有客户端的操作,standby负责维护状态信息以及需要是快速切换.
2.ZKFailoverController是独立的进程负责Namenode的主备切换进行总体控制,zookeeper集群的目的是为主备切换控制器提供切换选举支持.
ZKFailoverController负责周期性向Namenode发送探测指令,用于检测健康状况
如果Namenode是健康的,ZKFailoverController就会在zookeeper中保持一个会话,若Namenode是active,ZKFailoverController还会在zookeeprt中占用一个znode,若Namenode挂掉,则删除znode,备用namenode将会得到这把锁,升级为Namenode 且标记为active,若宕机的Namenode再次重启,重新注册zookeeper时发现已经有znode是会自动设置为standby
3.为了保持Standby与Active状态同步,需要Journal Node来辅助,Active Node会把所有对命名空间的修改日志发送给JN, Standby会从JN中读取edit应用到自己的命名空间中,在Standy升级为Active前,已经从JN读完所有的edit,这样就确保了Namenode命名空间状态完全同步.
4.DataNode要共享HDFS中的元数据信息,主Namenode与备Namenode要共享HDFS的数据块和DataNode之间的映像关系.DataNode同时会向主NameNode和备Namenode上报数据块的位置信息.
hadoop 高可用环境搭建
JournalNode和Zookeeper保持奇数个结点,不少于三个结点
node1 | node2 | node3 | node4 | |
---|---|---|---|---|
NameNode | Y | Y | ||
DataNode | Y | Y | Y | Y |
JournalNode | Y | Y | Y | |
Zookeeper | Y | Y | Y | |
DFSZKFailoverController | Y | Y |
下载zookeeper并解压
进入zookeeper中conf/目录,复制zoo_sample.cfg并命名为zoo.cfg并编辑
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/.../zkdata
dataLogDir=/.../zkdatalog
clientPort=2181
server.1=node1:2888:3888
server.2=node2:2888:3888
server.3=node3:2888:3888
server.4=node4:2888:3888
进入zkdata文件夹中创建文件myid,输入1,这里的数字1与zoo.cfg中的server.1中的1对应,在其他的机子上进行相同的操作,myid中输入的数字与zoo.cfg中一致.这里我写了一个脚本用来在docker容器中实现slaves文件的配置和myid文件的配置,按需选择.这个脚本需要在所有容器中执行,如果没有用docker的话直接略过.
if [ $(hostname) == "master" ]
then
if [ `grep "slave1" $HADOOP_CONFIG_HOME/slaves` ]
then
echo "slave1 has exist"
else
echo "slave1" >> $HADOOP_CONFIG_HOME/slaves
fi
if [ `grep "slave2" $HADOOP_CONFIG_HOME/slaves` ]
then
echo "slave2 has exist"
else
echo "slave2" >> $HADOOP_CONFIG_HOME/slaves
fi
fi
cp /etc/hosts /etc/hosts.tmp
sed -i '$d' /etc/hosts.tmp
cat /etc/hosts.tmp > /etc/hosts
rm /etc/hosts.tmp
echo -e "172.17.0.2\\tmaster\\n172.17.0.3\\tslave1\\n172.17.0.4\\tslave2" >> /etc/hosts
if [ $(hostname) == "slave1" ]
then
echo -e 2 > /root/hadoop/hadoop-2.8.3/zookeeper/zkdata/myid
echo "slave1 myid has been entered"
fi
if [ $(hostname) == "slave2" ]
then
echo -e 3 > /root/hadoop/hadoop-2.8.3/zookeeper/zkdata/myid
echo "slave2 myid has been entered"
fi
vim hadoop-env.sh
export JAVA_HOME=/…
vim core-site.xml
<configuration>
<property>
<name>hadoop.tmp.dir</name>
<value>/root/hadoop/hadoop-2.8.3/tmp</value>
</property>
<property>
<name>fs.default.name</name>
<value>hdfs://master:9000</value>
<final>true</final>
</property>
<property>
<name>ha.zookeeper.quorum</name>
<value>master:2181,slave1:2181,slave2:2181</value>
</property>
</configuration>
vim hdfs-site.xml
<configuration>
<property>
<name>dfs.replication</name>
<value>3</value>
<final>true</final>
</property>
<property>
<name>dfs.namenode.name.dir</name>
<value>/root/hadoop/hadoop-2.8.3/namenode</value>
<final>true</final>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>/root/hadoop/hadoop-2.8.3/datanode</value>
<final>true</final>
</property>
<!--ha-->
<property>
<name>dfs.nameservices</name>
<value>mycluster</value>
</property>
<!--Namenode in cluster-->
<property>
<name>dfs.ha.namenodes.mycluster</name>
<value>master,slave1</value>
</property>
<!--set RPC-->
<property>
<name>dfs.namenode.rpc-address.mycluster.master</name>
<value>master:8020</value>
</property>
<property>
<name>dfs.namenode.rpc-address.mycluster.slave1</name>
<value>slave1:9000</value>
</property>
<!--http-->
<property>
<name>dfs.namenode.http-address.mycluster.master</name>
<value>master:50070</value>
</property>
<property>
<name>dfs.namenode.http-address.mycluster.slave1</name>
<value>slave1:50070</value>
</property>
<!--auto recover-->
<property>
<name>dfs.ha.automatic-failover.enabled.mycluster</name>
<value>true</value>
</property>
<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://master:8485;slave1:8485;slave2:8485/mycluster</value>
</property>
<property>
<name>dfs.client.failover.proxy.provider.mycluster</name>
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>
<!--when JournalNode cluster share the dir to NameNode,the path it store it's data-->
<property>
<name>dfs.journalnode.edits.dir</name>
<value>/root/hadoop/hadoop-2.8.3/journal</value>
</property>
<!--NameNode change use ssh-->
<property>
<name>dfs.ha.fencing.methods</name>
<value>sshfence</value>
</property>
<!--ssh change without password-->
<property>
<name>dfs.ha.fencing.ssh.private-key-files</name>
<value>/root/hadoop/.ssh/id_rsa</value>
</property>
</configuration>
vim slaves
输入的datanode主机名
node1
node2
node3
node4
集群启动
1)启动ZooKeeper集群
在所有结点上的zookeeper目录中都执行
bin/zkServer.sh start
在所有机子启动zookeeper后可输入
bin/zkServer.sh start
检测zookeeper状态,每台机子都需要检测,只有一个leader其他都是follower
2) 格式化zookeeper集群
在一个namenode结点的hadoop目录上执行
bin/hdfs zkfc -formatZK
3) 启动Journal Node集群
在有Journal Node的结点上执行
sbin/hadoop-daemon.sh start journalnode
- 格式化NameNode(安装的第一次使用之后不在需要)
格式化两个NameNode中的一个就行
bin/hdfs namenode -format
看到输入的日志中出现successful 就成功了
5)启动格式化后的Namenode
sbin/hadoop-daemon.sh start namenode
将格式化后的namenode同步到另外一个namenode上
hdfs namenode -bootstrapStandby
启动第二台namenode
sbin/hadoop-daemon.sh start namenode
- 启动所有datanode
datanode之前在slaves文件中配置过,所以只需在namenode1上执行
sbin/hadoop-daemon.sh start datanode
7)启动ZooKeeperFailoverCotroller
sbin/hadoop-daemon.sh start zkfc
访问http://node1:9000,http://node2:9000观察是否有active和standby出现,若都出现则集群搭建完成.
Yarn(yet another resource negotiator)介绍
mapreduce1.0
Yarn
client向ResourceManager提交任务,终止任务.
ApplicationMaster由对应的应用程序完成,一个应用对应一个ApplicationMaster,ApplicationMaster向ResourceManager申请资源用于在NodeManager上启动相应的任务.NodeManager通过心跳信息向ResourceManager汇报自身状态.Map Task对应的是MapReduce作业启动时产生的Map任务,MPI Task是MPI框架对应的执行任务.
Yarn工作流程
- 用户向YARN中提交应用程序/作业
- ResourceManager为作业分配第一个Container,并与对应的NodeManager通信,要求在这个Container中启动该作业的ApplicationMaster
- ApplicationMaster首先向ResourceManager注册,这样用户可以直接通过ResourceManager查询作业的状态.
- ApplicationMaster采用轮询的方式通过RPC请求向ResourceManager申请资源
- 一旦.ApplicationMaster申请到资源,便与对应的NodeManager通信,启动任务
- NodeManager启动任务
- 各个任务通过RPC协议向ApplicationMaster汇报自己的状态,方便.ApplicationMaster管理任务的失败重启等任务
- 作业完成后,.ApplicationMaster向ResourceManager注销自己