本文基于三台阿里云ECS实例搭建完全分布式hadoop集群,并集成flume + kafka + sparkstreaming实现实时流处理。详细步骤会在本文后续一一写出,包括在搭建集群过程中遇到的坑以及应对办法。
三台ECS主机的规划如下:
外网ip | 内网ip | 角色 | |
主机1 | 47.101.148.34 | 172.19.173.4 | slave1 |
主机2 | 47.101.148.131 | 172.19.173.5 | slave2 |
主机3 | 106.14.199.161 | 172.19.173.3 | master |
【防坑】scala版本一定要和kafka版本对应,避免类似2.12前缀的scala和2.11前缀的kafka一起安装。
三台主机都需要修改。
编辑hosts文件:
vi /etc/hosts
添加以下节点:
172.19.173.3 master
172.19.173.4 slave1
172.19.173.5 slave2
这样就配置好了域名,在后面配置需要ip时我们可以直接用域名来方便地替换ip。
接下来修改主机名(xxx为刚刚在hosts配置的节点名)
hostnamectl set-hostname xxx
改完重启,执行hostname查看是否生效。
【防坑】集群节点最好在同一个子网内,因为其在安全性方面并没有做充分的设计,其设计之初就假定集群运行在一个安全可信的环境。例如一个是192.168.1.1,另一个就要设置为192.168.1.x。要不然后续会出很多麻烦,比如namenode给你启动失败。
【防坑】还要记得同步时间。不过用阿里云提供的centos7.4不用同步,默认自动同步。
三台主机都需要配置。
生成SSH的公钥,命令如下,三台主机都要执行一次:
ssh-keygen -t rsa
让输入内容直接回车即可,执行以后会在 /home/.ssh/(家目录/.ssh) 下生成id_rsa和id_rsa.pub文件。
将主机slave1和slave2在上一步骤生成的id_rsa.pub文件传到主机master的 /home/.ssh/ 下面,为了防止覆盖,重命名为id_rsa.pub.slave1和id_rsa.pub.slave2:
scp id_rsa.pub root@master:~/.ssh/id_rsa.pub.slave1
scp id_rsa.pub root@master:~/.ssh/id_rsa.pub.slave2
在主机master的 /home/.ssh/ 目录下分别将id_rsa.pub、id_rsa.pub.slave1和id_rsa.pub.slave2追加到authorized_keys文件中:
cat id_rsa.pub >> authorized_keys
cat id_rsa.pub.slave1 >> authorized_keys
cat id_rsa.pub.slave2 >> authorized_keys
将authorized_keys文件回传到各台主机中:
scp authorized_keys root@slave1:~/.ssh
scp authorized_keys root@slave2:~/.ssh
测试连通性,分别在各台主机试试ssh localhost、ssh master、ssh slave1、ssh slave2,均直接出现欢迎界面表示成功。
【防坑】如果是centos系统,还必须修改.ssh和.ssh/authorized_keys文件权限,要不会有权限错误。以下命令三台主机都要执行一次:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
三台主机都需要安装,在linux系统中,第三方软件最好都安装在/usr/local或/opt下,本文软件都安装在/usr/local下,后续不再说明。
https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
到官网下载jdk,我下载的是jdk1.8.0-181版本,并拷到各台阿里云服务器中,拷完后解压:
tar -zxvf jdk-8u181-linux-x64.tar.gz
设置环境变量:
vi /etc/profile
新增以下内容:
JAVA_HOME=/usr/local/jdk1.8.0_181
CLASSPATH=$JAVA_HOME/lib/
PATH=$PATH:$JAVA_HOME/bin
export PATH JAVA_HOME CLASSPATH
新增完保存退出后执行source使环境生效:
source /etc/profile
三台主机都需要安装。这里推荐两个网站,大数据各个组件都可以在这里找到并下载,速度比官网要快很多:
http://archive.apache.org/dist/
https://mirrors.tuna.tsinghua.edu.cn/apache/
后续不再说明。
三台主机都安装hadoop,这里的版本为hadoop-3.1.1
安装完成后进入/usr/local/hadoop-3.1.1/etc/hadoop,需要修改的配置文件为:core-site.xml、hdfs-site.xml、yarn-site.xml、mapred-site.xml、slaves、hadoop-env.sh、yarn-env.sh,因为这些配置文件均位于文件夹hadoop-3.1.1/etc/hadoop中,所以只需修改master的配置文件,然后同步文件夹hadoop-3.1.1/etc/hadoop到slave1和slave2中即可。
core-site.xml
fs.default.name
hdfs://master:9000
hadoop.tmp.dir
file:/usr/local/hadoop-3.1.1/tmp
io.file.buffer.size
131072
hdfs-site.xml
dfs.namenode.name.dir
file:/usr/local/hadoop-3.1.1/hdfs/namenode
dfs.datanode.data.dir
file:/usr/local/hadoop-3.1.1/hdfs/datanode
dfs.replication
2
dfs.permissions
false
need not permissions
dfs.namenode.http-address
master:50070
yarn-site.xml
yarn.resourcemanager.hostname
master
The address of the applications manager interface in the RM.
yarn.resourcemanager.address
${yarn.resourcemanager.hostname}:8032
The address of the scheduler interface.
yarn.resourcemanager.scheduler.address
${yarn.resourcemanager.hostname}:8030
The http address of the RM web application.
yarn.resourcemanager.webapp.address
${yarn.resourcemanager.hostname}:18088
The https adddress of the RM web application.
yarn.resourcemanager.webapp.https.address
${yarn.resourcemanager.hostname}:18090
yarn.resourcemanager.resource-tracker.address
${yarn.resourcemanager.hostname}:8031
The address of the RM admin interface.
yarn.resourcemanager.admin.address
${yarn.resourcemanager.hostname}:8033
yarn.nodemanager.aux-services
mapreduce_shuffle
mapred-site.xml
mapreduce.framework.name
yarn
mapred.job.tracker
master:9001
workers(本来没有这个文件,新建这个文件,然后添加以下内容)
slave1
slave2
【防坑】hadoop3中不用slaves文件,变成了workers文件,如果是hadoop2还是用slaves文件。
hadoop-env.sh、yarn-env.sh
export JAVA_HOME=/usr/local/jdk1.8.0_181
将修改好配置文件的hadoop目录从master拷贝至slave1和slave2,这样slave节点就不用重新再配置了:
scp -r /usr/local/hadoop-3.1.1 root@slave1:/usr/local
scp -r /usr/local/hadoop-3.1.1 root@slave2:/usr/local
接下来运行hadoop,启动hadoop的命令都只在master上执行。
1、首次使用,清空master的hdfs和tmp数据:
rm -rf /usr/local/hadoop-3.1.1/hdfs/*
rm -rf /usr/local/hadoop-3.1.1/tmp/*
2、master格式化namenode:
/usr/local/hadoop-3.1.1/bin/hdfs namenode -format
3、master启停hdfs:
/usr/local/hadoop-3.1.1/sbin/start-dfs.sh
/usr/local/hadoop-3.1.1/sbin/stop-dfs.sh
验证是否启动成功,在master输入 jps,应当存在namenode和secondary namenode,在slave上输入jps,应当存在datenode。
进一步验证,访问:http://106.14.199.161:50070/dfshealth.html#tab-overview(106.14.199.161是master的ip),打开成功。
【防坑】如果运行脚本报如下错误:
ERROR: Attempting to launch hdfs namenode as root
ERROR: but there is no HDFS_NAMENODE_USER defined. Aborting launch.
Starting datanodes
ERROR: Attempting to launch hdfs datanode as root
ERROR: but there is no HDFS_DATANODE_USER defined. Aborting launch.
Starting secondary namenodes [localhost.localdomain]
ERROR: Attempting to launch hdfs secondarynamenode as root
ERROR: but there is no HDFS_SECONDARYNAMENODE_USER defined. Aborting launch.
解决方案:
(缺少用户定义而造成的)因此编辑启动和关闭。
分别修改以下两个文件:
vi sbin/start-dfs.sh
vi sbin/stop-dfs.sh
顶部空白处添加以下四行:
HDFS_DATANODE_USER=root
HADOOP_SECURE_DN_USER=hdfs
HDFS_NAMENODE_USER=root
HDFS_SECONDARYNAMENODE_USER=root
再次启动脚本。
4、master启停yarn:
/usr/local/hadoop-3.1.1/sbin/start-yarn.sh
/usr/local/hadoop-3.1.1/sbin/stop-yarn.sh
在master输入 jps,应当存在resourcemanager。
在slave1和slave2输入jps,应当存在nodemanager。
访问:http://106.14.199.161:18088/cluster(106.14.199.161是master的ip),打开成功。
【防坑】注意,阿里云上不能配置8088端口,会有黑客定期扫描Yarn ResourceManager并植入挖矿程序。
【防坑】如果启动时报如下错误:
Starting resourcemanager
ERROR: Attempting to launch yarn resourcemanager as root
ERROR: but there is no YARN_RESOURCEMANAGER_USER defined. Aborting launch.
解决方案:
(也是由于缺少用户定义)
是因为缺少用户定义造成的,所以分别编辑开始和关闭脚本。
分别修改以下两个文件:
vi sbin/start-yarn.sh
vi sbin/stop-yarn.sh
顶部添加以下三行:
YARN_RESOURCEMANAGER_USER=root
HADOOP_SECURE_DN_USER=yarn
YARN_NODEMANAGER_USER=root
再次启动脚本。
三台主机都安装zookeeper,版本为zookeeper-3.4.12
1、建立数据目录:
mkdir usr/local/zookeeper-3.4.12/data
2、进入conf目录创建并修改zoo.cfg文件:
cp zoo_sample.cfg zoo.cfg
vi zoo.cfg
修改后的内容如下:
# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just
# example sakes.
dataDir=/usr/local/zookeeper-3.4.12/data
# the port at which the clients will connect
clientPort=2181
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1
server.1=0.0.0.0:2888:3888
server.2=slave1:2888:3888
server.3=slave2:2888:3888
【防坑】zoo.cfg 的修改,各个主机下对应的 server.x 中的 ip 设置为 0.0.0.0。
3、在数据目录/usr/local/zookeeper-3.4.12/data下面新建名为myid的文件,各个主机对应的内容是不同的,master的内容是1,slave1的内容是2,slave2的内容是3,分别对应zoo.cfg中server.x中的x。
4、设置环境变量:
vi /etc/profile
新增以下内容并source使环境生效:
export ZOOKEEPER_HOME=/usr/local/zookeeper-3.4.12
export PATH=$PATH:$ZOOKEEPER_HOME/bin:$ZOOKEEPER_HOME/conf
5、启停zookeeper
/usr/local/zookeeper-3.4.12/bin/zkServer.sh start
/usr/local/zookeeper-3.4.12/bin/zkServer.sh stop
三台主机都执行启动命令,启动完后命令行输入jps,显示QuorumPeerMain为正常。
查看各个主机的状态:
sh bin/zkServer.sh status
可以看到哪台主机是leader,哪台是follower。
三台主机都安装HBase,版本为hbase-1.4.6
安装成功后执行以下操作。
1、修改conf目录下的三个文件:hbase-env.sh、hbase-site.xml、regionservers:
hbase-env.sh
export JAVA_HOME=/usr/local/jdk1.8.0_181
export HBASE_MANAGES_ZK=true
export HBASE_LOG_DIR=/usr/local/hbase-1.4.6/logs
hbase-site.xml
hbase.rootdir
hdfs://master:9000/hbase
hbase.cluster.distributed
true
hbase.zookeeper.quorum
master,slave1,slave2
hbase.master.maxclockskew
180000
Time difference of regionserver from master
regionservers
slave1
slave2
2、master启停hbase
usr/local/hbase-1.4.6/bin/start-hbase.sh
usr/local/hbase-1.4.6/bin/stop-hbase.sh
master输入jps,显示HMaster为正常。
slave输入jps,显示HRegionServer为正常。
访问:http://106.14.199.161:16010/master-status,打开成功。
三台主机都安装Spark,版本为spark-2.1.0-bin-hadoop2.7
安装成功后执行以下操作。
1、创建并修改conf目录下的配置文件 spark-env.sh,slaves:
spark-env.sh
cp spark-env.sh.template spark-env.sh
vi spark-env.sh
修改后的内容为:
export JAVA_HOME=/usr/local/jdk1.8.0_181
export HADOOP_HOME=/usr/local/hadoop-3.1.1
export HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoop
export HBASE_HOME=/usr/local/hbase-1.4.6
slaves
cp slaves.template slaves
vi slaves
修改后的内容为:
slave1
slave2
2、master启停spark:
/usr/local/spark-2.1.0-bin-hadoop2.7/sbin/start-all.sh
/usr/local/spark-2.1.0-bin-hadoop2.7/sbin/stop-all.sh
master键入jps,显示Master为正常。
slave键入jps,显示Worker为正常。
访问:http://106.14.199.161:8080/,打开成功。
1、安装scala和maven
安装scala,版本为scala-2.11.8。
安装maven,版本为apache-maven-3.5.4。
2、设置环境变量,vi /etc/profile,新增以下内容并source使环境生效:
export M2_HOME=/usr/local/apache-maven-3.5.4
export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$M2_HOME/bin:$PATH
export PATH="$PATH:/usr/local/scala-2.11.8/bin"
三台主机都安装kafka,版本为kafka_2.11-0.10.1.0
安装成功后执行以下操作。
1、进入Kafka的config目录,修改server.properties:
broker.id=1 #约定master为1,slave1为2,slave2为3
listeners=PLAINTEXT://172.19.173.3:9092 #阿里云内网ip
advertised.listeners=PLAINTEXT://106.14.199.161:9092 #阿里云外网ip
zookeeper.connect=172.19.173.3:2181,172.19.173.4:2181,172.19.173.5:2181
2、启动kafka
三台主机都打开kafka。进入各台主机下的kafka目录,执行命令:
bin/kafka-server-start.sh config/server.properties &
【防坑】阿里云ECS突发实例2G内存太小起不来,需要修改kafka下的kafka-server-start.sh和zookeeper-server-start.sh,找到KAFKA_HEAP_OPTS="-Xmx1G -Xms1G",Xms最小内存,Xmx最大内存,默认都为1G,根据需要自行修改。
kafka相关命令汇总:
任意一台主机安装flume,版本为apache-flume-1.8.0-bin
安装成功后执行以下操作。
1、进入flume目录,修改conf/flume-env.sh:
export JAVA_HOME=/usr/local/jdk1.8.0_181
export JAVA_OPTS="-Xms128m -Xmx256m -Dcom.sun.management.jmxremote"
2、添加配置文件flume-conf.properties,修改内容如下(此处我随便建了一个/tmp/logs/kafka.log文件,tail -F表示监听这个文件追加的内容):
agent.sources = s1
agent.channels = c1
agent.sinks = k1
#配置s1
agent.sources.s1.type=exec
agent.sources.s1.command=tail -F /tmp/logs/kafka.log
agent.sources.s1.channels=c1
#配置c1
agent.channels.c1.type=memory
agent.channels.c1.capacity=10000
agent.channels.c1.transactionCapacity=100
#配置k1
agent.sinks.k1.type= org.apache.flume.sink.kafka.KafkaSink
agent.sinks.k1.kafka.bootstrap.servers=172.19.173.3:9092,172.19.173.4:9092,172.19.173.5:9092
agent.sinks.k1.kafka.topic=test
agent.sinks.k1.serializer.class=kafka.serializer.StringEncoder
agent.sinks.k1.channel=c1
3、设置环境变量,vi /etc/profile,新增以下内容并source使环境生效:
export FLUME_HOME=/usr/local/apache-flume-1.8.0-bin
export PATH=$PATH:$FLUME_HOME/bin
4、进入flume安装目录,启动flume
bin/flume-ng agent --conf-file conf/flume-conf.properties -c conf/ --name agent -Dflume.root.logger=INFO,console
三台主机都要执行
1、自己找以下这4个文件分别放入三台主机spark目录下的jars中:
2、然后cd到hbase安装目录的lib下,以下jar文件统一copy一份放到spark安装目录的jars中:
【防坑】注意:在利用spark程序往hbase中写数据时,如果缺少metrics-core-2.2.0.jar这个jar,spark程序会一直卡在stage阶段并一直尝试构建stage,但不会报任何错,等了大概半小时后,程序报错:
java.lang.NoClassDefFoundError: com/yammer/metrics/core/Gauge: 5 times, server with issue: null
3、进入spark目录下的bin,执行指令:
./spark-submit --master spark://master:7077 --driver-memory 512M --executor-memory 512M --total-executor-cores 2 --class "com.main.Monitor" ~/SparkDemo.jar
SparkDemo.jar为自己写的测试jar