在树莓派上搭建 Hadoop 集群环境

最近在学习 Hadoop,正好前几天又在玩儿树莓派,查阅了一些文档,感觉在树莓派上搭建 Hadoop 集群是可行的,当然了,别对性能抱太大的希望,主要是感受一下分布式计算的魅力。在这个过程中参考了很多文档,先列在这里,基本上这些文档都非常详细了,大家可以直接参考。

How to build 7 node Raspberry Pi Hadoop cluster

Hadoop集群安装配置教程 Hadoop2.6.0 Ubuntu/CentOS

实验软硬件清单

以下是我的实验环境所用的硬件和软件版本清单:

硬件部分:
– 树莓派2B型×6,4 核,1GHz CPU,1GB RAM
– 树莓派用散热片×12,用来超频后的散热
– TF卡×6,64GB,Class 10
– HDMI 线×1,我这里选择的是一端 HDMI,一端 DVI 的,因为我的显示没有 HDMI 接口
– USB 电源线×6,5V,2A。因为树莓派2B型的工作电流是 1.8A@5V 的
– USB 充电器×1,6 口,单口最大电流输出 2.4A
– 网线×6
– 8 口千兆交换机×1,用交换机是想从电脑可以直接访问每一台树莓派,这里用路由器也是可以的

软件部分:
– 操作系统:Raspbian Wheezy
– Java 环境:OpenJDK 7
– Hadoop 2.6.3

树莓派环境准备

给树莓派安装操作系统

给树莓派安装操作系统比较简单,这里需要说一下的是,我用的是苹果笔记本,一般卖树莓派的店附带的工具都是 Windows 版本的,所以,要在苹果操作系统上刷树莓派的卡,可以考虑另外一个小工具 ApplePi Baker:

MacOS X – ApplePi Baker – Prep SD-Cards for IMG or NOOBS

由于我插入的卡是已经做好系统的,所以“Prep for NOOBS”的按钮没有亮起来。如果你用的是一张空白的卡,这个按钮是可以点击的,首先点击这个按钮,完成分区,然后在“IMG file”栏选择 Wheezy 的镜像,通常是一个 .img 文件。选择好之后,就可以通过“Restore Backup”来恢复镜像到 SD 卡了,我的是 USB 2.0 的,大概花费 3-4 分钟。

卡刷完毕之后,查到树莓派,再插上电源线、鼠标和显示器,点亮树莓派,第一次运行,会进入树莓派的设定界面,然后做这么几个操作:

  1. 扩展存储卡,把整张卡都给树莓派用
  2. 设置时区,我这里选择的是 Asia 下面的 Shanghai
  3. 设置编码,建议系统默认编码选择为 en_US.UTF-8 UTF-8
  4. 设置键盘为 Generic-101,布局采用 United States
  5. 开启 SSH 服务
  6. 超频,选择 RPi 2,也就是主频 1000GHz
  7. 设置主机名,这一步可以先不做

完成设定之后,重启树莓派。

更新系统以及安装 Java 环境

先更新系统主要的软件包,为了提高速度,可以选择国内的源。我用的是中科大的源,速度还是很快的,感谢他们为开源软件做出的贡献。

我当时在做的时候是每个卡单独刷的,然后在每个节点上执行更新,花费了太多的时间,所以这里给出另外的方案,未经亲自尝试,如果有问题请大家告知

首先更新 sources.list 文件,修改这个文件需要使用 root 级别,所以这样:

在第一行行首插入一个 # 注释掉,然后在文件末尾加入中科大的源:

保存文件,回到命令行,更新 apt 的源:

然后更新系统:

耐心等待一下,等待 apt 源更新完毕之后,安装 Java 环境,我这里选择的是 openjdk-7-jdk:

OpenJDK 将被安装到 /usr/lib/jvm/java-7-openjdk-armhf,记下来这个路径,后面要用到。

安装完毕 Java 之后,确认一下 Java 的版本:

创建 Hadoop 用户以及设置相关环境

接下来,我们使用 pi 这个用户来创建 Hadoop 相关的用户:

创建 hadoop 用户,所属的组,也是 hadoop,这个用户的 HOME 目录位于 /home/hadoop

hadoop 这个用户加入到 sudo 组,后续的操作将直接使用 hadoop 这个用户,不再需要使用 pi 这个用户了。

sudo' …
Adding user hadoop to group sudo
Done.

hadoop 用户设定一个密码,用来从远程的电脑访问树莓派:

为了实验方便,我为 hadoop 用户设定的密码就是 hadoop,在实际应用场景中,不建议设定这么简单的密码。

然后为 hadoop 用户配置环境变量,首先,我们退出 pi 用户的登录,使用 hadoop 用户直接登录树莓派,登录之后,默认位于他的 HOME 目录,编辑 HOME 目录下的隐藏文件 .bashrc,在最后加入几行内容:

