在 Ubuntu 20.04 LTS 上搭建 Hadoop 环境

本文适用于 Ubuntu 20.04,对于 Ubuntu 22.04 或者更新版本的用户,请见此处

在古时候,人们用牛来拉重物。当一头牛拉不动一根原木时,人们从来没有考虑过要想方设法培育出一种更强壮的牛……

Grace Murray Hopper,美国计算机科学家

在 Apache 基金会的项目中,除了历史悠久、广泛使用的 httpd 网页服务器以外,在业界使用最广泛的技术可能就非 Hadoop 莫属了。Hadoop 提供了针对海量数据可靠的、可拓展的分布式计算解决方案。这些年来我们总能听到一些关于“Hadoop 已死?”的论调。但是来自各个云服务提供商的产品(失效链接)表明,Hadoop 及周边生态仍然在不断良性发展,并且持续触及至更多领域之中。时至今日,Hadoop 仍然是分布式处理海量数据的最佳解决方案。

我个人反感博客中充斥“xxx 如何配置”之类的工具类文章,这些主题出现在这些工具的官方文档和新手入门里会更好。但说到 Hadoop,它已经成为大数据方面的“生态标准”:既支持单机运行,甚至亦支持成百上千台机器组成集群运行。然而,不论是官方文档,还是社区上大多数人写的“配置教程”,我认为都没有向一个刚接触 Hadoop 生态的新手介绍我们做这些配置“是为了什么”、“有什么意义”,遂写本文,以作参考。

安装前的准备工作

我们在 Ubuntu 20.04 LTS 的基础上搭建 Hadoop 基础环境。该环境包含大数据分析框架 Hadoop、用于进行数据分布式分析的 MapReduce,以及用于分布式存储数据的 Hadoop 文件系统(HDFS)三部分。这是运行其他大数据周围组件的基础环境。

大数据——数据量足够大或复杂,以至于单节点无法处理。

一种我喜爱的对于大数据的定义方式

Hadoop 设计为任意复杂度的数据进行处理,由于实际可能分析的数据量跨度非常大:从单机可存储一直到需要大规模数据中心才能承载,Hadoop 提供了多种灵活的配置方式。由于面向入门用户,我们假设我们在单台物理计算机中使用伪分布式(Pseudo-Distributed)环境进行配置

出于权限隔离最佳实践(失效链接)的考虑,我们在系统中考虑为 Hadoop 创建单独的用户账户和组:

sudo adduser hadoop

Hadoop 基础组件及其外围项目大多是基于 Java 的,要运行 Hadoop,我们需要在系统中安装 Java 运行时环境(JRE)。有多种 JRE 可供选择,我们使用 openjdk-8 作为 JRE。Hadoop 官方文档中说明了对 Java 版本的支持情况。经测试,使用 openjdk-11 会导致 YARN 启动时出现某个错误。Hadoop 框架使用 SSH 协议与本地(或远程计算机)进行通信,我们需要在本地计算机中安装 SSH 服务器守护程序。

sudo apt install openjdk-8-jdk openssh-server -y

Hadoop 通常运行于分布式环境中。在这种环境下,它使用 SSH 协议与自己(或其他服务器)进行通信,为了能够配置 Hadoop 更安全地与服务器进行通信,我们为本地环境 hadoop 用户生成公-私密钥对,以支持 SSH 中的密钥对认证

sudo -u hadoop ssh-keygen -b 4096 -C hadoop
sudo -u hadoop ssh-copy-id localhost -p 22

上述命令生成带备注信息的长度为 4096 位的 RSA 密钥,并将密钥复制至本地计算机中,用于支持 SSH 密钥对认证方式。

获取 Hadoop 的发行版本

Hadoop 的各种发行版本通常从 Hadoop 官方网站的下载页面Apache Bigtop 项目或诸如 Cloudera Manager 等再发行版中获取。为便于讲解,我们使用来自 Hadoop 官方网站的发行版本 3.2.1 举例。我们准备将相关发行版本安装至文件系统的 /opt 目录下(另一个标准选择是 /usr/local)。我们从下载页面的任一镜像站点下载相关版本的二进制文件档案:

wget "https://mirrors.sonic.net/apache/hadoop/common/hadoop-3.2.1/hadoop-3.2.1.tar.gz"

