Environment
- 腾讯学生云
- CentOS 7.6,64 位
Non-distributed & Pseudo-distributed
这部分是在一部机上先搞搞环境,之后作为 master,包括非分布式和伪分布式的例程测试。有些配置步骤后面配 slave 的时候会有重复。
account
- 创建 hadoop 账户:
useradd -m hadoop -s /bin/bash
; - 改密码为
hadoop
:passwd hadoop
,输入hadoop
; - 赋 sudo 权限:
visudo
打开文件,找到root ALL=(ALL) ALL
这行(100 行左右),在后面加一行:hadoop ALL=(ALL) ALL
(用 tab 间开);
ssh
生成 ssh 公、私钥,方便免密登录。
- 执行
ssh-keygen -t rsa
,一路回车,就会在 ~/.ssh 生成公钥 id_rsa.pub 和私钥 id_rsa; - 将自己的公钥放到 authorized_keys 里:
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
,让 master 可以免密连自己; - 然后将 ~/.ssh 的内容复制一份放到 /home/hadoop 下(不知道有没有用)。
Java
去 [4] 下载(.tar.gz),参考 [6] 配置。
-
将压缩包解压到 /usr/local/java/(没有就先新建:
mkdir -p /usr/local/java
):tar -zxvf jdk-8u40-linux-x64.gz -C /usr/local/java
; -
编辑 /etc/profile,在末尾加上:
export JAVA_HOME=/usr/local/java/jdk1.8.0_40 export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar export PATH=$PATH:$JAVA_HOME/bin
保存后执行
source /etc/profile
使其生效; -
hello world 测试:
// test.java public class test { public static void main(String args[]) { System.out.println("hello world!"); } }
执行
javac test.java
和java test
;
hadoop installation
-
解压到 /usr/local/:
tar -zxvf hadoop-2.6.0-cdh5.6.0.tar.gz -C /usr/local
,然后cd /usr/local/
,将解压文件夹改名成 hadoop:mv hadoop-2.6.0-cdh5.6.0/ hadoop
; -
修改权限:
chown -R hadoop:hadoop ./hadoop
; -
再编辑 /etc/profile,在末尾加上:
export HADOOP_HOME=/usr/local/hadoop export PATH=$PATH:$HADOOP_HOME/bin 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
保存后执行
source /etc/profile
使其生效; -
执行
hadoop version
测试;
non-distubited example
非分布式例程测试,参考 [7]。cd /usr/local/hadoop
执行 hadoop jar ./share/hadoop/mapreduce/hadoop-mapreduce-examples-2.6.0-cdh5.6.0.jar
查看可以跑的例程,其中有个 grep 例程,跑它。
mkdir -p ~/input
cp ./etc/hadoop/*.xml ~/input # 将配置文件作为输入文件
adoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.6.0-cdh5.6.0.jar grep ~/input ~/output 'dfs[a-z.]+'
cat ~/output/* # 查看输出
看到一行 1 dfsadmin
的输出就是可以了。如果要跑下个例子,要先手动删掉 ~/output
,或者输出到别处,否则会报错。
pseudo-distributed
配一下伪分布式,并且跑个例程测试。切到 /usr/local/hadoop/,这 part 默认以此为工作目录;
configure
-
Hadoop 的配置文件位于
/usr/local/hadoop/etc/hadoop/
中,伪分布式需要修改 2 个配置文件:core-site.xml 和 hdfs-site.xml。- core-site.xml
<configuration> <property> <name>hadoop.tmp.dir</name> <value>file:/usr/local/hadoop/tmp</value> <description>Abase for other temporary directories.</description> </property> <property> <name>fs.defaultFS</name> <value>hdfs://localhost:9000</value> </property> </configuration>
- hdfs-site.xml
<configuration> <property> <name>dfs.replication</name> <value>1</value> </property> <property> <name>dfs.namenode.name.dir</name> <value>file:/usr/local/hadoop/tmp/dfs/name</value> </property> <property> <name>dfs.datanode.data.dir</name> <value>file:/usr/local/hadoop/tmp/dfs/data</value> </property> </configuration>
-
执行 namenode 格式化:
hdfs namenode -format
,仅首次运行需要,以后都不用; -
开启 NaneNode 和 DataNode 守护进程:
sbin/start-dfs.sh
;- 报错说没有 JAVA_HOME,参考 [8, 7],把前面 /etc/profile export 的那些 java 的、 hadoop 的环境变量咸不论都追加到 etc/hadoop/hadoop-env.sh 末尾(这文件在 25 行左右本来就 export 过一次 JAVA_HOME,看来没什么卵用,注了),然后再执行;
-
执行
jps
测试,看到输出形如:15296 DataNode 15457 SecondaryNameNode 16116 Jps 15180 NameNode
就可以了;
-
可以在自己电脑(因为服务器无界面)的浏览器用
<服务器公网IP>:50070
看到 hadoop 的一些信息;
example
-
在 HDFS 中创建用户目录:
hdfs dfs -mkdir -p /user/hadoop
; -
类似之前非分布式的操作,只不过要在 HDFS 文件系统中操作,而不是本机的文件系统:
hdfs dfs -mkdir /user/hadoop/input hdfs dfs -put etc/hadoop/*.xml /user/hadoop/input # 复制文件 hdfs dfs -ls /user/hadoop/input # 查看目录
-
跑 grep 例程:
hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.6.0-cdh5.6.0.jar grep /user/hadoop/input /user/hadoop/output 'dfs[a-z.]+'
; -
查看结果:
hdfs dfs -cat /user/hadoop/output/*
,输出形如:1 dfsadmin 1 dfs.replication 1 dfs.namenode.name.dir 1 dfs.datanode.data.dir
就是了;
-
可以将 HDFS 中的文件取出到本地文件系统:
rm -rf ~/output # 先删掉之前非分布式的输出目录 hdfs dfs -get /user/hadoop/output ~/output # 取出 cat ~/output/*
可以看到,结果一样;
-
同样,若要跑下一个测试,先删掉刚才的输出目录:
hdfs dfs -rm -r /user/hadoop/output
,或者指定另外的输出目录; -
关闭 hadoop 的命令:
sbin/stop-dfs.sh
,下次再启动时,不用再进行 namenode 初始化,直接用sbin/start-dfs.sh
启动就行;
Hadoop Cluster
腾讯云可以将刚配好的 master 结点打包成镜像,然后共享,在其它用作 slave 的结点上用这个共享的镜像重装,于是环境就复制过去了。
host name
修改各结点主机名,编辑 /etc/hostname,分别在各主机将内容改成 master
、slave1
、slave2
…
然后重启,使其生效。
hosts
修改 IP 和主机名的映射,编辑 /etc/hosts 文件,以 master 机为例:
<master内网IP> master # 注意是 内 网
<slave1公网IP> slave1
<slave2公网IP> slave2
- 注:本机用内网 IP,其它机用公网 IP。其它 slave 结点类推。
这样就可以用主机名代替 IP,用 ssh slave1
或 ping slave2
测试。
由于在前面配 master 的时候将它自己的公钥放进了 authorized_keys,而这些 slave 结点又是从 master 镜像复制过来,所以没另外配 ssh 也可以免密登录。
- REMARK:这么做不知道有没有潜在 bug,稳一拨还是建议各结点生成各自的公、私钥,再分发。
configuration files
参考 [3],修改 /usr/local/hadoop/etc/hadoop/ 下的 5 个配置文件:slaves、core-site.xml、hdfs-site.xml、mapred-site.xml、yarn-site.xml。这些文件先在 master 配好,然后打包分发到各 slaves。
slaves
此文件列出所有作为 DataNode 的主机名,原本有一行 localhost
,master 如果保留这行就是 master 同时作为 NameNode 和 DataNode,也可以删掉,使 master 仅作为 NameNode。这里把它删掉:
slave1
slave2
core-site.xml
先用 <!-- ...blabla... -->
把之前的配置注掉。
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://Master:9000</value>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>file:/usr/local/hadoop/tmp</value>
<description>Abase for other temporary directories.</description>
</property>
</configuration>
hdfs-site.xml
同样先注掉之前的。照 [3] 的说法,其中 dfsd.replication
难道是 slave 结点的数量?于是设成 2。
<configuration>
<property>
<name>dfs.namenode.secondary.http-address</name>
<value>Master:50090</value>
</property>
<property>
<name>dfs.replication</name>
<value>2</value>
</property>
<property>
<name>dfs.namenode.name.dir</name>
<value>file:/usr/local/hadoop/tmp/dfs/name</value>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>file:/usr/local/hadoop/tmp/dfs/data</value>
</property>
</configuration>
mapred-site.xml
原有的文件叫 mapred-site.xml.template,先 cp mapred-site.xml.template mapred-site.xml
复制一份,然后修改。
<configuration>
<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>
</configuration>
yarn-site.xml
<configuration>
<property>
<name>yarn.resourcemanager.hostname</name>
<value>Master</value>
</property>
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
</configuration>
pack & distribution
配好这些之后,将 /usr/local/hadoop/ 目录整个打包分发到各 slave 结点。
打包之前,先将之前伪分布式的一些临时文件删除:
cd /usr/local
rm -rf hadoop/tmp
rm -rf hadoop/logs/*
tar 打包,scp 发送:
tar zcf ~/hadoop.master.tar.gz hadoop # 打包放在 ~
scp ~/hadoop.master.tar.gz slave1:/home/hadoop
scp ~/hadoop.master.tar.gz slave2:/home/hadoop
unpack
现在分别登录各 slaves 结点,解压。由于各 slave 是克隆 master 的,已经有了 /usr/local/hadoop/ 目录,可以先将它重命名成 ~hadoop,然后再解压:
# 在 slave 结点终端
/usr/local/hadoop/sbin/stop-dfs.sh # 先停掉
cd /home/hadoop # 刚才传到这里
mv /usr/local/hadoop/ /usr/local/~hadoop # 直接删掉也行
tar zxvf hadoop.master.tar.gz -C /usr/local
chown -R hadoop /usr/local/hadoop
NameNode init
退回 master ,执行 NameNode 初始化:hdfs namenode -format
,仅首次运行需要,以后都不用。
firewall
关闭防火墙:
systemctl stop firewalld.service
systemctl disable firewalld.service
每个结点都要。
start
在 master 执行:
start-dfs.sh
start-yarn.sh
mr-jobhistory-daemon.sh start historyserver
可以分别在 master 和各 slave 上执行 jps
测试,master 输出形如:
2544 NameNode
3221 JobHistoryServer
3318 Jps
2906 ResourceManager
2731 SecondaryNameNode
slave 输出形如:
1553 DataNode
2118 Jps
1703 NodeManager
可以在自己电脑(因为服务器无界面)的浏览器用 <服务器公网IP>:50070
看到 hadoop 的一些信息。
example
执行分布式例程,在 master 上操作。
-
在 hdfs 上创建用户目录:
hdfs dfs -mkdir -p /user/hadoop
; -
复制文件:
hdfs dfs -mkdir /user/hadoop/input hdfs dfs -put /usr/local/hadoop/etc/hadoop/*.xml /user/hadoop/input
可以用
hdfs dfs -ls /user/hadoop/input
查看,也可以在<服务器公网IP>:50070
中看到Block Pool Used
那里有改变; -
运行例程:
hadoop jar /usr/local/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.6.0-cdh5.6.0.jar grep /user/hadoop/input /user/hadoop/output 'dfs[a-z.]+'
;- 可以看到形如
mapreduce.Job: map 67% reduce 22%
这样的进度信息; - 也可以在
<服务器公网IP>:8088/cluster
中看;
- 可以看到形如
-
查看结果:
hdfs dfs -cat /user/hadoop/output/*
,结果…输出为空? -
队友在跑 word count 例程的时候发现各种出错,最后好像说是把 dfs 里的临时文件删掉就可以了,见 2.6.2 第 6 点。
close
关闭集群,在 master 执行:
stop-yarn.sh
stop-dfs.sh
mr-jobhistory-daemon.sh stop historyserver