虽然我们还没有开始安装 Hadoop,但是把 Hadoop 相关的环境变量先设置上。然后退出再重新登录,使我们新配置的环境变量生效(也可以不退出,使用 source . .bashrc 来强制环境生效,但是我喜欢重新登录的方式)。重新登陆之后,可以使用 echo $JAVA_HOME 命令来查看是否是我们配置的路径。

配置 hosts 文件

使用 hadoop 用户登录,编辑 /etc/hosts 文件。假定我规划的是 6 个节点对应的主机名为 node1-node6,IP 地址从 101-106。我是直接在路由器上使用 Mac 地址绑定的 IP 地址,也可以在每个节点配置静态 IP 地址。在路由器上使用 MAC 绑定 IP 地址需要等到 6 个树莓派节点都点亮之后,通过 ifconfig -a 命令查看其网卡的 Mac 地址才可以。要编辑这个文件,需要 root 权限,所以需要 sudo vi /etc/hosts,编辑完毕之后, /etc/hosts 文件看起来应该是这样的:

注意,第一次使用 hadoop 用户执行 sudo 命令时,会有一些提示,仔细看这些提示的内容还是很有意思的:

hadoop@raspberrypi ~ $ sudo vi /etc/hosts

We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:

[sudo] password for hadoop:

到这里,第一个节点的准备工作完成了。

复制到另外 5 个树莓派

将第一块做好的树莓派关机 sudo halt,然后断电,将 TF 卡弹出,使用 ApplePi Baker 的“Create Backup”将卡中的内容镜像出来。由于使用的存储卡都比较大,实际使用的空间又比较少,为了减小镜像文件包的体积,建议使用 zip 格式制作镜像。然后开始为每个主机点亮,并且设置主机名。树莓派的配置界面仅在第一次执行,如果还需要调用这个配置界面,可以使用下面的命令:

按照前面的规划,主机名为 node1-node6。

节点间免密码 SSH 登录

Hadoop 集群之间的管理是通过 SSH 来进行的,所以需要将各个节点之间打通免密码 SSH 登录。首先,依次使用 hadoop 账户登录到各个节点,生成 SSH 的密钥对:

屏幕上出现提示的时候,一路回车,直到命令执行完毕返回到 shell 环境,此时,在 hadoop 用户的 $HOME/.ssh 目录下,将产生 2 个文件,分别是 rsa 密钥的私钥( /home/hadoop/.ssh/id_rsa)和公钥( /home/hadoop/.ssh/id_rsa.pub

6 个节点的 rsa 钥匙对生成完毕之后,回到 node1,然后在 $HOME/.ssh 目录下创建认证密钥文件 authorized_keys

然后,依次登录 node2-node6,将他们的 $HOME/.ssh/id_rsa.pub 文件中的内容复制,粘贴到 node1 的 $HOME/.ssh/authorized_keys 中,一行一个。

最终,在 node1 上的 authorized_keys 文件看起来大概是这样的(中间大段的 BASE64 字符串表示的密钥信息已被移除):

接下来,在 node1 节点上,依次 ssh 登录到 node1-node6(要包括自己),第一次 ssh 登录到某个节点的时候,会有提示:

这里要输入 yes,让 node1 记录主机的密钥指纹,接下来按照提示输入密码,然后退出。此时在 $HOME/.ssh/ 目录下会生成 known_hosts 文件。

从 node1 上再依次登录 node2-node6。全部登录完毕之后,就会在 node1 的 .ssh 目录生成完整的 authorized_keys 文件和 known_hosts 文件。

接下来,需要将这两个文件复制到 node2-node6 节点:

至此,系统级的基本工作就完成了,接下来是安装和配置 Hadoop 了。

安装配置 Hadoop

安装 Hadoop

下面的操作,如果没有特殊说明,都是在 node1 上完成的。我们将 node1 规划为 HDFS 的 NameNode,也就是管理节点。

首先下载 Hadoop 2.6.3 版本的安装文件:

Hadoop 2.6.3 下载地址列表页面

接下来,是解压缩、修改文件夹名称以及修改文件夹的属主信息,Hadoop 将被安装到 /usr/local,参考前面步骤设定的 HADOOP_HOME=/usr/local/hadoop。默认情况下,解压缩后的文件夹是带有版本名称的,所以需要重命名。

来验证一下 Hadoop 是否安装成功了吧:

如果能够看到上面的信息,表示 Hadoop 安装成功。

替换 Guava 类库

接下来,还暂时不能进入到 Hadoop 的配置环节,因为有一个 jar 文件的版本有些问题,就是 Google 的 guava 类库,Hadoop 2.6.3 带的是 guava-11.0.2 版本,在我实验的过程中发现,这个版本会有一些问题,会导致创建 HDFS 的时候,无法成功完成 format 动作。

我首先尝试了 guava 的 19.0 版本,发现 HDFS 的 format 正常了,但是后面运行示例任务的时候又出现了问题,又尝试了 15.0 的版本,总算是正常了。国外的论坛上也有很多人对此表示抱怨和不理解,主要是 guava 这个类库的新版本去掉了老版本中的一个构造函数,直接导致无法正常运行测试任务。但是在 Ubuntu 上使用 Hadoop 自带的这个版本,并未发现异常

先去 Maven 仓库获取 guava 的 15.0 版本:

然后编写一个脚本,命名为 guava-fix.sh,放到 hadoop 用户的 HOME 目录,脚本文件的内容为:

给这个脚本赋予执行权限:

然后,将 guava-15.0.jar 以及 guava-fix.sh 复制到 node2-node6 :

然后依次登录 node1-node6,执行 guava-fix.sh 脚本。或者直接使用 SSH 命令远程执行命令也可以。

禁止 JVM 的警告输出

这一点是在实验过程中遇到了问题,搜索了以后找到的解决方案。可能这个问题只有树莓派存在,因为它和本地类库有关系。在 Ubuntu 上没有遇到这个问题。

问题的现象是,在配置完毕 Hadoop 之后,尝试启动 HDFS 的时候,JVM 会输出一行警告信息:

导致 Hadoop 认为这些内容都是要去连接的节点,当然找不到了。所以就会有一大堆类似下面的错误:

对于这个问题的彻底解决办法是在树莓派系统上使用源代码自己构建 Hadoop,当然还有一个投机取巧的方式来解决,就是禁用 JVM 的警告。

编辑 /usr/local/hadoop/etc/hadoop/hadoop-env.sh 文件,找到:

修改为:

配置 hadoop-env.sh

/usr/local/hadoop/etc/hadoop/hadoop-env.sh 这个文件中最主要要修改的有 2 个变量,一个是 JAVA_HOME的路径,一个是 Hadoop 可用的内存。

编辑 hadoop-env.sh 文件,找到:

修改为:

找到:

修改为:

因为我们的小树莓派只有 1GB RAM,要是都分给 Hadoop 进程,会导致内存不足。当然了,上面这个参数只是控制 Hadoop 的 Java 进程最大的内存大小。

配置 Hadoop 核心文件

这里需要配置的文件有: slavescore-site.xmlhdfs-site.xmlmapred-site.xmlyarn-site.xml,都位于 /usr/local/hadoop/etc/hadoop 目录下,后面的叙述不再包含目录。

slaves 文件

slaves 文件的内容是这样的,一行一个节点,节点的名称就是我们在 /etc/hosts 中配置的名称。这里,我计划让 node1 作为 NameNode 和管理节点使用,所以,不把 node1 加入到 slaves 文件中。

slaves 文件内容如下;

core-site.xml

hdfs-site.xml

这里,我们把 Name 和 Data 的目录都放到 hadoop 用户的 HOME 目录下了,
并且设定了 1 个复制节点。

mapred-site.xml

先复制 mapred-site.xml.templatemapred-site.xml,然后,内容如下:

yarn-site.xml

分发 Hadoop 安装包到其他节点

接下来,需要将在 node1 上配置的 Hadoop 文件打包并且传送到其他节点。

依次登录 node2-node6 节点,解压缩,并且修改文件夹属主:

至此,6 个节点上的安装和配置就告一段落了,接下来要进入实际运行的步骤了。

格式化 NameNode

回到 node1 节点,然后开始准备格式化 NameNode 节点:

在屏幕的输出信息中,如果在最后几行输出信息中看到格式化成功的字样(Storage directory /home/hadoop/hdfs/name has been successfully formatted),就表示格式化 NameNode 成功了。

格式化完毕之后,我们在 HDFS 上创建 hadoop 用户的默认目录:

这样就在所有的 DataNode 上创建了 HDFS 的文件夹 /user/hadoop,当运行任务的时候,都是从这个目录开始计算的。

启动服务

终于到了最激动的时刻了,我们来启动 Hadoop 服务看看:

启动 HDFS 服务:

启动 yarn 服务:

启动任务历史记录服务器:

使用 jps 命令验证一下:

上面显示在 node1 上运行的服务,包括资源管理器、任务历史管理器、NameNode、备用 NameNode 以及 Jps 本身。

如果是在 node2 上查看:

然后用浏览器访问 node1(NameNode)的控制台(请忽略截图中的 IP 地址不是 192.168.1.x):

运行示例任务

Hadoop 安装包本身包含了示例任务,可以在 $HADOOP_HOME/share/hadoop/mapreduce 目录下找到 hadoop-mapreduce-examples-2.6.3.jar 文件,直接使用 hadoop 运行这个文件,就会列出来这个文件中包含的全部示例任务:

我们可以运行一下 pi 这个任务,大部分的教程都是运行 wordcount 任务,因为我们是在树莓派上玩儿的,所以我们还是运行一下 pi 这个任务吧:

So, Enjoy your Hadoop on Raspberry Pi!

发表评论

电子邮件地址不会被公开。 必填项已用*标注