hadoop集群配置

本文对 hadoop 的基础背景知识 以及 hadoop集群的安装、基础配置进行了总结。

1. Hadoop 架构

hadoop 2.x 开始,hadoop 主要由下面4个部分组成:

  • MapReduce - 用于计算;
  • Yarn - 资源调度;
  • HDFS - 数据存储;
  • Common - 辅助工具。

具体地,

HDFS 存储又可以分为两部分:

  • NameNode(nn): 相当于目录,存储文件的文件名、文件目录结构、文件属性等元数据。
  • Secondary NameNode(2nn): 辅助 namenode 的工作,监控 HDFS 状态,并进行 namenode 的备份(隔一段时间获取一次 namenode 的快照)。
  • DataNode(dn): 存储具体的文件数据。

yarn 资源管理调度工具,从顶层到底层可以分为4个部分:

  • Resource Manager
    • 直接对接客户端的请求;监控 node manager;启动、监控 application master;
  • Node manager
    • 管理每个节点(服务器)上的资源;处理来自 resource manager 的命令;处理来自 application master 的命令;
  • Application master
    • 为每个单独的任务服务。具体负责数据的切分,为应用程序申请资源等。
  • Container
    • yarn 中资源的抽象,封装了结点上的例如内存、cpu、磁盘等资源。

MapReduce 是具体的计算环节,主要包括两部分:

  • Map 阶段:并行处理输入数据;
  • Reduce 阶段:对 map 分析结果进行汇总。

2. Hadoop 配置

为了模拟 hadoop 真是的工作环境,我们尝试在windows 上使用 vmware 安装3台 centos 的虚拟机,来构成一个 hadoop cluster。

2.1 虚拟机的安装配置

使用 vmware 安装虚拟机,它有基础版和 pro 版之分,基础版是免费的,因此,我安装了基础版的,连接。相对来说,基础版缺少了直接的虚拟机拷贝镜像等高阶功能,在后续的配置中,稍麻烦一点的地方是需要安装系统3次,而pro版直接镜像拷贝即可。

安装的 linux 系统为 centos7, 主要是为了和多数教程中一致。

linux 安装过程中,基本全部默认即可,并同样的方法安装3台虚拟机。

安装完成后,需要进行如下设置。

a. 添加用户

安装时配置了 root 用户,此时要在系统中添加一个额外的用户,用于处理具体的hadoop 工作事务。设置过程如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 创建用户
adduser lab1 # 创建名为 lab1 的用户
# 设置密码
passwd lab1 # 111111

# 授权
whereis sudoers # 可以查看 sudoers 文件在哪里
ls -l /etc/sudoers # 查看对应文件的权限
# -r--r----- 1 root root 4251 9月 25 15:08 /etc/sudoers 发现只有只读权限
chmod -v u+w /etc/sudoers # 添加 w 权限
vim /etc/sudoers # 修改文件
# 文件修改部分如下

## Allow root to run any commands anywhere -- 在文档的接近最后面
root ALL=(ALL) ALL
lab1 ALL=(ALL) ALL

# 修改完毕后,将 /etc/sudoers 文件的写权限收回
chmod -v u-w /etc/sudoers

b. 设置网络

hadoop 需要在多台机器间进行通讯,因此,欲让集群中的机器能够正确的找到对应的结点,需要让各台机器的 ip 地址固定。

对于虚拟机设置来说,最方便的是使用 NAT 模式,使用 虚拟机提供的网卡 Vmnet8 作为子网的终端路由器,查询电脑上该块网卡的 ipv4 地址,我的为:ip: 192.168.237.1, 子网掩码:255.255.255.0

然后,我们配置虚拟机的 /etc/sysconfig/network-scripts/ifcfg-ens33 网络配置文件(note:ens33 为网卡名,有的centos上网卡名为 eth0, 可以通过 ip add 查看到系统的网卡信息,找到网卡名)。下面是文件中需要 修改 或添加的字段:

1
2
3
4
5
6
7
BOOTPROTO=static
ONBOOT=yes
PREFIX=24
GATEWAY=192.168.237.2
IPADDR=192.168.237.3
NETMASK=255.255.255.0
DNS1=192.168.237.2