然后,将其解压至 /opt(或者其他你喜爱的位置)中,后续指令均假设你将 Hadoop (及其周边组件)安装至 /opt 目录中:

sudo tar -zxvf hadoop-3.2.1.tar.gz -C /opt

为使用单独的 hadoop 用户操作,我们赋予 hadoop 用户 Hadoop 软件目录的拥有权:

sudo chown hadoop:hadoop -R /opt/hadoop-3.2.1

截至目前,我们已经完成了所有对于 Hadoop 的准备和安装工作,接下来我们切换为 hadoop 用户,并前往安装目录下,开始配置 Hadoop 的工作:

su hadoop
cd /opt/hadoop-3.2.1

配置 Hadoop 相关软件

Hadoop 并非是一个软件,而是一系列大数据存储及处理的工具集合。所以,有必要针对常用的基础组件进行配置,以完成 Hadoop 环境的搭建。

配置环境变量

很显然,我们最喜欢使用类似于 hdfs 而非 /opt/hadoop-3.2.1/bin/hdfs 的方式执行 Hadoop 命令。作为 hadoop 用户执行如下命令将 Hadoop 的相关变量添加至环境变量中,如果不想每次都输入,可以将这些命令添加至 ~/.bashrc 文件末尾:

export HADOOP_HOME=/opt/hadoop-3.2.1
export HADOOP_INSTALL=$HADOOP_HOME
export HADOOP_MAPRED_HOME=$HADOOP_HOME
export HADOOP_COMMON_HOME=$HADOOP_HOME
export HADOOP_HDFS_HOME=$HADOOP_HOME
export YARN_HOME=$HADOOP_HOME
export HADOOP_COMMON_LIB_NATIVE_DIR=$HADOOP_HOME/lib/native
export PATH=$PATH:$HADOOP_HOME/sbin:$HADOOP_HOME/bin
export HADOOP_OPTS="-Djava.library.path=$HADOOP_HOME/lib/native"

如果你选择将这些命令添加至 ~/.bashrc 中,你需要通过下列命令重新加载你的 .bashrc 配置:

source ~/.bashrc

配置 Hadoop 基础框架

为顺利运行 Hadoop 组件,我们有必要告诉 Hadoop 有关 Java 运行时环境(JRE)的位置信息。Hadoop 框架的基础配置文件位于 ./etc/hadoop/hadoop-env.sh 中,我们只需要修改其中的 JAVA_HOME 行。如果你使用其他方式(比如非标准端口)通过 SSH 客户端连接到(本地)服务器,则需要额外修改 HADOOP_SSH_OPTS 行:

export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
export HADOOP_SSH_OPTS="-p 22"

Hadoop 生态的大多数组件采用 .xml 文件的方式进行配置。它们采用了统一的格式:即将配置项填写在每个配置文件的 <configuration></configuration> 之间,每个配置项通过以下的方式呈现:

<property>
<name>配置项名称</name>
<value>配置值</value>
</property>

我们配置 Hadoop 的核心变量,这些配置位于 ./etc/hadoop/core-site.xml 配置文件中:

配置项
fs.defaultFShdfs://localhost/

……也就是说,将 ./etc/hadoop/core-site.xml 配置文件的 <configuration> 部分替换为以下内容:

<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://localhost/</value>
</property>
</configuration>

这将设置 Hadoop 默认的文件系统为本地 HDFS。Apache Hadoop 项目中提供了一份完整的配置项列表

配置 HDFS(Hadoop 文件系统)

在使用 Hadoop 文件系统(HDFS)之前,我们需要显式配置 HDFS,以指定 NameNode 与 DataNode 的存储位置。我们计划将 NameNode 与 DataNode 存储于本地文件系统上,即存放于 ~/hdfs 中:

mkdir -p ~/hdfs/namenode ~/hdfs/datanode

我们将以下属性添加至 HDFS 的配置文件 ./etc/hadoop/hdfs-site.xml 中,以体现这一点:

配置项
dfs.replication1
dfs.name.dir/home/hadoop/hdfs/namenode
dfs.data.dir/home/hadoop/hdfs/datanode
请参考上方配置 ./etc/hadoop/core-site.xml 文件的方式来将这些配置项添加到配置文件中

