前因
前端时间学习hadoop的时候,需要搭建hadoop集群,首先想到的是虚拟机进行搭建,但是呢,不知道为啥,自己的虚拟机有问题,虚拟机之间的网络也是时灵时不灵的,最后一气之下,学习了一段时间的docker,然后使用容器话技术进行了hadoop的部署。
推荐下docker的书籍,这个只需要了解一点基础就行了。然后又参考了这篇文章,进行了容器镜像的搭建和hadoop镜像的搭建。
1 安装包准备
- jdk采用的是jdk1.7_80直接使用的官网下载的,速度还行。选择的是jdk-7u80-linux-x64.tar.gz。
- hadoop采用的是2.9.1,官方下载太慢了,这里有一个国内镜像,贼快的。
- zookeeper采用的是3.4.12,下载地址同上
2 开始搭建
创建docker的hadoop镜像可以参考上面提到的文章进行搭建,我本地搭建了总共四个镜像文件如图:

这四个镜像中
- centos-ssh-root是基础镜像,是一个centos环境镜像,初始账户密码root:root,Dockerfile:
FROM centos
MAINTAINER jiyx
RUN yum install -y openssh-server sudo
RUN sed -i 's/UsePAM yes/UsePAM no/g' /etc/ssh/sshd_config
RUN yum install -y openssh-clients
#这个是自己踩的坑,如果没有which命令,journalnode运行不起来,后面是自行运行的安装,比较麻烦,还不如在这里直接进行安装
RUN yum install which
RUN echo "root:root" | chpasswd
RUN echo "root ALL=(ALL) ALL" >> /etc/sudoers
RUN ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key
RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
RUN mkdir /var/run/sshd
EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]
- centos-ssh-root-jdk是在centos镜像基础上搭建的jdk环境镜像,Dockerfile:
FROM jixy/centos-ssh-root
ADD jdk-7u80-linux-x64.tar.gz /usr/local/
RUN mv /usr/local/jdk1.7.0_80 /usr/local/jdk1.7
ENV JAVA_HOME /usr/local/jdk1.7
ENV PATH $JAVA_HOME/bin:$PATH
- centos-ssh-root-hadoop是在jdk镜像的基础上搭建的hadoop镜像,Dockerfile:
FROM jiyx/centos-ssh-root-jdk:1.7
ADD hadoop-2.9.1.tar.gz /usr/local
RUN mv /usr/local/hadoop-2.9.1 /usr/local/hadoop
ENV HADOOP_HOME /usr/local/hadoop
ENV PATH $HADOOP_HOME/bin:$PATH
- centos-ssh-root-zookeeper是在jdk镜像的基础上搭建的zookeeper镜像,Dockerfile:
FROM jiyx/centos-ssh-root-jdk:1.7
ADD zookeeper-3.4.12.tar.gz /usr/local
RUN mv /usr/local/zookeeper-3.4.12 /usr/local/zookeeper
ENV ZK_HOME /usr/local/zookeeper
ENV PATH $ZK_HOME/bin:$PATH
3 创建容器,修改文件
这里创建容器的数量是10台,具体如下
主机名 ip 所属集群 部署的服务
hadoop0 192.168.210.1 hadoop NameNode、DFSZKFailoverController(zkfc)
hadoop1 192.168.210.2 hadoop NameNode、DFSZKFailoverController(zkfc)
hadoop2 192.168.210.3 hadoop ResourceManager
hadoop3 192.168.210.4 hadoop ResourceManager
hadoop4 192.168.210.5 hadoop DataNode、NodeManager、JournalNode
hadoop5 192.168.210.6 hadoop DataNode、NodeManager、JournalNode
hadoop6 192.168.210.7 hadoop DataNode、NodeManager、JournalNode
zookeeper0 192.168.210.8 zookeeper QuorumPeerMain
zookeeper1 192.168.210.9 zookeeper QuorumPeerMain
zookeeper2 192.168.210.10 zookeeper QuorumPeerMain
因为docker的的启动进程只配置了一个,所以这里如果停止了容器的话,重启之后还需要重新启动部署的进程,没有虚拟机那么方便了。
3.1 创建容器之前的准备
创建容器之前,因为每次启动docker容器,容器的ip都会发生变动,所以需要进行docker的固定ip配置,可以参考这里。这里简单介绍下:
- 首先使用docker network ls查看docker的网络配置
- 然后使用命令docker network create -d bridge --subnet=192.168.210.0/24 --gateway=192.168.210.1 -o parent=en0 staticnet创建一个以宿主机en0网卡上网的桥接网段。
- 然后再使用docker network ls查看的时候就会多出一个staticnet的网段了
- 有了这个网段就可以在后面运行容器的时候固定容器的ip
3.2 创建三台zookeeper容器
- 使用命令docker run --name zookeeper0 --hostname zookeeper0 -d -P --net=staticnet --ip=192.168.210.1 centos-ssh-root-zookeeper运行第一个zk容器,剩下的自行修改命令运行。
- 然后使用命令docker exec -it zookeeper0 /bin/bash进入容器进行zk的集群配置,这个就跟一般部署zk集群一样
- 等三台集群都启动之后查看下集群状态是否正常。
因为docker容器之间本身就是想通的,不必要配置防火墙等
3.2 创建7台hadoop容器
- 使用命令docker run --name hadoop0 --hostname hadoop0 -d -P -p 50070:50070 -p 8088:8088 --net=staticnet --ip=192.168.210.4 jiyx/centos-ssh-root-jdk-hadoop:2.9.1运行第一台hadoop集群。第一台机器需要将50070和8088端口映射到宿主机上,其他的没必要。其他容器的启动基本类似都是docker run --name hadoop1 --hostname hadoop1 -d -P --net=staticnet --ip=192.168.210.5 jiyx/centos-ssh-root-hadoop:2.9.1,只需要修改ip和hostname即可。我再启动容器的时候使用了hadoop镜像,其实感觉使用jdk镜像更好一点,只不过需要配置环境变量,可能比较麻烦了
+运行命令docker exec -it hadoop0 /bin/bash进入hadoop集群,接下来就是配置了:
配置文件如下:
1.修改hadoo-env.sh
export JAVA_HOME=/usr/java/jdk1.7.0_55
2.修改core-site.xml
<configuration>
<!-- 指定hdfs的nameservice为ns1 -->
<property>
<name>fs.defaultFS</name>
<value>hdfs://ns1</value>
</property>
<!-- 指定hadoop临时目录 -->
<property>
<name>hadoop.tmp.dir</name>
<value>/usr/local/hadoop/data</value>
</property>
<!-- 指定zookeeper地址 -->
<property>
<name>ha.zookeeper.quorum</name>
<value>zookeeper0:2181,zookeeper1:2181,zookeeper2:2181</value>
</property>
</configuration>
3.修改hdfs-site.xml
<configuration>
<!--指定hdfs的nameservice为ns1,需要和core-site.xml中的保持一致 -->
<property>
<name>dfs.nameservices</name>
<value>ns1</value>
</property>
<!-- ns1下面有两个NameNode,分别是nn1,nn2 -->
<property>
<name>dfs.ha.namenodes.ns1</name>
<value>nn1,nn2</value>
</property>
<!-- nn1的RPC通信地址 -->
<property>
<name>dfs.namenode.rpc-address.ns1.nn1</name>
<value>hadoop0:9000</value>
</property>
<!-- nn1的http通信地址 -->
<property>
<name>dfs.namenode.http-address.ns1.nn1</name>
<value>hadoop0:50070</value>
</property>
<!-- nn2的RPC通信地址 -->
<property>
<name>dfs.namenode.rpc-address.ns1.nn2</name>
<value>hadoop1:9000</value>
</property>
<!-- nn2的http通信地址 -->
<property>
<name>dfs.namenode.http-address.ns1.nn2</name>
<value>hadoop1:50070</value>
</property>
<!-- 指定NameNode的元数据在JournalNode上的存放位置 -->
<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://hadoop4:8485;hadoop5:8485;hadoop6:8485/ns1</value>
</property>
<!-- 指定JournalNode在本地磁盘存放数据的位置 -->
<property>
<name>dfs.journalnode.edits.dir</name>
<value>/usr/local/hadoop/journal</value>
</property>
<!-- 开启NameNode失败自动切换 -->
<property>
<name>dfs.ha.automatic-failover.enabled</name>
<value>true</value>
</property>
<!-- 配置失败自动切换实现方式 -->
<property>
<name>dfs.client.failover.proxy.provider.ns1</name>
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>
<!-- 配置隔离机制方法,多个机制用换行分割,即每个机制暂用一行-->
<property>
<name>dfs.ha.fencing.methods</name>
<value>
sshfence
shell(/bin/true)
</value>
</property>
<!-- 使用sshfence隔离机制时需要ssh免登陆 -->
<property>
<name>dfs.ha.fencing.ssh.private-key-files</name>
<value>/root/.ssh/id_rsa</value>
</property>
<!-- 配置sshfence隔离机制超时时间 -->
<property>
<name>dfs.ha.fencing.ssh.connect-timeout</name>
<value>30000</value>
</property>
</configuration>
4.修改mapred-site.xml
<configuration>
<!-- 指定mr框架为yarn方式 -->
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
</configuration>
5.修改yarn-site.xml
<configuration>
<!-- 开启RM高可靠 -->
<property>
<name>yarn.resourcemanager.ha.enabled</name>
<value>true</value>
</property>
<!-- 指定RM的cluster id -->
<property>
<name>yarn.resourcemanager.cluster-id</name>
<value>yrc</value>
</property>
<!-- 指定RM的名字 -->
<property>
<name>yarn.resourcemanager.ha.rm-ids</name>
<value>rm1,rm2</value>
</property>
<!-- 分别指定RM的地址 -->
<property>
<name>yarn.resourcemanager.hostname.rm1</name>
<value>hadoop2</value>
</property>
<property>
<name>yarn.resourcemanager.hostname.rm2</name>
<value>hadoop3</value>
</property>
<!-- 指定zk集群地址 -->
<property>
<name>yarn.resourcemanager.zk-address</name>
<value>zookeeper0:2181,zookeeper1:2181,zookeeper2:2181</value>
</property>
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
</configuration>
6.修改slaves
将slaves修改为如下配置,因为一般datanode和nodemanager一般都存放在同样的服务器上,如果在不同的需要分开配置,也就是hadoop0和hadoop2需要分开配置
hadoop4
hadoop5
hadoop6
4 免密登录配置
- hadoop0需要免密登录到其他所有的hadoop容器
- hadoop2需要免密登录到hadoop的3、4、5、6
- 免密配置只需要在需要免密登录的服务器上执行ssh-keygen -r rsa 直接回车,然后ssh-copy-id 到需要登录的容器即可,如hadoop0上执行ssh-keygen -r rsa 然后ssh-copy-id hadoop1以及2、3、4、5、6上即可从0登录到其他。
5 启动
- 首先启动zk集群,命令zkServer.sh start ,要查看集群状态是否正常
- 然后启动journalnode,启动命令hadoop-daemon.sh start journalnode,启动完之后运行jps查看是否有JournalNode进程
- 第一次启动集群需要格式化hdfs,命令hdfs namenode -format,可以查看打印的日志判断正常与否
- 在hadoop0上执行hdfs zkfc -formatZK,格式化启动zkfc
- 在hadoop0上执行start-dfs.sh,会启动NameNode、DFSZKFailoverController、DataNode。
- 在hadoop2上执行start-yarn.sh,会启动ResourceManager、NodeManager
- 在hadoop3上执行yarn-daemon.sh start resourcemanager,备用的ResourceManager需要单独启动。启动玩之后可以使用yarn rmadmin -getServiceState rm2查看两个resourcemanager的状态。
至此完成配置。
参考:使用docker搭建hadoop分布式集群
网友评论