BOOTPROTO 是 ip 分配方式,需要从原来的 DHCP 改为 static,DNS1 不能忘记配置,否则使用 yum 等安装软件时,无法用解析域名。最后,有的配置教程中还添加了 HWADDR=00:0C:29:D8:CA:20 mac 地址字段,经测试,这一字段可以不写。

配置完毕后,service network restart 重启网络即可。

问题解决: 用时候网络无法启动,可能是因为与 NetworkManager 服务冲突(ref), 使用指令 service NetworkManager stop 关闭该服务,然后再重启网络即可。

c. 设置主机别名、关闭防火墙

为方便机器间的通讯,我们修改各个主机的 hostname,并在各个机器中修改 /etc/hosts 文件,来保存ip地址和 主机名称之间的映射关系。

修改 hostname 的方法为:hostnamectl set-hostname master (设置 主机的 hostname 为 master)。然后,在 /etc/hosts 文件下添加 ip 与 hostname之间的关系:

1
2
3
192.168.237.3 master
192.168.237.4 slave1
192.168.237.5 slave2

此外,为了方便 windows 使用网页访问 hadoop 的相关 log 页面,修改windows 上 C:\WINDOWS\system32\drivers\etc 文件,也添加相同的内容即可, 参考.

最后,为了方便 本地机访问,关闭centos虚拟机的防火墙:sudo systemctl stop firewalld

d. 配置 ssh 无密码登录

为了方便后序hadoop 结点之间的互相访问,我们配置各个结点直接的 ssh 无密码访问。ssh 访问的原理是利用公钥和私钥进行加密通信,服务器 A 实现无密码安全访问服务器 B 的方法如下:

  1. 在 A 服务器上,ssh-key-gen 生成一个秘钥对,包括一个 公钥 A 和 私钥 A。
  2. 将 A 服务器的 公钥 A 拷贝到 B 服务器上,并授权该 key。
  3. 服务器 A 使用 ssh 访问服务器 B,使用 服务器 A 的私钥进行加密。
  4. 服务器 B 接收到数据后,去授权 key 中寻找到 服务器 A 的公钥,并解密数据。
  5. 服务器 A 采用 A 的公钥加密数据后返回给 A 服务器。
  6. 服务器 A 收到 B 发送的数据后,使用 私钥进行解密即可。

具体操作是,若希望 master 机器能够无密码访问 slave1 和 slave2,执行下述指令:

1
2
3
4
5
6
7
8
9
10
11
cd ~/.ssh  # 切换到 .ssh 目录 -- 注意是当前用户 家目录下的 .ssh
ssh-keygen -t rsa # 生成 ssh 公钥私钥对
# 询问 passphrase 等内容,全部 默认回车跳过即可。
# 完毕后会生成两个文件:
id_rsa
id_rsa.pub

# 最后拷贝公钥
ssh-copy-id slave1 # 在 slave1 的 .ssh 目录下会添加一个 authoried_keys
ssh-copy-id slave2
ssh-copy-id master # 可以免密登录自己 ...

2.2 hadoop 的安装配置

hadoop 的安装配置参考官网: 单节点配置, 集群配置

a. hadoop 的安装

安装操作可以仅在一台虚拟机上进行配置,后序使用远程拷贝,远程分发功能进行拷贝即可。

首先,我们在 centos 中新建文件夹 /opt/software/ 用于放置待安装的安装包,以及 /opt/module/ 文件夹用于放置安装的文件。

新建这两个文件夹之后,为了方便读写,我们修改它们的读写权限,sudo chown lab1:lab1 /opt/module/ /opt/software/

hadoop 的运行需要 jdk 的支持,因此,我分别下载了 jdk 的安装包和 hadoop 的安装包,通过 xftp 从本地机传输到虚拟机,放置在了 software 文件夹下。

安装过程参考下面的指令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
################################################
# java 安装
tar -zxvf jdk-8u281-..... -C /opt/module # 解压后放置到 module 文件夹下
# 配置环境变量
sudo vi /etc/profile

# 在文档末尾添加如下内容。

