Docker( for Windows) 搭建hadoop集群
参考:
基于 Docker 搭建 Hadoop 平台_不思故亡的博客-CSDN博客_docker搭建hadoop
使用docker部署hadoop集群 - upupfeng - 博客园 (cnblogs.com)
hadoop 启动dfs失败- Q1Zhen - 博客园 (cnblogs.com)
基于docker的hadoop集群搭建小何又沐风的博客-CSDN博客基于docker搭建hadoop
Hadoop集群添加、删除节点_oToyix的博客-CSDN博客_hadoop集群添加节点
一、集群规划
主机名 | IP | 用户 | HDFS | YARN |
---|---|---|---|---|
hadoop0 | 待定 | root | NameNode、DataNode | ResourceManager 、NodeManager |
hadoop1 | 待定 | root | SecondaryNameNode、DataNode | NodeManager |
hadoop2 | 待定 | root | DataNode | NodeManager |
![](https://img.haomeiwen.com/i23466769/2dc859341cb3f964.png)
二、环境准备
1、Docker( for Windows)环境(docker也可以装在wsl2里面),请自行搭建
2、jdk-8u333-linux-x64.tar.gz - JDK 官方下载页面
3、hadoop-3.3.3.tar.gz - hadoop 3.3.3官方下载
三、构建centos-hadoop镜像
1、创建Dockerfile文件,并将其和下载的压缩包放一起
![](https://img.haomeiwen.com/i23466769/0cefbbb53cfda9f7.png)
2、编写Dockerfile,内容如下
FROM centos:centos7.9.2009
# 使用centos7版本就好,不要使用centos8
MAINTAINER sksum@qq.com
# 安装openssh-server和sudo软件包,并且将sshd的UsePAM参数设置成no
RUN yum install -y openssh-server sudo
RUN sed -i 's/UsePAM yes/UsePAM no/g' /etc/ssh/sshd_config
#安装openssh-clients
RUN yum install -y openssh-clients
# 添加测试用户root,密码root,并且将此用户添加到sudoers里
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
# 启动sshd服务并且暴露22端口
RUN mkdir /var/run/sshd
EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]
# 将JDK包添加到镜像之中,并配置环境变量
ADD jdk-8u333-linux-x64.tar.gz /usr/local/
RUN mv /usr/local/jdk1.8.0_333 /usr/local/jdk1.8
ENV JAVA_HOME /usr/local/jdk1.8
ENV PATH $JAVA_HOME/bin:$PATH
# 将hadoop包添加到镜像之中,并配置环境变量
ADD hadoop-3.3.3.tar.gz /usr/local
RUN mv /usr/local/hadoop-3.3.3 /usr/local/hadoop
ENV HADOOP_HOME /usr/local/hadoop
ENV PATH $HADOOP_HOME/bin:$PATH
ENV PATH $HADOOP_HOME/sbin:$PATH
# 配置集群的角色,不然启动集群时会报错
ENV HDFS_NAMENODE_USER="root"
ENV HDFS_DATANODE_USER="root"
ENV HDFS_SECONDARYNAMENODE_USER="root"
ENV YARN_RESOURCEMANAGER_USER="root"
ENV YARN_NODEMANAGER_USER="root"
# 创建文件目录,用于后面存放HDFS数据
RUN mkdir /home/hadoop
RUN mkdir /home/hadoop/tmp /home/hadoop/hdfs_name /home/hadoop/hdfs_data
# 定义时区参数
ENV TZ=Asia/Shanghai
#设置时区
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo '$TZ' > /etc/timezone
# 中文支持
RUN yum -y install kde-l10n-Chinese
RUN yum -y install glibc-common
RUN localedef -c -f UTF-8 -i zh_CN zh_CN.utf8
# 设置编码
ENV LC_ALL zh_CN.UTF-8
3、打包镜像,起名为 centos-hadoop
docker build -t centos-hadoop ./
打包成功后可以使用命令docker images
检查镜像是否生成
![](https://img.haomeiwen.com/i23466769/fcc0cbaa8001df85.png)
四、创建hadoop容器
1、 搭建子网络,以便子容器(集群)能相互通讯
docker network create --subnet=192.168.1.0/24 hadoopnet
2、 创建hadoop容器,并分配网络
# 主服务器hadoop0端口映射到宿主机,映射8088端口、9870端口、9864端口
docker run -itd --name hadoop0 --hostname hadoop0 --net hadoopnet --ip 192.168.1.2 -p 8088:8088 -p 9870:9870 -p 9864:9864 centos-hadoop
docker run -itd --name hadoop1 --hostname hadoop1 --net hadoopnet --ip 192.168.1.3 centos-hadoop
docker run -itd --name hadoop2 --hostname hadoop2 --net hadoopnet --ip 192.168.1.4 centos-hadoop
3、使用docker ps
命令查看创建的3个容器
![](https://img.haomeiwen.com/i23466769/c7ead3e373a9f03a.png)
五、配置ssh免密登录
1、进入主服务器(主节点),以下操作在主要服务器操作即可
docker exec -it hadoop0 /bin/bash
2、配置ssh免密登录
ssh-keygen
#剩下的一路回车即可
# 以下3条都不能省,请根据提示输入yes以及主机密码,开头我们设置的是root/root
ssh-copy-id hadoop0
ssh-copy-id hadoop1
ssh-copy-id hadoop2
六、配置hadoop集群
1、进入hadoop的文件配置目录(也是在主节点服务器中操作),主要修改以下配置文件:
cd $HADOOP_HOME/etc/hadoop
配置文件名 | 配置内容 | 配置对象 |
---|---|---|
core-site.xml | 集群全局参数 | 用于定义系统级别的参数, 如HDFS URL、Hadoop的临时目录等 |
hdfs-site.xml | HDFS参数 | 如名称节点和数据节点的存放位置、 文件副本的个数、文件读取权限等 |
mapred-site.xml | Mapreduce参数 | 包括JobHistory Server和应用程序参数, 如reduce任务的默认个数、 任务所能够使用内存的默认上下限等 |
yarn-site.xml | 集群资源管理系统参数 | 配置 ResourceManager, NodeManager 的通信端口, web监控端口等 |
workers | 集群 DataNode节点的主机名或IP | 集群 DataNode节点的主机名或IP, 以便于start-all.sh启动集群的节点 |
1、vi hadoop-env.sh
,添加如下配置(此步骤可忽略,其在打包镜像时已配置环境变量)
export JAVA_HOME=/usr/local/jdk1.8
2、 vi core-site.xml
<configuration>
<!-- 定义主服务器的URI和端口-->
<property>
<name>fs.defaultFS</name>
<value>hdfs://hadoop0:9000</value>
</property>
<!-- 设置hadoop本地数据存储路径 -->
<property>
<name>hadoop.tmp.dir</name>
<value>/home/hadoop/tmp</value>
</property>
<!-- HDFS垃圾箱设置,可以恢复误删除,分钟数,0为禁用,添加该项无需重启hadoop -->
<property>
<name>fs.trash.interval</name>
<value>1440</value>
</property>
</configuration>
2、vi hdfs-site.xml
<configuration>
<!-- 保存FsImage镜像的目录,作用是存放hadoop的名称节点namenode里的metadata -->
<property>
<name>dfs.namenode.name.dir</name>
<value>file:/home/hadoop/hdfs_name</value>
</property>
<!-- 存放HDFS文件系统数据文件的目录,作用是存放hadoop的数据节点datanode里的多个数据块 -->
<property>
<name>dfs.datanode.data.dir</name>
<value>file:/home/hadoop/hdfs_data</value>
</property>
<!-- hdfs数据块的复制份数,默认3,理论上份数越多跑数速度越快,但是需要的存储空间也更多。有钱人可以调5或者6 -->
<property>
<name>dfs.replication</name>
<value>2</value>
</property>
<!-- SNN进程运行机器位置信息-->
<property>
<name>dfs.namenode.secondary.http-address</name>
<value>hadoop1:9001</value>
</property>
<!-- 是否开启webhdfs -->
<property>
<name>dfs.webhdfs.enabled</name>
<value>true</value>
</property>
</configuration>
3、vi mapred-site.xml
<configuration>
<!-- 设置MR程序默认运行模式,YARN集群 local本地模式-->
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
<!-- MR程序历史服务地址-->
<property>
<name>mapreduce.jobhistory.address</name>
<value>hadoop0:10020</value>
</property>
<!-- MR程序历史服务器web地址-->
<property>
<name>mapreduce.jobhistory.webapp.address</name>
<value>hadoop0:19888</value>
</property>
<property>
<name>yarn.app.mapreduce.am.env</name>
<value>HADOOP_MAPRED_HOME=${HADOOP_HOME}</value>
</property>
<property>
<name>mapreduce.map.env</name>
<value>HADOOP_MAPRED_HOME=${HADOOP_HOME}</value>
</property>
<property>
<name>mapreduce.reduce.env</name>
<value>HADOOP_MAPRED_HOME=${HADOOP_HOME}</value>
</property>
</configuration>
4、vi yarn-site.xml
<configuration>
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<property>
<name>yarn.nodemanager.auxservices.mapreduce.shuffle.class</name>
<value>org.apache.hadoop.mapred.ShuffleHandler</value>
</property>
<property>
<name>yarn.resourcemanager.address</name>
<value>hadoop0:8032</value>
</property>
<property>
<name>yarn.resourcemanager.scheduler.address</name>
<value>hadoop0:8030</value>
</property>
<property>
<name>yarn.resourcemanager.resource-tracker.address</name>
<value>hadoop0:8031</value>
</property>
<property>
<name>yarn.resourcemanager.admin.address</name>
<value>hadoop0:8033</value>
</property>
<property>
<name>yarn.resourcemanager.webapp.address</name>
<value>hadoop0:8088</value>
</property>
</configuration>
5、vi workers
配置的为 DataNode节点的主机名或IP(hadoop3.0以后slaves更名为workers)
hadoop0
hadoop1
hadoop2
# 删掉 localhost
6、将主节点服务器的配置文件同步给另外两台从服务器(还是在$HADOOP_HOME/etc/hadoop
目录下执行)
scp -r * hadoop1:$HADOOP_HOME/etc/hadoop
scp -r * hadoop2:$HADOOP_HOME/etc/hadoop
scp -r /home/hadoop hadoop1:/home/
scp -r /home/hadoop hadoop2:/home/
7、在主节点下(NameNode)格式化HDFS(首次使用,文件存储系统要进行格式化,在主服务器操作即可)
hdfs namenode -format
看到约倒数第十行提示信息,会提示初始化成功
INFO common.Storage: Storage directory /home/hadoop/hdfs_name has been successfully formatted.
补充:不要重复格式化HDFS,会导致DataNode无法启动。
8、使用命令 start-all.sh
启动HDFS 集群和YARN集群,此时日志如下:
[root@hadoop0 sbin]# start-all.sh
Starting namenodes on [hadoop0]
Last login: Mon May 30 06:43:27 UTC 2022 on pts/2
Starting datanodes
Last login: Mon May 30 06:51:35 UTC 2022 on pts/2
Starting secondary namenodes [hadoop1]
Last login: Mon May 30 06:51:37 UTC 2022 on pts/2
Starting resourcemanager
Last login: Mon May 30 06:51:40 UTC 2022 on pts/2
Starting nodemanagers
Last login: Mon May 30 06:51:45 UTC 2022 on pts/2
补充:HDFS 集群和YARN集群也可单独启动,启动命令都在$HADOOP_HOME/sbin
中,至此,Hadoop集群部署结束。
七、验证hadoop集群是否正常启动
方法1、可检查各个容器,通过命令jps
,查看进程是否正常启动
# 容器hadoop0(主节点)
[root@hadoop0 sbin]# jps
4054 ResourceManager
3447 NameNode
3594 DataNode
4206 NodeManager
4815 Jps
# 容器hadoop1(从节点)
[root@hadoop1 hdfs_data]# jps
709 DataNode
823 SecondaryNameNode
1129 Jps
909 NodeManager
# 容器hadoop2(从节点)
[root@hadoop2 /]# jps
1730 Jps
1004 NodeManager
847 DataNode
如上所示,显示已启动的进程,与集群规划中的一致,各容器进程启动正常。
2、测试hdfs是否可以正常上传文件
# HDFS创建一个目录
hdfs dfs -mkdir /test
# 容器内创建一个文件
echo "hello hdfs" >> local.txt
# 将文件上传到HDFS
hdfs dfs -put local.txt /test
# 查看HDFS 的test文件夹
hdfs dfs -ls /test
# Found 1 items
# -rw-r--r-- 2 root supergroup 11 2022-05-30 07:51 /test/local.txt
# 查看文件内容
hdfs dfs -cat /test/local.txt
# hello hdfs
3、检查web界面是否能够正常打开(前面创建容器时,有将这端口映射到宿主机端口)
Yarn集群监控界面:http://localhost:8088/
HDFS集群监控界面: http://localhost:9870/
![](https://img.haomeiwen.com/i23466769/3ccab15a7cc6a33e.png)
4、mapReduce服务测试
4.1 进入hadoop计算样例目录
cd $HADOOP_HOME/share/hadoop/mapreduce
4.2 运行测试样例 hadoop jar hadoop-mapreduce-examples-3.3.3.jar pi 3 100
调用jar包计算pi的值,计算100次(根据自己的hadoop版本修改命令)
4.3通过浏览器查看,在浏览器中输入localhost:8088,可以查看任务情况以及日志等
![](https://img.haomeiwen.com/i23466769/cd09a57f4f1d92e8.png)
八、节点扩容
1、创建新的容器hadoop3
docker run -itd --name hadoop3 --hostname hadoop3 --net hadoopnet --ip 192.168.1.5 centos-hadoop
2、进入主节点容器
docker exec -it hadoop0 /bin/bash
3、配置免密登录
ssh-copy-id hadoop3
4、修改主节点容器中的 DataNode节点配置文件,新增从节点的hostname名称
cd $HADOOP_HOME/etc/hadoop
vi workers
新增 hadoop3
或者直接
echo "hadoop3" >> $HADOOP_HOME/etc/hadoop/workers
5、将hadoop配置文件同步到新节点容器hadoop3(主要是步骤六那几个xml文件)
cd $HADOOP_HOME/etc/hadoop
scp -r * hadoop3:$HADOOP_HOME/etc/hadoop
6、(新开窗口)切换到hadoop3节点服务器,启动datanode 和nodemanager进程
docker exec -it hadoop3 /bin/bash
hdfs --daemon start datanode
yarn --daemon start nodemanager
# jps命令可以检测进程是否启动成功
7、切回主节点hadoop1服务器,动态刷新集群节点,并做资源重新分配。
hdfs dfsadmin -refreshNodes
start-balancer.sh
8、通过网页判断节点是否新增成功
HDFS集群监控界面:Namenode information
![](https://img.haomeiwen.com/i23466769/237c9bed89ff4faf.png)
也可以在主节点服务器通过以下命令判断节点是否新增成功
# 查看现有HDFS各节点状态,命令操作如下
hdfs dfsadmin -report
# 查看YARN各节点状态,命令操作如下
yarn node -list
九、动态删除节点(未测试)
1、 主节点配置hdfs-site.xml文件
# 进入配置文件目录
cd $HADOOP_HOME/etc/hadoop
# 编辑文件
vi hdfs-site.xml
2、加入下面代码,指定要删除的节点配置文件
<property>
<name>dfs.hosts.exclude</name>
<value>${HADOOP_HOME}/etc/hadoop/excludes</value>
</property>
3、编辑上面步骤指定的配置文件,将要删除的节点名称添加到文件里面
echo hadoop3 >> ${HADOOP_HOME}/etc/hadoop/excludes
4、修改了hadoop的配置文件,就得将配置文件同步给其他节点
scp -r * hadoop1:$HADOOP_HOME/etc/hadoop
scp -r * hadoop2:$HADOOP_HOME/etc/hadoop
scp -r * hadoop3:$HADOOP_HOME/etc/hadoop
5、刷新主节点
hdfs dfsadmin -refreshNodes
start-balancer.sh
6、查看HDFS各节点状态
hdfs dfsadmin -report
十、补充说明
上述教程 docker 是安装在Windows系统,虽然正常搭建起来了hadoop集群,也能正常使用。但是有一个问题存在,那就是宿主机(Windows)无法访问docker容器的IP(只能通过端口映射到宿主机),这点让我觉得很无法忍受(因为我后面还要扩容容器安装其他软件)。因此我又在windows的linux子系统(Windows Subsystem for Linux, 简称WSL)上安装了docker,并按照上面教程重新成功的搭建了hadoop集群。下面补充docker安装WSL2上的个别问题。
1、window 访问linux系统上的docker容器IP方式。
# 在Windows系统的管理员终端,给路由列表中永久添加一条静态路由
route -p add 192.168.1.0/24 mask 255.255.240.0 172.22.65.131
# 其中192.168.1.0/24是docker的容器使用bridge网络,详见前面步骤四、1,
# 172.22.65.131 是linux网卡的ip,如下图
# window添加完静态路由后,window就可以ping得通docker容器了,可测试如下
# ping 192.168.1.2
![](https://img.haomeiwen.com/i23466769/b83eb92a14baa48e.png)
2、windows重启后,WSL2的IP出现变化问题。
这问题没有直接的解决方式(其他方案不少)。考虑到这个hadoop集群搭建的性质只是用于学习,建议每次重启WSL2后,在windows里面管理员终端重新添加下静态路由
# WSL2下查询linux ip
$(ifconfig eth0 | grep -w inet | awk '{print $2}')
# WSL2下关闭防火墙(坑,每次重启后都需要关闭防火墙)
sudo ufw disable
# 开启防火墙
# sudo ufw enable
# 检查防火墙状态
# sudo ufw status
补充:有个很奇怪的问题,wsl2重启前,明明已经关闭了防火墙了,重启后检查防火墙状态时提示的也是防火墙没激活。
但是windows(宿主机)却ping不通docker容器的ip(仅可以ping通wsl2),此时再关闭一次防火墙就好了。
# windows终端下删除老的静态路由
route delete 192.168.1.0
# 为当前Windows系统路由列表中永久添加一条静态路由
route -p add 192.168.1.0/24 mask 255.255.240.0 172.22.65.131
# 记得用前面查询出来的 ip ,代替掉172.22.65.131
3、其他可能用得上的命令
# 检查docker是否运行
service docker status
# 运行docker
sudo service docker start
# 启动容器hadoop0
docker start hadoop0
# 进入容器hadoop0
docker exec -it hadoop0 /bin/bash
# 启动hadoop集群(记得要把另外几个容器也启动起来)
start-all.sh