CentOS 7.0 hadoop 安装与配置
蒋小超 2015.04.03
背景介绍
hadoop 是一种大数据分布式运算解决方案。
hadoop 是什么?
实际上 hadoop 就是 Google 的 MapReduce 核心算法的一个开源实现,主要用于海量数据的处理。
一般来说数据量超过 1T 就可以算海量数据了,当然如果只是一个简单的文件超过 1T 还是很容易的,但是这里说的是数据,就是一个一个小的数据记录的集合,比如淘宝这样的很多商品,比如 Google 这样的搜索引擎。
那么就有个疑问了,如果只是数据记录, hadoop 相比数据库有什么优势?数据库也是大量数据的集合啊?这就牵扯到了分布式计算, hadoop 在设计时就考虑过用大量性能不是那么强的节点合并在一起工作,而数据库往往有一个主数据库,能力往往取决于主要设备的性能。实际上 hadoop 还有一个 hive 分支用来做和数据库差不多的事情。
hadoop 能做什么?
就像上面说的, hadoop 主要目的就是海量数据处理,根据它的设计可以做:
大量数据的保存。这个其实不是主要功能,不过 hadoop 可以在保存文件的时候保存几个备份,而且还会把他们放到不同的节点里面,所以当做 RAID 也是可以的。
数据仓库/数据挖掘。比如大量日志的分析等等
搜索引擎。这是设计初衷了,就是想快速索引和查询
云计算。收集用户方方面面的信息然后从中间获取信息(看起来像数据挖掘?)
研究。分布式计算什么的挺前沿的,可以研究一下咯。而且云计算的本质也就是海量数据的存储和并行处理
这里是hadoop 主页
大数据集群中不同主机扮演不同角色,主要分为下面几种:
-
Master
NameNode
NameNode 用于管理文件系统 HDFS ,维护文件系统树结构和文件元数据。当有新文件要写入系统时客户端会先向 NameNode 查询当前文件系统的状态,然后得知自己可以往哪里写入,最后实际写入文件系统,这中间 NameNode 就是管理主要信息的核心设备。ResourceManager
ResourceManager 用于管理和分配工作,它是所有工作的总调度程序。
-
Slave
DataNode
DataNode 提供文件存储,它将自己的存储空间分块,然后向 NameNode 报告自己的存储状态并负责真正保存文件NodeManager
NodeManager 用于接受 ResourceManager 分配的工作并实际工作,是所有工作的实际执行者。
这篇文档实际上是参考 这里 加上自己的实际试验写出来了,原文没有使用 CentOS 7,而且版本稍微有点老,我仅仅是更新了一下。
安装和配置步骤
安装环境
我这里的安装环境基于虚拟机,有3个 CentOS 7.0 虚拟机,IP地址分别为:
- 192.168.110.10 Master.hadoop
- 192.168.110.11 Slave_1.hadoop
- 192.168.110.12 Slave_2.hadoop
因为 hadoop 要求所有参与设备的环境都相同,包括有相同用户,相同安装目录等,所以可以先把准备工作做好。
准备工作
-
创建用户 'hadoop',用户密码和用户名相同。这个用户用于实际工作,root 用户仅用于配置环境
useradd hadoop passwd hadoop
-
主机命名和注册
首先修改每台主机的 /etc/hostname 文件,确定主机名然后修改每台主机的 /etc/hosts 文件,将主机名和 IP 地址对应关系都写进去
-
开启不需要密码的 ssh 登录
hadoop 对其他 DataNode 的操作都用的是 ssh 连接,频繁操作肯定不能不停的输入密码。理论上每个设备都应该创建密钥并在其他设备上注册,但其实在 NameNode 上做下面的操作也可以,因为一般情况下都是 NameNode 操作 DataNode.# 创建用户密钥,root 用户和 hadoop 用户都要创建 ssh-keygen -t rsa # 将密钥在 DataNode 上注册,注意要切换用户 ssh-copy-id root@Master.hadoop ssh-copy-id hadoop@Master.hadoop
上面的动作都完成后应该可以用下面的命令测试:
```bash
# 必须获得响应
ping Slave_1.hadoop
# 不需要输入密码即可登录其他设备
ssh Slave_1.hadoop
```
- 在每个 slave 上面用 ssh-copy-id 将自己的私钥在 Master 上注册,slave 之间就不需要注册了
下载和安装
对于 hadoop 来说有 2 个必要组件,分别是:
hadoop
下载站点-
Java 运行环境
CentOS 自带 Java 环境,只要用 yum 安装就可以了yum install openjdk
环境变量最好加入 /etc/profile 文件里,在文件里加入下面的内容:
export JAVA_HOME=/usr/lib/jvm/java-openjdk export JRE_HOME=/usr/lib/jvm/java-openjdk/jre export CLASSPATH=.:${CLASSPATH}:${JAVA_HOME}/lib:${JRE_HOME}/lib export PATH=${PATH}:${JAVA_HOME}/bin:${JRE_HOME}/bin
然后让配置生效:
source /etc/profile
将配置文件复制到其他客户端:
scp /etc/profile root@slave_1:/etc
如果没有意外的话 java 应该就可用了,可以用下面的命令检查:
[root@Master etc]# java -version java version "1.7.0_51" OpenJDK Runtime Environment (rhel-2.4.5.5.el7-x86_64 u51-b31) OpenJDK 64-Bit Server VM (build 24.51-b03, mixed mode)
配置 hadoop
我这里下载的是 hadoop-2.6.0.tar.gz 文件,将它复制到 /usr 目录下,然后用下面的命令解压并把它交给 hadoop 用户:
```bash
cd /usr
tar zxvf hadoop-2.6.0.tar.gz
mv hadoop-2.6.0 hadoop
chown -R hadoop:hadoop hadoop
```
从现在开始就要切换到 hadoop 用户了,之后的命令中如果有需要 root 权限的都会专门说明。
-
先在 hadoop 安装目录中创建一个 tmp 目录,未来的查询都可以在这个目录下进行
cd /usr/hadoop mkdir tmp
-
将 hadoop 需要的环境变量加入 /etc/profile 文件中去,这个步骤需要 root 权限
在文件最后加上下面的内容,然后拷贝到其他主机中去:
# Set hadoop environment export HADOOP_HOME=/usr/hadoop export PATH=$PATH:$HADOOP_HOME/bin
现在开始真正配置 hadoop 了,下面的文件都在 hadoop 安装目录的 etc/hadoop 目录下,注意先备份。
最开始的时候 hadoop 配置文件很少,不过随着项目越来越大配置文件也开始增加了,到现在为止 hadoop 的代码大致分为了 core , hdfs 和 map/reduce 三部分,配置文件也被分成了三个。不过 mapred-site.xml 其实可以不配置 :
- core- site.xml
- hdfs-site.xml
- mapred-site.xml
其中 core-site.xml 和 hdfs-site.xml 是站在 HDFS 角度上配置文件; core-site.xml 和 mapred-site.xml 是站在 MapReduce 角度上配置文件。
-
配置 hadoop-env.sh
这里真正要配置的其实就是 JAVA_HOME 这个参数,不过其实不配置也可以在上面步骤中的环境变量中得到
export JAVA_HOME=/usr/lib/jvm/java-openjdk
-
配置 core-site.xml
按照下面的内容配置 Master (NameNode/ResourceManager) 的地址和端口号,进行下面的配置前一定要创建 /usr/hadoop/tmp 目录。
fs.defaultFS 用来指定 ResourceManager 设备
<configuration> <property> <name>hadoop.tmp.dir</name> <value>/usr/hadoop/tmp</value> <description>A base for other temporary directories.</description> </property> <property> <name>fs.defaultFS</name> <value>hdfs://Master.hadoop</value> </property> <!-- file system properties --> <property> <name>fs.default.name</name> <value>hdfs://Master.hadoop:9000</value> </property> </configuration>
上面的 hadoop.tmp.dir 如果不配置的话默认就会用临时目录 /tmp/hadoo-hadoop 。这个目录每次重启后都会被删掉,必须重新执行format才行,否则会出错。
-
配置 hdfs-site.xml
下面配置中的 dfs.replication 参数用来指定每个文件保存多少份,对于普通使用来说 1 份就可以,但这种没有备份的情况可能一个 DataNode 损坏就丢失文件了,如果文件比较重要最好还是多备份一份,这里设置为 2 是因为我们有 2 台 DataNode 正好每个上面备份一个,如果配置的 DataNode 数量不够会报警。如果不配置这个参数那么默认是 3
<configuration> <property> <name>dfs.replication</name> <value>2</value> </property> </configuration>
-
配置 mapred-site.xml
hadoop 2.6 不需要配置这个文件
-
主机配置
-
修改 /usr/hadoop/etc/hadoop/masters 文件,默认如果没有那么就得新建一个,在里面加上一行:
192.168.110.11
或者名称也可以Master.hadoop
-
修改 /usr/hadoop/etc/hadoop/slaves 文件,在里面把其他 DataNode 加进来
Slave_1.hadoop Slave_2.hadoop
-
好了,到这里 Master 上的配置就完成了,之后需要将配置好的目录用 scp 拷贝到其他 slave 机器上。理论上来说 slave 上面应该单独配置,不过直接复制其实也是可以的。复制完成了一定记得到 slave 主机上把 hadoop 目录的权限交给 hadoop:
```bash
scp -r /usr/hadoop root@192.168.110.12:/usr
chown -R hadoop:hadoop /usr/hadoop
```
记得把 /etc/profile 文件也复制到客户机上去,主要是那几个系统变量:
`scp /etc/profile root@192.168.110.12:/etc`
启动和功能验证
下面的操作都是用 hadoop 用户在 Master 上进行的。
格式化 HDFS 系统
在 NameNode 上要格式化 HDFS 系统,这个动作只需要做一次就可以了:
`hadoop namenode -format`
我这里执行后的输出如下,看到 Exiting with status 0 吗?
```bash
[hadoop@Master hadoop]$ hadoop namenode -format
DEPRECATED: Use of this script to execute hdfs command is deprecated.
Instead use the hdfs command for it.
15/04/07 18:15:30 INFO namenode.NameNode: STARTUP_MSG:
/************************************************************
STARTUP_MSG: Starting NameNode
STARTUP_MSG: host = Master.hadoop/192.168.110.11
STARTUP_MSG: args = [-format]
STARTUP_MSG: version = 2.6.0
STARTUP_MSG: classpath = ...
STARTUP_MSG: build = https://git-wip-us.apache.org/repos/asf/hadoop.git -r e3496499ecb8d220fba99dc5ed4c99c8f9e33bb1; compiled by 'jenkins' on 2014-11-13T21:10Z
STARTUP_MSG: java = 1.7.0_51
************************************************************/
15/04/07 18:15:30 INFO namenode.NameNode: registered UNIX signal handlers for [TERM, HUP, INT]
15/04/07 18:15:30 INFO namenode.NameNode: createNameNode [-format]
Formatting using clusterid: CID-8762898e-f67e-4cc9-b9ff-199c054c3051
15/04/07 18:15:31 INFO namenode.FSNamesystem: No KeyProvider found.
15/04/07 18:15:31 INFO namenode.FSNamesystem: fsLock is fair:true
15/04/07 18:15:31 INFO blockmanagement.DatanodeManager: dfs.block.invalidate.limit=1000
15/04/07 18:15:31 INFO blockmanagement.DatanodeManager: dfs.namenode.datanode.registration.ip-hostname-check=true
15/04/07 18:15:31 INFO blockmanagement.BlockManager: dfs.namenode.startup.delay.block.deletion.sec is set to 000:00:00:00.000
15/04/07 18:15:31 INFO blockmanagement.BlockManager: The block deletion will start around 2015 Apr 07 18:15:31
15/04/07 18:15:31 INFO util.GSet: Computing capacity for map BlocksMap
15/04/07 18:15:31 INFO util.GSet: VM type = 64-bit
15/04/07 18:15:32 INFO util.GSet: 2.0% max memory 889 MB = 17.8 MB
15/04/07 18:15:32 INFO util.GSet: capacity = 2^21 = 2097152 entries
15/04/07 18:15:32 INFO blockmanagement.BlockManager: dfs.block.access.token.enable=false
15/04/07 18:15:32 INFO blockmanagement.BlockManager: defaultReplication = 2
15/04/07 18:15:32 INFO blockmanagement.BlockManager: maxReplication = 512
15/04/07 18:15:32 INFO blockmanagement.BlockManager: minReplication = 1
15/04/07 18:15:32 INFO blockmanagement.BlockManager: maxReplicationStreams = 2
15/04/07 18:15:32 INFO blockmanagement.BlockManager: shouldCheckForEnoughRacks = false
15/04/07 18:15:32 INFO blockmanagement.BlockManager: replicationRecheckInterval = 3000
15/04/07 18:15:32 INFO blockmanagement.BlockManager: encryptDataTransfer = false
15/04/07 18:15:32 INFO blockmanagement.BlockManager: maxNumBlocksToLog = 1000
15/04/07 18:15:32 INFO namenode.FSNamesystem: fsOwner = hadoop (auth:SIMPLE)
15/04/07 18:15:32 INFO namenode.FSNamesystem: supergroup = supergroup
15/04/07 18:15:32 INFO namenode.FSNamesystem: isPermissionEnabled = true
15/04/07 18:15:32 INFO namenode.FSNamesystem: HA Enabled: false
15/04/07 18:15:32 INFO namenode.FSNamesystem: Append Enabled: true
15/04/07 18:15:32 INFO util.GSet: Computing capacity for map INodeMap
15/04/07 18:15:32 INFO util.GSet: VM type = 64-bit
15/04/07 18:15:32 INFO util.GSet: 1.0% max memory 889 MB = 8.9 MB
15/04/07 18:15:32 INFO util.GSet: capacity = 2^20 = 1048576 entries
15/04/07 18:15:32 INFO namenode.NameNode: Caching file names occuring more than 10 times
15/04/07 18:15:32 INFO util.GSet: Computing capacity for map cachedBlocks
15/04/07 18:15:32 INFO util.GSet: VM type = 64-bit
15/04/07 18:15:32 INFO util.GSet: 0.25% max memory 889 MB = 2.2 MB
15/04/07 18:15:32 INFO util.GSet: capacity = 2^18 = 262144 entries
15/04/07 18:15:32 INFO namenode.FSNamesystem: dfs.namenode.safemode.threshold-pct = 0.9990000128746033
15/04/07 18:15:32 INFO namenode.FSNamesystem: dfs.namenode.safemode.min.datanodes = 0
15/04/07 18:15:32 INFO namenode.FSNamesystem: dfs.namenode.safemode.extension = 30000
15/04/07 18:15:32 INFO namenode.FSNamesystem: Retry cache on namenode is enabled
15/04/07 18:15:32 INFO namenode.FSNamesystem: Retry cache will use 0.03 of total heap and retry cache entry expiry time is 600000 millis
15/04/07 18:15:32 INFO util.GSet: Computing capacity for map NameNodeRetryCache
15/04/07 18:15:32 INFO util.GSet: VM type = 64-bit
15/04/07 18:15:32 INFO util.GSet: 0.029999999329447746% max memory 889 MB = 273.1 KB
15/04/07 18:15:32 INFO util.GSet: capacity = 2^15 = 32768 entries
15/04/07 18:15:32 INFO namenode.NNConf: ACLs enabled? false
15/04/07 18:15:32 INFO namenode.NNConf: XAttrs enabled? true
15/04/07 18:15:32 INFO namenode.NNConf: Maximum size of an xattr: 16384
15/04/07 18:15:32 INFO namenode.FSImage: Allocated new BlockPoolId: BP-1017743206-192.168.110.11-1428401732358
15/04/07 18:15:32 INFO common.Storage: Storage directory /usr/hadoop/tmp/dfs/name has been successfully formatted.
15/04/07 18:15:32 INFO namenode.NNStorageRetentionManager: Going to retain 1 images with txid >= 0
15/04/07 18:15:32 INFO util.ExitUtil: Exiting with status 0
15/04/07 18:15:32 INFO namenode.NameNode: SHUTDOWN_MSG:
/************************************************************
SHUTDOWN_MSG: Shutting down NameNode at Master.hadoop/192.168.110.11
************************************************************/
```
启动 hadoop
以前的时候都是用 sbin/start-all.sh 脚本启动,不过现在已经不建议这么做了,建议的方式是分别执行下面 2 个脚本:
```bash
./sbin/start-dfs.sh
./sbin/start-yarn.sh
```
执行上面命令之前最好关闭集群中其他设备的防火墙,有可能会被奇怪的挡住……另外只需要在 Master 上执行即可,不需要找 Slave
我这里的输出是这样的:
```bash
[hadoop@Master hadoop]$ ./sbin/start-dfs.sh
Starting namenodes on [localhost]
localhost: starting namenode, logging to /usr/hadoop/logs/hadoop-hadoop-namenode-Master.hadoop.out
Slave_1.hadoop: starting datanode, logging to /usr/hadoop/logs/hadoop-hadoop-datanode-Slave_1.hadoop.out
Slave_2.hadoop: starting datanode, logging to /usr/hadoop/logs/hadoop-hadoop-datanode-Slave_2.hadoop.out
Starting secondary namenodes [0.0.0.0]
0.0.0.0: secondarynamenode running as process 32261. Stop it first.
```
```bash
[hadoop@Master hadoop]$ ./sbin/start-yarn.sh
starting yarn daemons
starting resourcemanager, logging to /usr/hadoop/logs/yarn-hadoop-resourcemanager-Master.hadoop.out
Slave_1.hadoop: starting nodemanager, logging to /usr/hadoop/logs/yarn-hadoop-nodemanager-Slave_1.hadoop.out
Slave_2.hadoop: starting nodemanager, logging to /usr/hadoop/logs/yarn-hadoop-nodemanager-Slave_2.hadoop.out
```
如果都正确启动的话可以在 slave 主机上去看看 /usr/hadoop/tmp 目录,里面应该有这 2 个目录的,都是自动创建的:
```bash
[root@Salve_1 hadoop]# ll tmp/
total 0
drwxrwxr-x 3 hadoop hadoop 17 Apr 7 18:34 dfs
drwxr-xr-x 5 hadoop hadoop 54 Apr 7 18:37 nm-local-dir
```
验证是否启动
下面的方法都可以验证:
-
使用 java 的 jps 小工具可以看到 ResourceManager , NameNode 都启动了:
# On Master [hadoop@Master hadoop]$ jps 29011 ResourceManager 21836 NameNode 2159 Jps 32261 SecondaryNameNode # On Slave [root@Salve_1 hadoop]# jps 4799 DataNode 20182 Jps 11010 NodeManager
-
用
./bin/hdfs dfsadmin -report
查看状态# On Master [hadoop@Master hadoop]$ ./bin/hdfs dfsadmin -report Configured Capacity: 107321753600 (99.95 GB) Present Capacity: 95001157632 (88.48 GB) DFS Remaining: 95001149440 (88.48 GB) DFS Used: 8192 (8 KB) DFS Used%: 0.00% Under replicated blocks: 0 Blocks with corrupt replicas: 0 Missing blocks: 0 ------------------------------------------------- Live datanodes (2): Name: 192.168.110.12:50010 (Slave_1.hadoop) Hostname: Slave_1.hadoop Decommission Status : Normal Configured Capacity: 53660876800 (49.98 GB) DFS Used: 4096 (4 KB) Non DFS Used: 6159425536 (5.74 GB) DFS Remaining: 47501447168 (44.24 GB) DFS Used%: 0.00% DFS Remaining%: 88.52% Configured Cache Capacity: 0 (0 B) Cache Used: 0 (0 B) Cache Remaining: 0 (0 B) Cache Used%: 100.00% Cache Remaining%: 0.00% Xceivers: 1 Last contact: Thu Apr 09 10:49:27 CST 2015 Name: 192.168.110.13:50010 (Slave_2.hadoop) Hostname: Slave_2.hadoop Decommission Status : Normal Configured Capacity: 53660876800 (49.98 GB) DFS Used: 4096 (4 KB) Non DFS Used: 6161170432 (5.74 GB) DFS Remaining: 47499702272 (44.24 GB) DFS Used%: 0.00% DFS Remaining%: 88.52% Configured Cache Capacity: 0 (0 B) Cache Used: 0 (0 B) Cache Remaining: 0 (0 B) Cache Used%: 100.00% Cache Remaining%: 0.00% Xceivers: 1 Last contact: Thu Apr 09 10:49:27 CST 2015
-
如果都运行了,就可以用浏览器查看了。在系统中使用下面的命令可以看到 hadoop 使用的端口:
[hadoop@Master hadoop]$ netstat -tnulp | grep java (Not all processes could be identified, non-owned process info will not be shown, you would have to be root to see it all.) tcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTEN 21836/java tcp 0 0 0.0.0.0:50090 0.0.0.0:* LISTEN 32261/java tcp 0 0 0.0.0.0:50070 0.0.0.0:* LISTEN 21836/java tcp6 0 0 :::8030 :::* LISTEN 29011/java tcp6 0 0 :::8031 :::* LISTEN 29011/java tcp6 0 0 :::8032 :::* LISTEN 29011/java tcp6 0 0 :::8033 :::* LISTEN 29011/java tcp6 0 0 :::8088 :::* LISTEN 29011/java
hadoop 在进程中的表现就是 java 程序, IPv6 的几个端口用于内部通讯, IPv4 的 3 个端口分别是数据通讯RPC端口(9000)、DFS 状态查看(50070)和整体状态查询(50090)
附录
正常情况下各个进程情况
-
Master
Master 有 3 个主要进程就可以了,以前还有 JobTracker ,不过现在这个进程会在每次开始工作时自动启动,完成后退出[hadoop@Master hadoop]$ jps 15336 SecondaryNameNode 23851 Jps 16195 ResourceManager 14081 NameNode
-
Slave
Slave 有 2 个即可, TaskTracker 也是需要时启动[hadoop@Slave_1 logs]$ jps 9683 NodeManager 18383 Jps 8749 DataNode