## JAVA_HOME
export JAVA_HOME=/opt/module/jdkxx
export PATH=$PATH:$JAVA_HOME/bin # 刚开始忘记加 $JAVA_HOME 前面的 $ 符号,source之后一直无效

# 让配置生效
source /etc/profile

# 查看 java 安装情况
java -version

################################################
# hadoop 安装
tar -zxvf hadoop-2.8.3xxxx.tar.gz -C /opt/module/

ll # 查看目录下的内容
pwd # 查看当前目录

# 配置环境变量
sudo vi /etc/profile

# 切换到最后一行,添加下述内容

## HADOOP_HOME
export HADOOP_HOME=/opt/module/hadoop-2.8.3
export PATH=$PATH:$HADOOP_HOME/bin
export PATH=$PATH:$HADOOP_HOME/sbin

source /etc/profile
hadoop # 查看安装情况

有一些教程中提到需要进行本地编译,一般是对于比较早先的 hadoop 版本来说,由于较早的hadoop 版本仅提供编译好的 32 位版本(主要是 hadoopx.x.x/lib 文件夹中的库文件)。但是较新的 hadoop 版本都开始提供64位版本的编译安装包了,因此不再需要通过编译源码来获得 64 位版本的 hadoop 了。查看自己的 hadoop 的版本的方法(link).

b. 配置 hadoop

如最前面官方文档中所述,hadoop 有多种安装模式, 这里简单记录我使用虚拟机进行集群配置的步骤。

配置之前,回顾前面 hadoop 的组成部分,我们首先规划各个结点服务器上的放置的内容:

  • master: hdfs- datanode; yarn- resourceManager + nodeManager;
  • slave1: hdfs- nameNode + datanode; yarn- nodeManager;
  • slave2: hdfs- secondarynameNode + datanode; yarn- nodeManager;

在上面的规划中,需要注意的是:nameNode 和 secondaryNameNode 以及 resourceManager 由于占用空间都比较大,应该分配在三台单独的服务器上。

规划完毕后,就开始修改 hadoop 中位于 etc/hadoop/ 文件夹下的配置文件。

hdfs, 首先修改核心的 hadoop 配置文件,指定 hadoop 中 namenode 的位置,具体的,在 core-site.xml 文件中添加下述字段:

1
2
3
4
5
6
7
8
9
10
11
<!-- 指定HDFS中NameNode的地址 -->
<property>
<name>fs.defaultFS</name>
<value>hdfs://slave1:9000</value>
</property>

<!-- 指定Hadoop运行时产生文件的存储目录 -->
<property>
<name>hadoop.tmp.dir</name>
<value>/opt/module/hadoop-2.8.3/data/tmp</value>
</property>

hdfs: 配置完毕了 namenode,secondarynamenode 的配置在 hdfs-site.xml 进行,添加下面的配置:

1
2
3
4
5
6
7
8
9
10
11
<!-- 指定文件的备份数,默认的就是3,所以这里也可以不配 -->
<property>
<name>dfs.replication</name>
<value>3</value>
</property>

<!-- 指定Hadoop辅助名称节点主机配置 -->
<property>
<name>dfs.namenode.secondary.http-address</name>
<value>slave2:50090</value>
</property>

yarn: 首先指定 mapreduce 运算在 yarn 上。在 mapred-site.xml 文件中,添加下述配置项:

1
2
3
4
5
<!-- 指定MR运行在Yarn上 -->
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>

然后,配置 yarn 的相关服务,在 yarn-site.xml 中进行设置,添加下列配置字段:

1
2
3
4
5
6
7
8
9
10
11
<!-- Reducer获取数据的方式 -->
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>

<!-- 指定YARN的ResourceManager的地址 -->
<property>
<name>yarn.resourcemanager.hostname</name>
<value>master</value>
</property>

最后,我们需要修改 mapred-env.sh, yarn-env.sh, hadoop-env.sh 文件,在他们中修改 java path 为 前面安装的 java 的根目录(e.g. export JAVA_HOME=/opt/module/jdk1.8.0_281),保证指令执行时能够找到 jdk 的正确位置。

此外,还可以配置历史服务器(log),日志聚集服务器 以及集群的时间同步功能等其他配置。

