本文适用于 Ubuntu 20.04,对于 Ubuntu 22.04 或者更新版本的用户,请见此处。
在 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.defaultFS | hdfs://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.replication | 1 |
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.name | yarn |
同样地,我们编辑 ./etc/hadoop/yarn-site.xml
文件:
配置项 | 值 |
yarn.nodemanager.aux-services | mapreduce_shuffle |
yarn.resourcemanager.hostname | localhost |
启动 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 上的数据仓库了。