在开始前,给出Hadoop的官方文档,一切搭建过程以文档为主: href="https://hadoop.apache.org/docs/r2.6.5/
一、基础设施
基础设置这一步主要是设计到操作系统、环境、网络、必须的软件的前期准备,只有准备好了才可以着手搭建。
- 设置IP和主机名
- 关闭防火墙和selinux
- 设置host映射
- 时间同步
- 安装jdk
- 设置ssh免密钥
搭建上面提到的基础设置
-
设置IP及主机名
可以通过ifconfig查看当前主机的ip。 通过修改/etc/sysconfig/network-scripts/ifcfg-ens33修改网络配置。 -
修改hosts映射
键入以下命令
vim /etc/hosts
修改hosts文件,设置主机ip对应的引用名,这样可以实现解耦的目的。
- 关闭防火墙和selinux
关闭selinux,修改文件/etc/selinux/config
如下:
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - No SELinux policy is loaded.
SELINUX=disabled
# SELINUXTYPE= can take one of three values:
# targeted - Targeted processes are protected,
# minimum - Modification of targeted policy. Only selected processes are protected.
# mls - Multi Level Security protection.
SELINUXTYPE=targeted
- 设置时间同步
安装ntp
yum install ntp -y
修改/etc/ntp.conf文件,同步阿里云服务器的时间。
server ntp1.aliyun.com
设置开启运行ntpd,未来只要你机器一起来时间就是同步的
service ntpd start
chkconfig ntpd on
- 安装jdk1.8
需要下载jdk1.8的rpm格式的包,上传到linux,然后执行下面的命令安装即可:
rpm -i xxx.rpm
搞定后进入/usr/java目录中是否存在default软连接指向jdk的目录。如果没有,则需要在/usr/java目录下创建一个default软连接目录指向jdk目录。因为有些软件只认识/usr/java/default
ln -s /usr/java/jdk1.8.0_131 ./default
- 除此之外,我们还需要修改下
/etc/profile
文件,设置javaHome
JAVA_HOME=/usr/java/default
PATH=$JAVA_HOME/bin:$PATH
CLASSPATH=$JAVA_HOME/jre/lib/ext:$JAVA_HOME/lib/tools.jar export PATH JAVA_HOME CLASSPATH
修改完毕后,键入source /etc/profile
加载修改内容即可。
- 设置ssh免密钥
键入下面命令,查看是否本机使用ssh要密码
$ ssh localhost
如果需要密码,就要执行下面的命令免密
$ ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa
上面的命令就是使用ssh-keygen利用dsa算法生成一个ssh密钥,放在~/.ssh/目录下的id_dsa文件中存储。
-t 则表示使用的算法,支持rsa和dsa
-P 表示密码,这里用的没有密码
-f 指定dsa文件存放路径
$ cat ~/.ssh/id_dsa.pub >> ~/.ssh/authorized_keys
上面的命令就是,把公钥追加到~/.ssh/authorized_keys
中去。只要别的机器有了另一个机器的公钥,也就是在~/.ssh/authorized_keys
里存的是目标机器发给你的公钥id_dsa.pub
,你就可以通过ssh命令免密登录这台机器。
搭建所需环境
- Jdk1.8必须要安装好。本机的javaHome必须要配置。
- ssh命令必须要安装好,这里会使用ssh命令去登录hadoop所在的机器上,并执行hadoop提供的一些脚本来来远程管理hadoop的一些进程。注意需要让自己的机器在被ssh连接的时候免密操作。
ssh有个不好的地方,比如你给所有的机器上都装好了jdk环境(放在/etc/profile文件中)
你在本机上是可以加载/etc/profile文件并使用java命令来启动hadoop。
但是使用ssh命令访问控制其他机器,就无法使用java命令,因为找不到javaHome,具体的原因是ssh命令并不会去加载/etc/profile中的内容,必须要手动添加执行source命令将/etc/profile文件的内容加载到虚拟机中,才可以使用JAVAHOME等系统变量。
二、hadoop集群部署的三种模式
- Local(Standalone)Mode
这种模式表示hadoop使用单个Java 进程运行。这种模式是hadoop默认的运行模式,不属于分布式模式,只有单节点。这种模式使用于debug - Pseudo-Distributed Mode
这种模式是伪分布式模式,用的是单节点,在一台机器中,所有的角色都是一个独立的java进程,而不是扎堆在同Java进程中。
分布式就是角色分布在不同的物理机里 - Fully-DistributedMode
完全分布式。 表示不同的角色(NameNode/DataNode)存放在不同的物理机上,实现一个真正的分布式环境
三、Hadoop部署配置
Hadoop采用2.6.5版本搭建。
下载地址:点击此下载hadoop-2.6.5
1、搭建hadoop伪集群
下载完hadoop-2.6.5.tar.gz包之后,上传到linux中,然后接下
tar -zxvf hadoop-2.6.5.tar.gz
在/opt目录下创建一个bigdata目录,并把解压后的hadoop-2.6.5文件夹移动到/opt/bigdata目录下
mkdir /opt/bigdata
mv hadoop-2.6.5 /opt/bigdata
然后进入到hadoop-2.6.5目录下,可以看到其中包含的模块如下:
[root@node1 hadoop-2.6.5]# ll
total 108
drwxrwxr-x 2 haizhang haizhang 194 Oct 3 2016 bin
drwxrwxr-x 3 haizhang haizhang 20 Oct 3 2016 etc
drwxrwxr-x 2 haizhang haizhang 106 Oct 3 2016 include
drwxrwxr-x 3 haizhang haizhang 20 Oct 3 2016 lib
drwxrwxr-x 2 haizhang haizhang 239 Oct 3 2016 libexec
-rw-rw-r-- 1 haizhang haizhang 84853 Oct 3 2016 LICENSE.txt
-rw-rw-r-- 1 haizhang haizhang 14978 Oct 3 2016 NOTICE.txt
-rw-rw-r-- 1 haizhang haizhang 1366 Oct 3 2016 README.txt
drwxrwxr-x 2 haizhang haizhang 4096 Oct 3 2016 sbin
drwxrwxr-x 4 haizhang haizhang 31 Oct 3 2016 share
其中sbin则装载着hadoop提供的一些启动脚本,bin则是hadoop自己的一些命令。etc命令则装载着hadoop配置文件。
其次我们需要配置下Hadoop_Home在/etc/profile
文件中。
export HADOOP_HOME=/opt/bigdata/hadoop-2.6.5
PATH=$JAVA_HOME/bin:$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin
只要修改了/etc/profile文件,就要source下
source /etc/profile
2、配置hadoop角色
在配置角色前,我们需要把hadoop的hadoop-env.sh文件修改下
cd $HADOOP_HOME/etc/hadoop
vim hadoop-env.sh
修改内容如下
export JAVA_HOME=/usr/java/default
将${JAVA_HOME}
改成上面的javahome绝对路径,因为别的机器使用ssh命令登录你的hadoop时,不会加载/etc/profile
,也就是说用ssh控制的时候,加载不了控制机器上/etc/profile
配置的javahome变量,故此${JAVA_HOME}
需要变成本机javaHome的绝对路径。
按照官网的步骤搭建:
查看官网,我们在搭建伪分布式集群时,还需要修改hadoop/core-site.xml
和 hadoop/hdfs-site.xml
的两个内容
- hadoop/core-site.xml
加上下面的内容:
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://node1:9000</value>
</property>
</configuration>
上面信息表示,定义hdfs中的nameNode在哪台机器的哪个端口上启动。
- hadoop/hdfs-site.xml
<configuration>
<property>
<name>dfs.replication</name>
<value>1</value>
</property>
</configuration>
定义hdfs中存放文件块的副本数,这里设置成1,因为只有1台DataNode节点。
- 修改hadoop的slaves文件
其次我们需要修改hadoop中的slaves文件
cd /opt/bigdata/hadoop-2.6.5/etc/hadoop
vim slaves
把localhost修改下,变成主机名
node1
然后保存,这个文件的含义就是表示DataNode角色在哪里启动。
修改hadoop的一些默认配置
我们可以访问下面的地址,可以看到hadoop的一些默认设置:
https://hadoop.apache.org/docs/r2.6.5/hadoop-project-dist/hadoop-common/core-default.xml
其中hadoop.tmp.dir
这个选项,对应的默认存放地址时/tmp
目录下,非常不安全。而dfs.nameNode.name.dir
对应的值也是存放在/tmp
目录中的。也就是nameNode存放元数据也是放在这个目录的,非常不安全!
dfs.nameNode.name.dir的配置参考https://hadoop.apache.org/docs/r2.6.5/hadoop-project-dist/hadoop-hdfs/hdfs-default.xml 这个连接提供的就是hdfs的一些默认配置,按需修改
我们需要在hadoop/hdfs-site.xml
文件中自定义存放路径。
<property>
<name>dfs.namenode.name.dir</name>
<value>/var/bigdata/hadoop/local/dfs/name </value>
</property>
修改datanode存放data的默认路径
默认存放如下,还是存放在/tmp目录下,不安全
我们需要在hadoop/hdfs-site.xml 文件中自定义存放路径。
<property>
<name>dfs.datanode.data.dir</name>
<value>/var/bigdata/hadoop/local/dfs/data</value>
</property>
四、初始化运行
- 格式化filesystem ,这条命令只有第一次搭建hadoop集群的时候执行,其他时候不要再执行。
$ hdfs namenode -format
格式化的语义就是把hdfs中的所有内容清空,还原成最初的状态。
执行格式化操作之后,就可以看到/var目录下就生成了bigdata目录,存放的是namenode信息,注意datanode并没创建。
我们需要给我们的hadoop页面中的一些配置文件做一些修改。
cd到我们上面定义的存放namenode的目录,如下:
cd /var/bigdata/hadoop/local/dfs
然后执行hadoop提供的hdfs启动脚本
[root@node1 dfs]# start-dfs.sh
Starting namenodes on [node1]
The authenticity of host 'node1 (192.168.199.11)' can't be established.
ECDSA key fingerprint is SHA256:foaKi1WLgZrtop8WMtZWKt5BXjE8DkWVBC9NPbRZzB8.
ECDSA key fingerprint is MD5:d4:b4:48:78:2f:b2:85:2b:a3:28:0a:f4:d2:b7:dd:9b.
Are you sure you want to continue connecting (yes/no)? yes
node1: Warning: Permanently added 'node1,192.168.199.11' (ECDSA) to the list of known hosts.
node1: starting namenode, logging to /opt/bigdata/hadoop-2.6.5/logs/hadoop-root-namenode-node1.out
node1: starting datanode, logging to /opt/bigdata/hadoop-2.6.5/logs/hadoop-root-datanode-node1.out
Starting secondary namenodes [0.0.0.0]
The authenticity of host '0.0.0.0 (0.0.0.0)' can't be established.
ECDSA key fingerprint is SHA256:foaKi1WLgZrtop8WMtZWKt5BXjE8DkWVBC9NPbRZzB8.
ECDSA key fingerprint is MD5:d4:b4:48:78:2f:b2:85:2b:a3:28:0a:f4:d2:b7:dd:9b.
Are you sure you want to continue connecting (yes/no)? yes
0.0.0.0: Warning: Permanently added '0.0.0.0' (ECDSA) to the list of known hosts.
0.0.0.0: starting secondarynamenode, logging to /opt/bigdata/hadoop-2.6.5/logs/hadoop-root-secondarynamenode-node1.out
可以看到,在上面的配置中我们并没有配置secondary namenodes
的启动位置,但是secondary namenodes
还是在本机默认启动了
官网给出的secondary namenode
默认配置如下:
其中secondary namenode
还需要存放namenode中的FSimage和Editlog才能做合并,所以它也有存放这两样东西的文件路径,下面是默认配置:
我们可以控制Secondary NameNode的启动默认配置,需要在hdfs-site.xml 中添加下面的配置:
<property>
<name>dfs.namenode.secondary.http-address</name>
<value>node1:50090</value>
</property>
<property>
<name>dfs.namenode.checkpoint.dir</name>
<value>/var/bigdata/hadoop/local/dfs/secondary</value>
</property>
操作完成后,我们可以使用stop-dfs.sh脚本停止hdfs
[root@node1 local]# stop-dfs.sh
Stopping namenodes on [node1]
node1: stopping namenode
node1: stopping datanode
Stopping secondary namenodes [node1]
node1: stopping secondarynamenode
然后再次启动,这时候加载的就不是官网默认配置了,而是从hdfs-site.xml中加载snn的配置。
start-dfs.sh 第一次启动的时候,datanode和snn角色会初始化创建自己的数据目录。
第一次启动成功后,就可以看到对应的目录下存在这三个文件夹
[root@node1 dfs]# pwd
/var/bigdata/hadoop/local/dfs
[root@node1 dfs]# ls
data name secondary
我们可以cd到这三个目录里面的current文件夹中,可以发现有个VERSION文件,其中存在一个clusterID属性
clusterID=CID-5d119075-b369-4d20-b9cd-bc4dac5b90ea
对比发现data name secondary这三个角色的clusterID都是一样的,实际上dataNode和snn的clusterID要和namenode一致,以保持通讯。
启动成功后,我们可以访问node1:50070
来访问hdfs提供的图形界面了,注意访问该路径的机器要修改hosts文件,node1需要和访问机器的ip绑定。
windows机器上hosts文件路径:C:\Windows\System32\drivers\etc\HOSTS
五、命令的执行
1、查看hdfs dfs命令的用法
我们可以使用hdfs的一些命令操作hdfs。键入下面命令可以查看hdfs的具体用法:
hdfs dfs
2、使用hdfs dfs命令创建对应的目录
比如我们想要在hdfs根目录下创建一个bigdata目录,就可以键入下面命令
[root@node1 current]# hdfs dfs -mkdir /bigdata
此时登录浏览器访问node1:50070
就可以看到文件目录结构了。
注意,这个目录不是创建在本地目录,而是hdfs中的目录。
一般而言,对于hdfs来说,用户目录是使用/user/root
目录,我们键入下面命令创建:
[root@node1 current]# hdfs dfs -mkdir -p /user/root
3、在hdfs中上传一个文件
使用下面命令上传一个文件到hdfs中的/user/root目录
[root@node1 ~]# hdfs dfs -put hadoop-2.6.5.tar.gz /user/root
当上传的时候,可以发现下面的现象:
上传过程中,我们的文件名多加了一个COPYING后缀
而上传完毕后,又将文件名更改了回来。
我们可以看到这个文件默认的block大小是128MB,总大小是190.39MB ,Replication表示文件块的副本数,由于我们只有一个Datanode节点,并且hdfs.site.xml
文件中定义的副本数为1,故这里副本数是1。
上面这两张图分别显示了该文件的两个文件块,Block0大小为128MB,而Block1大小是60多MB,并且都放在node1中的dataNode中存储。
我们也可以在虚拟机中cd到下面的路径
[root@node1 subdir0]# pwd
/var/bigdata/hadoop/local/dfs/data/current/BP-1712431170-192.168.199.11-1589006889116/current/finalized/subdir0/subdir0
[root@node1 subdir0]# ll
total 196488
-rw-r--r-- 1 root root 134217728 May 9 22:07 blk_1073741825
-rw-r--r-- 1 root root 1048583 May 9 22:07 blk_1073741825_1001.meta
-rw-r--r-- 1 root root 65417541 May 9 22:07 blk_1073741826
-rw-r--r-- 1 root root 511083 May 9 22:07 blk_1073741826_1002.meta
其中BP打头这串文件名不一致,其他的基本都是一致的。上面的目录就是datanode存放这个文件的位置,我们可以看到又4个文件。
- **.meta 结尾的表示块的校验和,比如blk_1073741825_1001.meta则表示文件块blk_1073741825的校验和。注意这里的1073741825和我们在hdfs提供的ui界面上查到的BlockId一致。
自定义块大小
官方默认的块大小是128MB
假设我们想要上传一个文件,希望按照我们自定义的块大小划分,就可以修改dfs.blocksize
的值。
我们先创建一个小文件
for i in `seq 100000`;do echo "hello hadoop$i" >> data.txt;done
随后键入下面命令,上传新生成的data.txt到hdfs中。并且以文件块大小为1MB划分。
[root@node1 ~]# hdfs dfs -D dfs.blocksize=1048576 -put data.txt
注意,后面我没有写明上传到hdfs的哪个命令,表示默认上传/user/root (hdfs用户家目录)
可以看到上传完毕后data.txt
块大小是1MB并切割成了2个block块。
并且我们看下datanode中存放的记录信息
发现多出了4个文件,表示存放data.txt的两个block和对应的校验和。
验证一个现象
data.txt实际上存放的是hello hadoop1 到 hello hadoop100000 ,因为文件按块指定大小划分,我们不妨打开上面的 blk_1073741827 文件(data.txt中的第一个块),并且跳转到最后一行:
可以发现最后一行数据只有一部分,并不是完整的一行数据。
我们继续打开 blk_1073741828文件
发现第一行就是 blk_1073741827最后一行缺失的数据。
那么此时就应证了之前我们说的,文件按块划分,按照字节严格切割的说法。
在实际计算的过程中,其实会把缺少的数据重新修正过来。
后面分析hdfs源码的时候会讲到