WSL 与 Hyper-V 中安装 Hadoop
安装前准备
根据 Hadoop Java Versions,最新版 Hadoop 支持 Java 8 与 Java 11 的运行时环境,同时还支持 Java 8 的编译。此外,Apache Hadoop 社区编译测试都使用 OpenJDK,因此这里我们选择安装 OpenJDK 8。Ubuntu 仓库中的 headless 版 JDK 是针对无需 GUI 界面的 Java 程序的软件包,占用空间更小。
此外,Hadoop 官方文档要求安装并启用 ssh,并且推荐安装 pdsh 更好地管理 ssh 资源。
1 | sudo apt install openjdk-8-jdk-headless ssh pdsh |
使用命令 sudo service ssh start
启动 ssh(WSL 不能使用 systemctl,只能用 SysV init 的命令),若出现 sshd: no hostkeys available -- exiting.
的错误,使用 sudo ssh-keygen -A
生成一个 hostkey 后重试。
从 https://hadoop.apache.org/releases.html 下载合适的二进制版本压缩包(这里选择 hadoop 3.3.4)。
安装 Hadoop
使用 tar xvaf hadoop-3.3.4.tar.gz
解压,随后进入 hadoop-3.3.4 目录,编辑目录下的 etc/hadoop/hadoop-env.sh
文件,定义环境参数:
1 | # 设置 Java 安装的根目录,若使用 apt 安装 openjdk-8-jdk-headless,路径应为下述路径 |
随后在目录中执行 bin/hadoop
可以看到一些简要说明。
Okay…… 其实已经安装结束了,可以使用单机模式的 Hadoop 了。
尝试一下 Hadoop 提供的 MapReduce 的示例程序:
1 | mkdir input |
如果没有问题的话会出现很多运行信息,最后的文件内容输出是:
1 | neko@ubuntu:~/hadoop-3.3.4$ cat output/* |
伪分布式集群配置
伪分布式集群指在一台机器上开多个 Hadoop 的 Java 进程来模拟在多台机器上运行 Hadoop 的效果。
修改配置文件
在目录中编辑 etc/hadoop/core-site.xml
文件:
找到最末尾的
1 | <configuration> |
替换为
1 | <configuration> |
编辑 etc/hadoop/hdfs-site.xml
文件:
找到最末尾的
1 | <configuration> |
替换为
1 | <configuration> |
配置免密码登录 ssh
尝试使用 ssh localhost
连接本地 ssh。
若出现 ssh: connect to host localhost port 22: Connection refused
的问题,可能是 ssh 未启动,可以使用 sudo service ssh status
查看 ssh 的状态。
若连接需要密码,需要使用如下命令创建密钥以实现免密码登录:
1 | ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa |
运行 MapReduce 任务
格式化文件系统:
1
bin/hdfs namenode -format
启动 NameNode 守护进程和 DataNode 守护进程:
1
sbin/start-dfs.sh
若出现类似
pdsh@ubuntu: localhost: rcmd: socket: Permission denied
的错误,可能是 pdsh 的默认 rcmd 配置不是 ssh。使用
pdsh -q -w localhost
命令检查,若Rcmd type
一栏内容不是 ssh,在~/.bashrc
或你的 shell 解释器配置文件中加入export PDSH_RCMD_TYPE=ssh
,并使用source ~/.bashrc
或你的 shell 解释器对应命令更新当前配置。随后再次尝试。
浏览器中打开 NameNode 网页接口,应该能看到相关信息。URL 默认是 http://localhost:9870/
创建 HDFS 用户目录以运行 MapReduce 任务:
1
2bin/hdfs dfs -mkdir /user
bin/hdfs dfs -mkdir /user/<username> # <username> 替换为你当前系统的用户名,以下命令若未使用绝对路径,则默认是从 /user/<username> 开始检索的复制任务输入文件到分布式文件系统中:
1
2bin/hdfs dfs -mkdir input
bin/hdfs dfs -put etc/hadoop/*.xml input尝试执行示例程序:
1
bin/hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.3.4.jar grep input output 'dfs[a-z.]+'
和单机示例程序一样,如果没有问题的话会出现很多运行信息。
从分布式文件系统中拷出文件至本地并检查:
1
2
3执行命令前记得先删掉之前单机示例程序创建的 output 目录,不然会拷出到那个目录下
bin/hdfs dfs -get output output
cat output/*或者可以直接查看分布式文件系统中的文件:
1
bin/hdfs dfs -cat output/*
运行结果应该是:
1
21 dfsadmin
1 dfs.replication结束守护进程:
1
sbin/stop-dfs.sh
Hadoop 守护进程的日志会写入 $HADOOP_LOG_DIR
文件夹,此文件夹默认在 $HADOOP_HOME/logs
。
多开虚拟机配置“真”分布式集群
通常,集群中需要有一台 NameNode,一台 ResourceManager,它们是主服务器用于控制。其他服务(例如 Web App Proxy Server 和 MapReduce Job History 服务器)通常在专用硬件或共享基础设施上运行,具体取决于负载。
集群中的其余机器同时充当 DataNode 和 NodeManager,作为从服务器用于计算。
在这套模拟配置中,我们开三台 Hyper-V 虚拟机,均部署 DataNode
和 NodeManager
服务,1 号额外部署 NameNode
和 ResourceManager
服务。
这里之所以不用 WSL 是因为 WSL 开多个发行版实际上是在一台虚拟机中运行的,这会导致多个发行版(虚拟磁盘)系统用的 IP 是同一个,不便于批量管理。
配置 Hadoop
Hadoop 有两类重要的配置文件:
- 只读的默认配置文件
core-default.xml
,hdfs-default.xml
,yarn-default.xml
和mapred-default.xml
.
- 每个站点单独的配置文件
etc/hadoop/core-site.xml
,etc/hadoop/hdfs-site.xml
,etc/hadoop/yarn-site.xml
和etc/hadoop/mapred-site.xml
.
此外还有环境配置的文件,比如 etc/hadoop/hadoop-env.sh
。
要配置集群,需要配置 Hadoop 守护服务器的 environment
与 configuration parameters
参数。
HDFS 的守护服务器包括 NameNode、SecondaryNameNode 和 DataNode。YARN 的守护服务器有ResourceManager、NodeManager 和 WebAppProxy。如果要使用 MapReduce,那么 MapReduce Job History 服务器也将运行。对于大型集群,它们通常运行在不同的主机上。
配置环境
和前面一样,先配置 etc/hadoop/hadoop-env.sh
中的 Java 路径。
各个守护进程还有各自的运行环境配置选项,如 Java 虚拟机内存等,可以在 etc/hadoop/hadoop-env.sh
看到各选项的说明和示例,这里暂时不做配置。
此外,通常还会配置 HADOOP_HOME
环境变量,可以在 /etc/profile.d
文件夹中添加一个 sh 文件,包含以下两行:
1 | HADOOP_HOME=/home/neko/hadoop-3.3.4 # 这里填写 Hadoop 的路径 |
使用 source /etc/profile
使其生效。
配置 hosts
为方便起见,可以配置 /etc/hosts
文件指定各台 Hadoop 服务器的 IP 到某个 hostname。
此外,要在 /etc/hostname
中将不同的虚拟机修改为不同的主机名,避免在管理面板中发现多个节点合并显示的情况。
下面的配置均使用 hadoop00x 代替第 x 台虚拟机的 IP 地址。
配置密钥
和上面一样,为三台服务器配置各自的密钥。
此外还需将 1 号虚拟机的公钥写到 2 号、3 号虚拟机的 ~/ .ssh/authorized_key
文件中:
1 | ssh-copy-id -i ~/.ssh/id_rsa.pub hadoop002 |
配置守护进程
编辑 etc/hadoop/core-site.xml
,将末尾几行修改为:
1 | <configuration> |
fs.defaultFS
:NameNode 的 URI,值的格式为hdfs://host:port/
io.file.buffer.size
:顺序文件的读写缓存大小。hadoop.tmp.dir
:Hadoop 集群存储临时文件的目录
编辑 etc/hadoop/hdfs-site.xml
:
1 | <configuration> |
dfs.namenode.name.dir
:NameNode 持久存储命名空间和事务日志的本地路径,可用逗号分隔多个路径以存储多份。dfs.hosts
/dfs.hosts.exclude
:允许/排除的 DataNode,如有必要可以设置。dfs.blocksize
:HDFS 大文件系统的块大小。dfs.namenode.handler.count
:NameNode 服务线程数。dfs.datanode.data.dir
:在 DataNode 中存储块的本地路径列表,以逗号分隔。如果这是一个逗号分隔的目录列表,那么数据将存储在所有目录中,通常会设置不同的设备/磁盘。
编辑 etc/hadoop/yarn-site.xml
:
1 | <configuration> |
yarn.resourcemanager.hostname
:可以设置它来代替设置所有yarn.resourcemanager*address
地址资源。端口为 ResourceManager 组件的默认端口。yarn.nodemanager.aux-services
:若需要使用 MapReduce 需要设置成mapreduce_shuffle
- 其余配置省略
编辑 etc/hadoop/mapred-site.xml
:
1 | <configuration> |
mapreduce.framework.name
:执行框架(local / yarn)mapreduce.map.memory.mb
:map 资源限制(单位:MB)mapreduce.map.java.opts
:用于 map 的子 jvm 的堆大小mapreduce.reduce.memory.mb
:reduce 资源限制(单位:MB)mapreduce.reduce.java.opts
:用于 reduce 的子 jvm 的堆大小mapreduce.task.io.sort.mb
:用于排序以提高效率的内存限制mapreduce.task.io.sort.factor
:在对文件排序时一次合并的流mapreduce.reduce.shuffle.parallelcopies
:reduce 从大量的 map 中获取输出所运行的并行副本数mapreduce.jobhistory.address
:MapReduce Job History 服务的host:port
,默认端口为 10020mapreduce.jobhistory.webapp.address
:MapReduce Job History 的 Web UI 的host:port
,默认端口为 19888mapreduce.jobhistory.intermediate-done-dir
:MapReduce 作业写入历史文件的目录mapreduce.jobhistory.done-dir
:由 MapReduce Job History 服务管理历史文件的目录。
编辑 etc/hadoop/workers
:
一行一个所有的 woker 的 hostname:
1 | hadoop001 |
Hadoop 管理
1 | 在 NameNode 节点(hadoop001)上格式化 HDFS |
默认管理端口号:
HDFS:9870
YARN:8088
可以通过 hadoop001:9870
和 hadoop001:8088
或者使用对应 IP 查看相应的管理面板。
注意请谨慎使用格式化命令,多次格式化后会导致 NameNode 的 clusterID 和 DataNode 的 clusterID 不匹配,无法启动 DataNode。如果在 HDFS 的管理界面中发现 Live Nodes 数为 0,在 DataNode 节点中使用 jps
查看发现没有 datanode 进程,可能就是这个原因导致的。这个时候可以选择从头重来一遍,或者修改配置文件(直接在 hadoop 目录下搜索文件名 VERSION
)以匹配两者的 clusterID,或者删除 DataNode 节点 hadoop 目录下的 blocks 文件夹,删除 NameNode 节点 hadoop 目录下的 data 文件夹,以及所有节点 hadoop 目录下的 logs 文件夹,重新格式化后启动。