首次启动 Hadoop 环境之前,我们需要初始化 Namenode 节点数据:

hdfs namenode -format

忘记初始化 Namenode 节点可能导致遇到 NameNode is not formatted. 错误。

配置 MapReduce(由 YARN 驱动)

MapReduce 是一种简单的用于数据处理的编程模型,YARN(Yet Another Resource Negotiator)是 Hadoop 的集群资源管理系统。我们使用与上边类似的方法编辑 ./etc/hadoop/mapred-site.xml 文件,配置以下项目:

配置项
mapreduce.framework.nameyarn

同样地,我们编辑 ./etc/hadoop/yarn-site.xml 文件:

配置项
yarn.nodemanager.aux-servicesmapreduce_shuffle
yarn.resourcemanager.hostnamelocalhost

启动 Hadoop 集群环境

上述配置完成后,我们启动 Hadoop 的相关服务:

start-dfs.sh
start-yarn.sh
mr-jobhistory-daemon.sh start historyserver

这将启动以下守护进程:一个 namenode、一个辅助 namenode、一个 datanode(HDFS)、一个资源管理器、一个节点管理器(YARN)以及一个历史服务器(MapReduce)。为验证 Hadoop 相关服务启动成功,我们使用 JDK 中提供的 jps 命令。该命令显示所有正在运行的 Java 程序。

jps

你可以通过访问该主机的 9870 端口,以查看 HFS 的相关情况。如果你发现某些组件未按预期工作,你可以在 Hadoop 安装目录的 ./logs 下找到各服务对应的运行日志进行排查。

其他可选组件的安装

不同于 Hadoop 的基础框架,这些组件通常是可选的,并且是随需求安装的。我们在此介绍一些工具的安装与配置。

Hive

Hive 是构建于 Hadoop 上的数据仓库框架,用于在分布式存储的架构上读取、写入并管理大规模数据集,并使用 SQL 语法进行查询。它将 SQL 查询转换为一系列在 Hadoop 集群上运行的作业,特别适合熟悉 SQL 而不善于使用 Java 进行数据分析的用户。通过 Hive 官方网站下载最新版本的 Hive 发行版,我们使用 3.1.2 版本:

wget "http://mirrors.ibiblio.org/apache/hive/hive-3.1.2/apache-hive-3.1.2-bin.tar.gz"

与安装 Hadoop 基础组件的方法类似,我们将 Hive 解包到 /opt 中。类似地,我们修改 apache-hive-x.y.z-bin 目录的拥有者:

sudo tar -zxvf apache-hive-3.1.2-bin.tar.gz -C /opt
sudo chown hadoop:hadoop -R /opt/apache-hive-3.1.2-bin

与 MySQL 发行版本类似,我们使用 mysql_secure_installation 命令配置 MariaDB,设置数据库 root 用户密码。

然后我们以 hadoop 的身份修改 ~/.bashrc 文件,以添加与 Hive 执行相关的环境变量配置。以下命令需要以 hadoop 用户身份运行:

export HIVE_HOME=/opt/apache-hive-3.1.2-bin
export PATH=$PATH:$HIVE_HOME/bin

通过 source ~/.bashrc 应用更改后,我们配置Hive 使用的关系型数据库。 Hive 将数据仓库的数据(存放于 HDFS 上)与描述这些数据的元数据存放于不同的位置。其中,元数据(Metastore)一般存放于关系型数据库中。我们以 Apache Derby 为例:

schematool -dbType derby -initSchema

需要注意,由于本教程示例中使用的 Hadoop 3.2.1 版本,与 Hive 3.1.2 版本中均包含 guava 组件,但其版本并不兼容,如果在运行 hive 指令时遇到 java.lang.NoSuchMethodError 错误,请考虑使用下列变通方法:

rm /opt/apache-hive-3.1.2-bin/lib/guava-19.0.jar
cp /opt/hadoop-3.2.1/share/hadoop/hdfs/lib/guava-27.0-jre.jar /opt/apache-hive-3.1.2-bin/lib/

截止目前,我们就可以使用 hive 命令访问由本地 Derby 元数据库承载的存储于 HDFS 上的数据仓库了。