c. 启动 hadoop

准备工作

启动之前,我们首先要确保之前的 namenode 和 datanode 已经关闭,通过 jps 可以查询。然后,一般要删除之前的数据与 logs。rm -rf data/ logs/, 然后再重新格式化结点:hdfs namenode -format

单节点启动

单结点启动是指单独启动每个结点,分别启动 namenode(以及secondarynamenode),datanode,resourcemanager,nodemanager,具体指令如下:

1
2
3
4
hadoop-daemon.sh start namenode
hadoop-daemon.sh start datanode
yarn-daemon.sh start resourcemanager
yarn-daemon.sh strat nodemanager

但对于真是的集群来说,单结点启动太过麻烦,需要登录到每一台机器单独进行操作。

集群启动

通过配置 ssh 免密登录,我们可以方便的在某一台机器上启动整个集群。启动集群之前,需要修改 etc/hadoop/slaves 文件,在其中添加datanode所在的结点名称:

1
2
3
master
slave1
slave2

需要注意的是,修改时 不能有空格、空行。

配置完毕后,就可以启动 hdfs 了,可以在 master 结点上执行: sbin/start-dfs.sh,log 显示如下:

1
2
3
4
5
6
slave1: starting namenode, logging to /opt/module/hadoop-2.8.3/logs/hadoop-lab1-namenode-slave1.out
slave1: starting datanode, logging to /opt/module/hadoop-2.8.3/logs/hadoop-lab1-datanode-slave1.out
slave2: starting datanode, logging to /opt/module/hadoop-2.8.3/logs/hadoop-lab1-datanode-slave2.out
master: starting datanode, logging to /opt/module/hadoop-2.8.3/logs/hadoop-lab1-datanode-master.out
Starting secondary namenodes [slave2]
slave2: starting secondarynamenode, logging to /opt/module/hadoop-2.8.3/logs/hadoop-lab1-secondarynamenode-slave2.out

此外,还可以通过 jps 查询各结点启动是否正常。

最后,我们通过指令 sbin/start-yarn.sh 来启动 yarn,log 如下:

1
2
3
4
5
starting yarn daemons
starting resourcemanager, logging to /opt/module/hadoop-2.8.3/logs/yarn-lab1-resourcemanager-master.out
slave2: starting nodemanager, logging to /opt/module/hadoop-2.8.3/logs/yarn-lab1-nodemanager-slave2.out
slave1: starting nodemanager, logging to /opt/module/hadoop-2.8.3/logs/yarn-lab1-nodemanager-slave1.out
master: starting nodemanager, logging to /opt/module/hadoop-2.8.3/logs/yarn-lab1-nodemanager-master.out

需要注意的是,启动 yarn 的时候,必须在 resourcemanager 所在的结点上启动,否则会报错。

d. 运行程序

集群配置启动完毕后,我们可以运行一些示例程序、上传一些文件验证配置的正确性。

上传文件

上传文件使用命令 bin/hdfs dfs -put '源文件地址' 'hdfs系统中的地址',例子如下:

1
2
3
4
5
# 进行了两个文件的拷贝,一个大文件,一个小文件。都放在了 hdfs 根目录下
# 在 http://slave1:50070/explorer.html#/ 中我们可以看到,当文件大小超过 block size 128 M 时,文件会被分为两个块放置
# 此外,由于设置了 replication 为3, 文件被 复制,分发存储到了3台服务器上, master, slave1, slave2
[lab1@master hadoop-2.8.3]$ hdfs dfs -put wcinput/wc.input /
[lab1@master hadoop-2.8.3]$ hdfs dfs -put /opt/software/hadoop-2.8.3.tar.gz /

单词计数

此外,我们还可以运行 一些 hadoop 自带的例子程序,这里以运行单词计数程序为例子:

1
2
3
4
5
6
7
8
9
# step1: 穿件文件夹
mkdir wcinput
cd wcinput
touch wc.input
# 编辑 wc.input 中的内容
vi wc.input # 写一些单词

# 运行程序 /user/lab1/input 为输入数据;/user/lab1/output 为数据输出
hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.8.3.jar wordcount /user/lab1/input /user/lab1/output