最近想学习如何使用hdfs来存储文件,在网上学习了一下,明确了HDFS(Hadoop Distribute File System 分布式存储)、mapReduce(分布式计算)、YARN(Yet Another Resource Negotiator资源管理)是hadoop的三大组成部分,要想使用hdfs,必须搭建hadoop集群,为此展开了近一个星期的摸索。
网上的教程有很多,但很多都写的不全,自己也是一直踩坑,无奈之下只好对着官方文档一个个看,逐渐理解并明确了部署方法,在经过反复测试确保正常之后,决定在此记录一下,以便与大家交流分享。
1、集群规划
1.1 hadoop版本
hadoop版本不同,配置的内容也不同,本文使用的是hadopp-3.3.2,同样适用3的其他版本,安装包链接见2.1节
1.2 节点数量
只为测试学习,节点不用太多,计划使用3个节点,即构建3个docker容器,1个namenode节点,2个datanode节点,其中1个datanode作为second namenode
1.3 hostname与ip
hadoop集群要求节点具有固定的hostname和ip,在此做如下规划:
namenode的hostname为master,ip为192.168.0.10
第1个datanode的hostname为slave1,ip为192.168.0.11
第2个datanode的hostname为slave2,ip为192.168.0.12
1.4 端口
hadoop集群提供了网页管理界面,主要包括hdfs(文件系统)、cluster(集群)、jobhistory(历史任务)三大部分,每个部分都有访问的端口号
通过查阅官方文档确认了默认的端口号分别为9870、8088、19888,我们直接使用这些默认的端口号
2、hadoop镜像构建
2.1 安装包
hadoop-3.3.2.tar.gz jdk-8u321-linux-x64.tar.gz hadoop需要java的环境,此包下载需要oracle账号,没有账号的可以免费注册,如果有使用m1 mac 系统的请下载jdk17 Arm64 版本的
2.2 Dockerfile
构建镜像我们使用Dockerfile,注意这个文件的内容大家可以根据自己的情况修改,如 镜像源:使用centos7,大家可以换 LABEL:元数据这里列了作者和日期,大家可以改成自己的信息 ssh:用于节点直接相互访问用 which:hadoop命令执行需要which,不然会报错 jdk:不是8u321版本的,可以修改下面这两行中的版本信息
ADD jdk-8u321-linux-x64.tar.gz /usr/local/
RUN mv /usr/local/jdk1.8.0_321 /usr/local/jdk1.8
hadoop:不是3.3.2版本的,可以修改下面这两行中的版本信息
ADD hadoop-3.3.2.tar.gz /usr/local
RUN mv /usr/local/hadoop-3.3.2 /usr/local/hadoop
下面是完整的文件内容
FROM centos:7
LABEL author="hjq" date="2022/03/05"
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
RUN yum install -y 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
ADD jdk-8u321-linux-x64.tar.gz /usr/local/
RUN mv /usr/local/jdk1.8.0_321 /usr/local/jdk1.8
ENV JAVA_HOME /usr/local/jdk1.8
ENV PATH $JAVA_HOME/bin:$PATH
ADD hadoop-3.3.2.tar.gz /usr/local
RUN mv /usr/local/hadoop-3.3.2 /usr/local/hadoop
ENV HADOOP_HOME /usr/local/hadoop
ENV PATH $HADOOP_HOME/bin:$PATH
CMD ["/usr/sbin/sshd", "-D"]
2.3 构建
在本地新建一个自定义名称的文件夹,将上述的Dockerfile、hadoop-3.3.2.tar.gz、jdk-8u321-linux-x64.tar.gz拷贝到该文件夹下,然后使用终端进入该目录,并运行docker build -t hadoop-test . 别忘了后面的.
等待运行结束,包含ssh、jdk、hadoop的镜像就构建完成了
3、hadoop镜像配置
我们先用上述构建好的镜像运行一个测试容器,在此容器中配置好参数后,保存为新的镜像,这样以后构建node容器就不用重新配置了
- 构建容器
docker run -d --name hadoop-test hadoop-test - 进入容器
docker exec -it hadoop-test bash - 进入hadoop配置目录
cd /usr/local/hadoop/etc/hadoop/ - 配置hadoop环境变量
vi hadoop-env.sh
export HDFS_NAMENODE_USER=root
export HDFS_DATANODE_USER=root
export HDFS_SECONDARYNAMENODE_USER=root
export YARN_RESOURCEMANAGER_USER=root
export YARN_NODEMANAGER_USER=root
export JAVA_HOME=/usr/local/jdk1.8
- 配置核心参数
vi core-site.xml io.file.buffer.size:文件缓冲区大小,默认为4096(4MB),可以按需修改 fs.trash.interval:清理回收站的间隔,单位为分钟,默认为0,表示hdfs里删除的文件不会进入回收站,而是直接删除,可以按需修改
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://master:9000</value>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>file:/usr/local/hadoop/tmp</value>
</property>
<property>
<name>io.file.buffer.size</name>
<value>131702</value>
</property>
<property>
<name>fs.trash.interval</name>
<value>1440</value>
</property>
</configuration>
- 配置hdfs
vi hdfs-site.xml dfs.namenode.name.dir:namenode存储表信息的路径 dfs.datanode.data.dir:datanode存储实际文件数据块的路径 dfs.replication:文件副本个数,不超过datanode的个数 dfs.namenode.secondary.http-address:secondary namenode服务网址,端口号默认为9868,可按需修改
<configuration>
<property>
<name>dfs.namenode.name.dir</name>
<value>file:/usr/local/hadoop/hdfs/name</value>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>file:/usr/local/hadoop/hdfs/data</value>
</property>
<property>
<name>dfs.replication</name>
<value>2</value>
</property>
<property>
<name>dfs.namenode.secondary.http-address</name>
<value>master:9001</value>
</property>
</configuration>
- 配置资源管理
vi yarn-site.xm l yarn.resourcemanager.hostname:yarn管理的主机名 yarn.nodemanager.aux-services:默认 yarn.log-aggregation-enable:是否聚合各子节点的日志信息到主节点,设置为是,不然在web上看不到日志 yarn.log-aggregation.retain-seconds:日志保存时长,单位秒,默认为-1,不删除,可按需设置
<configuration>
<!-- Site specific YARN configuration properties -->
<property>
<name>yarn.resourcemanager.hostname</name>
<value>master</value>
</property>
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<property>
<name>yarn.log-aggregation-enable</name>
<value>true</value>
</property>
<property>
<name>yarn.log-aggregation.retain-seconds</name>
<value>640800</value>
</property>
</configuration>
- 配置分布式计算
vi mapred-site.xml mapreduce.framework.name:用于执行MapReduce作业的运行时框架,可选项是local、classic、yarn,默认为local,我们选yarn mapreduce.jobhistory.address:日志历史服务器地址,默认为0.0.0.0:10020 ,可按需修改 mapreduce.jobhistory.webapp.address:日志历史网页地址,默认为0.0.0.0:19888 ,可按需修改
<configuration>
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
<property>
<name>mapreduce.jobhistory.address</name>
<value>master:10020</value>
</property>
<property>
<name>mapreduce.jobhistory.webapp.address</name>
<value>master: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>
- 配置子节点
vi workers hadoop2配置的slaves ,这是2与3的一大差别 将文中的localhost用我们的datanode的hostname替换
slave1
slave2
- 到此hadoop的配置基本搞定,退出并关闭容器
将此容器保存为新的镜像 docker commit hadoop-test hadoop:base
4、集群搭建
有了上述配置好的hadoop镜像,我们可以快速构建 node 容器
4.1 构建docker网桥
之前说过,hadoop要求节点具有固定ip,docker可以通过network为容器配置固定ip
docker network create --subnet=192.168.0.0/24 hadoop
其中24 表示ip的前24位为固定,后8为可用,即192.168.0.1-192.168.0.254 可用,hadoop 为network的名称,此部分可按需修改
4.2 构建node容器
分别运行如下命令构建master 、slave1 、slave2 三个容器,其中–hostname用于设置node的主机名称,–ip用于配置固定ip
我们为master绑定8088、9870、19888端口号,便于在本地访问
需要注意的是,我们在构建镜像时为容器设置了启动命令CMD ["/usr/sbin/sshd", "-D"] (Dockerfile最后一行,使容器启动时自动启动ssh服务),所以不要使用docker run -itd 来构建容器,否则会被后面自定义的命令(如bash )替换,导致ssh未启动,从而出现22端口无法访问的问题
docker run -d --name master --hostname master --network hadoop --ip 192.168.0.10 -P -p 8088:8088 -p 9870:9870 -p 19888:19888 hadoop:base
docker run -d --name slave1 --hostname slave1 --network hadoop --ip 192.168.0.11 -P hadoop:base
docker run -d --name slave2 --hostname slave2 --network hadoop --ip 192.168.0.12 -P hadoop:base
4.3 配置node免密登录
进入master容器 docker exec -it master bash 生成密钥 ssh-keygen 一直回车就行 将密钥分发给其他node,此过程需要输入 yes 和 密码(Dockerfile里设置的是root )
ssh-copy-id master
ssh-copy-id slave1
ssh-copy-id slave2
进入其他datanode节点做上述同样的操作
4.4 启动服务
ok,终于全都配置好了,回到master 容器去启动服务
- 格式化hdfs
hdfs namenode -format 注意,第一次格式化就行,以后慎用,格式化会导致namenode的clusterID和datanode的clusterID不一致,以致datanode无法启动 - 启动服务
$HADOOP_HOME/sbin/start-all.sh - 启动历史日志服务
$HADOOP_HOME/bin/mapred --daemon start historyserver - 查看启动的服务
jps ,master节点有如下服务表示正常 - 进入
slave1 、slave2 容器,运行 jps ,slave节点有如下服务表示正常
4.5 关闭服务
如果需要关闭服务,可执行以下命令
- 关闭历史任务服务
$HADOOP_HOME/bin/mapred --daemon stop historyserver - 关闭服务
$HADOOP_HOME/sbin/stop-all.sh
5、hadoop测试
5.1 hdfs服务测试
- 在master容器中新建一个文件
vi test.txt ,随便输入一些字符,并保存退出 - 将文件保存到hdfs的根目录
hdfs dfs -put test.txt / - 查看hdfs的根目录内容
hadoop fs -ls / ,可以看到文件已保存到hdfs - 我们也可以通过浏览器访问hdfs管理界面,在浏览器中输入
localhost:9870 ,并在Utilities 中点击Browse the file system ,即可看到文件存储情况,网址端口号根据自己的配置来
5.2 mapReduce服务测试
- 进入hadoop计算样例目录
cd $HADOOP_HOME/share/hadoop/mapreduce - 运行测试样例
hadoop jar hadoop-mapreduce-examples-3.3.2.jar pi 3 100 调用jar包计算pi的值,计算100次(根据自己的hadoop版本修改命令) - 通过浏览器查看,在浏览器中输入
localhost:8088 ,可以查看任务情况以及日志等,网址端口号根据自己的配置来 - 运行完的任务过一段时间会清除,此时可以去历史任务页面查看,网址为
localhost:19888 ,网址端口号根据自己的配置来
结语
写了一晚上终于写完了,最近一周没算白忙活,后面还得继续深入学习,加油~
参考文献
- https://www.cnblogs.com/rmxd/p/12051866.html
- https://www.lousenjay.top/2018/08/21/hadoop3.0%E5%85%A8%E5%88%86%E5%B8%83%E5%BC%8F%E9%9B%86%E7%BE%A4%E6%90%AD%E5%BB%BA/#%E5%89%8D%E6%8F%90%E5%87%86%E5%A4%87
- https://blog.csdn.net/qq_45744501/article/details/112175428
- 官方文档
|