说明:本文所有操作均在 64位 ubuntu 16.04 操作系统下进行
准备
通过物理机器虚拟化 4 台虚拟机:1 个 Master 节点,3 个 Slave 节点。为了实现节点间在同一局域网上定向通信,配置使用静态地址,各节点的 IP 分布如下:
节点主机名 | 静态 IP 地址 | 主要角色 |
---|---|---|
master | 192.168.1.200 | namenode 节点 |
slave01 | 192.168.1.201 | datanode 节点 |
slave02 | 192.168.1.202 | datanode 节点 |
slave03 | 192.168.1.203 | datanode 节点 |
Master 节点机器主要配置 NameNode 和 JobTracker 角色,总体负责分布式数据和分解任务的执行;Slave 节点机器配置 DataNode 和 TaskTracker 的角色,负责分布式数据存储以及任务的执行。
需要的软件:
软件名称 | 描述 |
---|---|
VirtualBox | 用于虚拟化主机 |
Ubuntu Server 16.04.2 LTS | 服务器版的 ubuntu 操作系统 |
jdk-8u121-linux-x64.tar.gz | Hadoop 需要 JDK 的支持 |
hadoop-2.7.3.tar.gz | hadoop 的安装文件 |
配置一个单节点环境
安装 VirtualBox
使用 apt
安装 virtual box
$ sudo apt install virtualbox
新建虚拟机
打开 VirtualBox,点击 New,Name 填 master (为方便区分),Type 选择 Linux,Version 选择 Ubuntu(64-bit),点击下一步。
一路 Next,最终如下图。
为虚拟机安装操作系统
选择镜像
点击 Settings,选中 Storage -> Controller:IDE -> Empty
右上方有一个光盘的小图标,点击之后选择下载好的 Ubuntu Server 镜像
点击 OK 确定。
安装
点击 Start 运行虚拟机开始安装
注意:语言请选择 "English",选择 "中文" 安装过程中会报错
选择 "Install Ubuntu Server"
一路回车,到创建新用户时停止。
这里我将用户名设置为 spark (最头疼的就是起名字了,你可以根据自己的喜好随意起名 _ )
continue,continue,到设置密码的时候停止。
注意:密码输入完成后还需重新输入一次以确认两次密码是否一致
如果密码强度太弱系统会发出如下提示:
手动选择 Yes
然后一路回车。注意,在此过程中系统会自动配置时区时间,就不要 cancel 了,让它自己配一会儿。
接下来是给磁盘分区,依旧回车,到如图所示的时候停下来,选择 Yes
继续,到这一步,选择 Yes
现在静静的等一小会儿_。
到这一步,直接 continue
然后系统会连接网络更新软件,这一步不是必须的(且比较耗时),所以选择 cancel,然后继续回车,到下图所示的步骤停止。
这里我们选择安装 standard system utilities
和 OpenSSH server
。standard system utilities
不安装的话机器基本无法正常使用,安装 OpenSSH server
是为了方便集群之间的通信。
好了,剩下的所有对话框都可以用回车解决了。
等待安装完成,系统会自动重启。
关闭虚拟机,并设置虚拟机的网络为桥接(bridged adapter)模式。
对安装的操作系统进行配置
启动虚拟机,并进行如下配置:
- 设置主机名
- 设置静态 IP
- 安装 JDK
- 安装 Hadoop
1. 设置主机名
打开文件 hostname
$ sudo vim /etc/hostname
将内容修改为 master
2. 设置静态 IP
打开文件 interfaces
$ sudo vim /etc/network/interfaces
我的 interfaces
文件中的内容如下:
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).
source /etc/network/interfaces.d/*
# The loopback network interface
auto lo
iface lo inet loopback
# The primary network interface
auto enp0s3
iface enp0s3 inet dhcp
将 dhcp
修改为 static
,并添加 ip 地址,子网掩码,网关
修改完成后的文件内容如下:
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).
source /etc/network/interfaces.d/*
# The loopback network interface
auto lo
iface lo inet loopback
# The primary network interface
auto enp0s3
iface enp0s3 inet static
address 192.168.1.200
netmask 255.255.255.0
gateway 192.168.1.1
完成后继续配置 DNS 解析
$ sudo vim /etc/resolvconf/resolv.conf.d/base
添加如下内容:
nameserver 192.168.1.1
nameserver 114.114.114.114
重启使配置生效
此时,主机名已经是 master
了,运行 ifconfig
查看一下 ip
是否正确修改
spark@master:~$ ifconfig
...
enp0s3 Link encap:Ethernet HWaddr 08:00:27:0f:f6:ec
inet addr:192.168.1.200 Bcast:192.168.1.255 Mask:255.255.255.0
inet6 addr: fe80::a00:27ff:fe0f:f6ec/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:86 errors:0 dropped:0 overruns:0 frame:0
TX packets:86 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:12088 (12.0 KB) TX bytes:12102 (12.1 KB)
...
看到 inet addr
已经修改为 192.168.1.200
在进行接下来的操作之前我们先配置一下本机(物理机)的 hosts
文件,使 ip
和主机名绑定,方便后续操作
$ sudo vim /etc/hosts
在文件末尾添加如下内容:
192.168.1.200 master
192.168.1.201 slave01
192.168.1.202 slave02
192.168.1.203 slave03
现在我们就可以通过主机名来连接主机了
打开终端,使用 ssh
连接虚拟机
$ ssh spark@master
spark 为虚拟机中创建的用户名,master 为刚才配置的主机名
中间会有个小提示,输入 yes
回车,然后输入 spark
用户的密码
3. 安装 JDK
参考 JDK 的正确安装姿势
4. 安装 Hadoop
我已经提前下载好了 hadoop-2.7.3.tar.gz,直接传到虚拟机里就可以了
这里有个小技巧,可以用 scp
命令在 linux
主机之间传文件,例如:
$ scp hadoop-2.7.3.tar.gz spark@master:/home/spark/
这条命令表示将文件 hadoop-2.7.3.tar.gz
从本机复制到 master
主机的 /home/spark/
目录下
在虚拟机中进行安装 hadoop 的操作
解压安装文件
在用户家目录下新建 apps
目录,将 hadoop-2.7.3.tar.gz
移动到 apps
目录中进行解压
$ mkdir apps && mv hadoop-2.7.3.tar.gz apps && cd apps && tar zxvf hadoop-2.7.3.tar.gz
配置
- 配置 hadoop 环境变量
export HADOOP_HOME="/home/spark/apps/hadoop-2.7.3"
export HADOOP_LOG_DIR="$HADOOP_HOME/logs"
export YARN_LOG_DIR="$HADOOP_LOG_DIR"
export PATH="$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin"
使配置立即生效
$ source ~/.bashrc
执行 hadoop
命令,出现如下信息则说明环境配置成功
$ hadoop
Usage: hadoop [--config confdir] [COMMAND | CLASSNAME]
CLASSNAME run the class named CLASSNAME
...
- 修改 hadoop 配置文件
2.1 修改~/apps/hadoop-2.7.3/etc/hadoop
目录下的hadoop-env.sh
yarn-env.sh
mapred-env.sh
文件中JAVA_HOME
的值为/opt/java/jdk1.8.0_121
2.2 修改~/apps/hadoop-2.7.3/etc/hadoop/slaves
文件内容如下:
slave01
slave02
slave03
2.3 配置 ~/apps/hadoop-2.7.3/etc/hadoop/core-site.xml
添加如下内容:
<property>
<name>fs.defaultFS</name>
<value>hdfs://master:9000</value>
<description>设定 namenode 的主机名及端口</description>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/home/spark/apps/hadoop-2.7.3/tmp/hadoop-${user.name}</value>
<description>存储临时文件的目录</description>
</property>
<!-- 用户 "spark" 可以代理所有主机上的所有用户 -->
<property>
<name>hadoop.proxyuser.spark.hosts</name>
<value>*</value>
</property>
<property>
<name>hadoop.proxyuser.spark.groups</name>
<value>*</value>
</property>
2.4 配置 ~/apps/hadoop-2.7.3/etc/hadoop/hdfs-site.xml
添加如下内容:
<property>
<name>dfs.namenode.http-address</name>
<value>master:50070</value>
<description> NameNode 地址和端口 </description>
</property>
<property>
<name>dfs.namenode.secondary.http-address</name>
<value>slave01:50090</value>
<description> SecondNameNode 地址和端口 </description>
</property>
<property>
<name>dfs.replication</name>
<value>3</value>
<description> 设定 HDFS 存储文件的副本个数,默认为 3 </description>
</property>
<property>
<name>dfs.namenode.name.dir</name>
<value>file:///home/spark/apps/hadoop-2.7.3/dfs/name</value>
<description> namenode 用来持续存储命名空间和交换日志的本地文件系统路径 </description>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>file:///home/spark/apps/hadoop-2.7.3/dfs/data</value>
<description> DateNode 在本地存储块文件的目录列表 </description>
</property>
<property>
<name>dfs.namenode.checkpoint.dir</name>
<value>file:///home/spark/apps/hadoop-2.7.3/dfs/namesecondary</value>
<description>
设置 secondarynamenode 存储临时镜像的本地文件系统路径,
如果这是一个用逗号分隔的列表,则镜像将会冗余复制到所有目录
</description>
</property>
<property>
<name>dfs.webhdfs.enabled</name>
<value>true</value>
<description> 是否允许网页浏览 HDFS 文件 </description>
</property>
<property>
<name>dfs.stream-buffer-size</name>
<value>131072</value>
<description>
默认 4KB,作为 hadoop 缓冲区,用于 hadoop 读 HDFS 的文件和写 HDFS 的文件,
还有 map 的输出都用到了这个缓冲区容量,对于现在的硬件,可以设置为 128KB(131072),
甚至是 1MB(太大了 map 和 reduce 任务可能会内存溢出)
</description>
</property>
2.5 配置 ~/apps/hadoop-2.7.3/etc/hadoop/mapred-site.xml
该文件需要通过模板复制一份
$ cp mapred-site.xml.template mapred-site.xml
添加如下内容:
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
<property>
<name>mapreduce.jobhistory.address</name>
<value>master:10020</value>
</property>
<property>
<name>mapreduce.jobhistory.webapp.address</name>
<value>master:19888</value>
</property>
2.6 配置 ~/apps/hadoop-2.7.3/etc/hadoop/yarn-site.xml
添加如下内容:
<property>
<name>yarn.resourcemanager.hostname</name>
<value>master</value>
</property>
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<property>
<name>yarn.nodemanager.aux-services.mapreduce.shuffle.class</name>
<value>org.apache.hadoop.mapred.ShuffleHandler</value>
</property>
<property>
<name>yarn.resourcemanager.address</name>
<value>master:8032</value>
</property>
<property>
<name>yarn.resourcemanager.scheduler.address</name>
<value>master:8030</value>
</property>
<property>
<name>yarn.resourcemanager.resource-tracker.address</name>
<value>master:8031</value>
</property>
<property>
<name>yarn.resourcemanager.admin.address</name>
<value>master:8033</value>
</property>
<property>
<name>yarn.resourcemanager.webapp.address</name>
<value>master:8088</value>
</property>
绑定 hostname
与 ip
之前我们在物理机中绑定过 ip
与 hostname
。现在,在虚拟机中进行同样的操作
$ sudo vim /etc/hosts
在文件末尾添加如下内容:
192.168.1.200 master
192.168.1.201 slave01
192.168.1.202 slave02
192.168.1.203 slave03
通过 ping master
检查是否修改成功
$ ping master
PING master (192.168.1.200) 56(84) bytes of data.
64 bytes from master (192.168.1.200): icmp_seq=1 ttl=64 time=0.016 ms
64 bytes from master (192.168.1.200): icmp_seq=2 ttl=64 time=0.022 ms
64 bytes from master (192.168.1.200): icmp_seq=3 ttl=64 time=0.021 ms
至此,我们已经完成了一台主机上 hadoop 的配置,接下来,我们通过 master 主机克隆 3 个 slave 主机
克隆多个虚拟主机
关闭虚拟机,选中列表中的 master,右键选择 clone
将其命名为 slave01,并把下面的对勾打上(用于重新初始化 MAC 地址)
继续创建 slave02, slave03,方法同上
现在,我们就有了 4 台虚拟主机
配置 slave 主机
修改 slave01 的 hostname
$ sudo vim /etc/hostname
内容如下:
slave01
修改 slave01 的 ip
$ sudo vim /etc/network/interfaces
将 address
修改为 192.168.1.201
对 slave02 和 slave03 做类似操作
配置 SSH 免密码登录
在 master 主机上运行如下命令(一路回车):
$ ssh-keygen -t rsa
此时 ~/.ssh
目录下会生成两个文件:id_rsa
id_rsa.pub
,前者是私钥,后者是公钥
将 id_rsa.pub
写入 authorized_keys
文件并测试是否可以对本机进行 SSH 无密码登录
$ cat .ssh/id_rsa.pub >> .ssh/authorized_keys
$ chmod 600 .ssh/authorized_keys
$ ssh localhost // 接下来会询问是否继续,输入 yes 回车
对 3 台 slave 主机进行上述操作均会生成自己的 authorized_keys
将 slave 主机的公钥依次复制到 master 主机
$ ssh-copy-id -i ~/.ssh/id_rsa.pub spark@master
此时 master 主机的 authorized_keys
文件内容如下:
$ cat .ssh/authorized_keys
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDPdIlGd1POJtarQAVIos5GuZKs64wRQfDXBT/p8WtLshKQ2NN+HGqOqwOY42VjtaEAhoWiWUaT4DPuMgMVso7N90oLVADOu8kEqE8EErrZKTbD1qW4HJOA5LNdNt6ExrTQQMQ8W8gdxN209/e/z7ZIblnT2ZXfw0Y5bQHYf37RI9+vo//NTPFLTP07YoKc9LYTx4YxQxw7PJRm7+G6B2wY5x/YIqYlhwWCqDut/lfoRFR0iMbifsjyOyNMSDF2/f6DQvTgx+EZ3UAxZFSQhE1HSdxpTsWA/SbRctF7MlTWrDYP6eknVfHjdD15CBcqEdkVbiKNJk6WjobeUy8XSWyz spark@master
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC20+5tTSIoj+cLVN9lhWtyyJudzKJP7lEz/bP3fecX00nNAeWD0YJnWMOVibw3ISMZ8lHu4YUqZjzN6taDesqGWtI57o7cRr5PeeuU2Iwruy48MOPHlx4kgXPjLN4APapTJ5m5UPZYjERt3RnEGfHMU5dowZ8QKAl4rk0yApctXoD3N1Kz2avNqKiREdzGo7bJm/HrEzt5uUqKqEQqVpFGOZRhZ7t2Ad/mu5/CvgB/weA24wC3noXliGTxdX6x0/SHKBdIBCWnTzgX6xAbs/l/Gix2Se70/Xl23pJRp4GK/ulOB4zKasxJOTfe0/33BhNT48AUCVoYXRUNuoq7Um3L spark@slave01
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7To6Xa58/2EPR0OOHFpsy5n9acp+a/cwoYXI9rIvO8ISG52FBHahtimEN2RgIon0oU+r32+E3wcZRB/4uwfBQriKxGHpII3WVTEj8qZoDywqITvbhM08EXBISzIIOfIc6s3zCZb6fqQW1Vsw5Toz6QteEB8g9Eq6AXrvM4PKILq+aZeV8qnjFZOWccjz+sHRXyNcP1v111hZbrrOBvAvh5Q8P79ReLDyWjJodfS6MTuQe6kMnTscvwA+2x/qxeYthkXDlp7+ETogYrP/LBcfd+LUX6A2fzFahQSy/Ok1Dzq0N/BRPnpEWD920GwpN0VhjOQMn7relKHxl0I4HUwAz spark@slave02
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC54wC6D1TckbScYKtErVdM8a332bIyyaFDTCoL7kyvHubx4ZE2uY9CxBxosKk/eC9GLYc3gIOfVrXotGBzafQxUUVf/AxsuP2cMoSQU4yjLmyFE5D/HISIG+1kt9wGE6RqL0HmQ7BAOMBwv0rvI4GeEpnEo3O7cwRmEh42r5mS7kAHYKg2f8sLqMeA8UXrh4YUqzs8r64lEphOgd4UBmAdc1xKrM9j95P3dKeFfRANSfckJkNHgdzGYWioaY/qSfYczjR8JLXT6veC822xF6Q6Za05fYMzVVW9f/DfNdXba01rb20RJmQ1lC68ClqgR5EDFqSt5xAaVn4aSuH57IOv spark@slave03
复制此文件到 3 台 slave 主机即可实现节点之间的免密码登录
$ scp .ssh/authorized_keys spark@slave01:/home/spark/.ssh/
$ scp .ssh/authorized_keys spark@slave02:/home/spark/.ssh/
$ scp .ssh/authorized_keys spark@slave03:/home/spark/.ssh/
Hadoop 的启动和测试
格式化文件系统
$ hdfs namenode -format
输出如下信息:
...
17/03/03 21:11:54 INFO util.ExitUtil: Exiting with status 0
17/03/03 21:11:54 INFO namenode.NameNode: SHUTDOWN_MSG:
/************************************************************
SHUTDOWN_MSG: Shutting down NameNode at master/192.168.1.200
************************************************************/
提示 Exiting with status 0
则表示格式化成功
启动 HDFS
启动 Hadoop HDFS
服务
$ start-dfs.sh
验证是否启动成功,在浏览器地址栏输入 http://master:50070 ,出现如下图所示的信息则表示启动成功:
也可以通过 jps
命令查看各节点是否正常启动
启动 Yarn
$ start-yarn.sh
验证是否启动成功,在浏览器地址栏输入 http://master:8088 ,出现如下图所示的信息则表示启动成功:
同样的,也可以使用 jps
命令查看各节点启动的进程
此时可以看到 master 节点多了 ResourceManager
进程,slave 节点多了 NodeManager
进程
集群验证
使用 Hadoop 自带的 WordCount 例子进行集群验证
- 在 HDFS 上创建目录
$ hadoop fs -mkdir -p /data/input
- 在本地创建
wordcount.txt
文件并上传到 HDFS
wordcount.txt
中的内容如下:
Hello laowang
hello kviccn
hello jack
上传到文件到 HDFS
$ hadoop fs -put wordcount.txt /data/input
- 运行 WordCount
$ hadoop jar ${HADOOP_HOME}/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.3.jar wordcount /data/input /data/output
等待运行结束,输出如下信息:
17/03/03 21:48:46 INFO client.RMProxy: Connecting to ResourceManager at master/192.168.1.200:8032
17/03/03 21:48:48 INFO input.FileInputFormat: Total input paths to process : 1
17/03/03 21:48:48 INFO mapreduce.JobSubmitter: number of splits:1
17/03/03 21:48:48 INFO mapreduce.JobSubmitter: Submitting tokens for job: job_1488547769795_0001
17/03/03 21:48:49 INFO impl.YarnClientImpl: Submitted application application_1488547769795_0001
17/03/03 21:48:49 INFO mapreduce.Job: The url to track the job: http://master:8088/proxy/application_1488547769795_0001/
17/03/03 21:48:49 INFO mapreduce.Job: Running job: job_1488547769795_0001
17/03/03 21:49:00 INFO mapreduce.Job: Job job_1488547769795_0001 running in uber mode : false
17/03/03 21:49:00 INFO mapreduce.Job: map 0% reduce 0%
17/03/03 21:49:09 INFO mapreduce.Job: map 100% reduce 0%
17/03/03 21:49:20 INFO mapreduce.Job: map 100% reduce 100%
17/03/03 21:49:21 INFO mapreduce.Job: Job job_1488547769795_0001 completed successfully
17/03/03 21:49:21 INFO mapreduce.Job: Counters: 49
...
查看结果:
$ hadoop fs -cat /data/output/*
Hello 1
hello 2
jack 1
kviccn 1
laowang 1
至此,Hadoop 完全分布式环境搭建成功。