总结一下在生产环境部署Hadoop+Spark+HBase+Hue等产品遇到的问题、提高效率的方法和相关的配置。

集群规划

假设现在生产环境的信息如下:

  • 服务器数量:6
  • 操作系统:Centos7
  • Master节点数:2
  • Zookeeper节点数:3
  • Slave节点数:4

划分各个机器的角色如下:

主机名角色运行进程
hadoop1MasterNamenode
hadoop2Master_backupNamenode
hadoop3Slave、YarnDatanode、ResourceManager、NodeManager
hadoop4Slave、ZookeeperDatanode、NodeManager、QuorumPeerMain
hadoop5Slave、ZookeeperDatanode、NodeManager、QuorumPeerMain
hadoop6Slave、ZookeeperDatanode、NodeManager、QuorumPeerMain

一些注意事项

尽量使用非root用户

这是为了避免出现一些安全问题,毕竟是生产环境,即使不是也养成习惯。
各个机器的用户名保持一致,需要超级用户权限时加入sudoers里面即可。

数据存放的目录和配置文件分离

一般我们在自己的虚拟机上搭建集群的时候这个可以忽略不计,但是生产机器上需要注意一下。

由于生产机一般配置都很高,几十T的硬盘很常见,但是这些硬盘都是mount上去的,如果我们按照虚拟机上的操作方式来部署的话,集群的所有数据还是会在/目录下,而这个目录肯定是不会大到哪里去,
有可能就出现跑着跑着抛磁盘空间爆满的异常,但是回头一查,90%的资源没有利用到。
所以,将集群存放数据的目录统一配置到空间大的盘上去,而配置文件保持不变,即配置文件和数据目录的分离,避免互相影响,另外在使用rsync进行集群文件同步的时候也比较方便。

规划集群部署的目录

部署之前提前将各个目录分配好,针对性的干活~
这里将Hadoop、HBase、Spark等软件安装在:/usr/local/bigdata目录下
数据存放目录配置在:/data2/bigdata下
这里的/data2为mount上去的硬盘

集群部署

这里使用的各个软件版本号为:

  • Zookeeper3.4.5
  • Hadoop2.2.0
  • HBase0.98
  • Spark1.4.1
  • Hive1.2.1
  • Hue3.7.0

必要准备

1、修改主机名和IP的映射关系

编辑/etc/hosts文件,确保各个机器主机名和IP地址的映射关系

2、防火墙设置

生产环境上防火墙不可能关闭,所以查考下方的端口表让网络管理员开通吧~
P.S. 当然如果你不care的话直接关防火墙很省事,不过不推荐。。

3、JDK的配置

先检查一下生产机上有没有预装了OpenJDK,有的话卸了吧~

rpm -qa | grep OracleJDK

把出现的所有包都

rpm -e --nodeps

卸载掉。

重新安装OracleJDK,版本没有太高要求,这里使用1.7。
到Oracle官网下载对应版本的JDK之后在安装在/usr/local下面,在~/.bash_profile中配置好环境变量,输入java -version出现对应信息即可。

4、ssh免密码登陆

这个步骤如果机器比较多的话就会很烦了,现在各个机器上生成ssh密钥:

ssh-keygen -t rsa

一路回车保存默认目录:~/.ssh
通过ssh将各个机器的公钥复制到hadoop1的~/.ssh/authorized_keys中,然后发放出去:

#本机的公钥
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
#各个节点的公钥
ssh hadoopN cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
#复制完之后将authorized_keys发放给各个节点
scp ~/.ssh/authorized_keys hadoopN:~/.ssh/authorized_keys

测试:

ssh date hadoop2

如果出现权限问题尝试使用:

chmod -R 700 ~/.ssh

Zookeeper

将zk上传到/usr/local/bigdata中解压缩
进入conf目录,修改zoo.cfg:

cp zoo_sample.cfg zoo.cfg
vim zoo.cfg
#修改:
dataDir=/data2/bigdata/zookeeper/tmp
ticktickTime=20000

#在最后添加:
server.1=hadoop4:2888:3888
server.2=hadoop5:2888:3888
server.3=hadoop6:2888:3888

ticktickTime默认为2000,2-20倍的minSessionTimeout与maxSessionTimeout
注: tickTime 心跳基本时间单位毫秒,ZK基本上所有的时间都是这个时间的整数倍。
zk的详细配置见:
zookeeper配置文件详解

创建配置的dataDir:

mkdir /data2/bigdata/zookeeper/tmp
touch /data2/bigdata/zookeeper/tmp/myid
echo 1 > /data2/bigdata/zookeeper/tmp/myid

配置结束,将Zookeeper传到hadoop5、6上,创建dataDir并修改myid为2、3

启动

在hadoop4、5、6上进入zk的bin目录:

./zkServer.sh start
./zkServer.sh status

正确的结果应该是一个leader,两个follower

Hadoop

上传hadoop包到/usr/local/bigdata并解压缩,进入etc/hadoop目录

hadoop-env.sh

考虑到数据和程序的分离,决定将那些会不断增长的文件都配置到/data2/bigdata/hadoop下,包括:日志文件,pid目录,journal目录。
所以在此文件中需要配置:

  1. JAVA_HOME
  2. HADOOP_PID_DIR
  3. HADOOP_LOG_DIR
  4. HADOOP_CLASSPATH

HADOOP_CLASSPATH根据需要配置其他jar包的路径

yarn-en.sh

  1. YARN_LOG_DIR
  2. YARN_PID_DIR

其他五个核心文件内容如下:

core-site.xml:

<configuration>
<!--hdfs通讯地址-->
<property>
<name>fs.defaultFS</name>
<value>hdfs://ns1</value>
</property>
<!--数据存放目录-->
<property>
<name>hadoop.tmp.dir</name>
<value>/data2/bigdata/hadoop/tmp</value>
</property>
<!--zk地址-->
<property>
<name>ha.zookeeper.quorum</name>
<value>hadoop4:2181,hadoop5:2181,hadoop6:2181</value>
</property>
<!--hdfs回收站文件保留时间-->
<property>
<name>fs.trash.interval</name>
<value>4320</value>
</property>
<!--hue相关配置-->
<property>
<name>hadoop.proxyuser.hue.hosts</name>
<value>*</value>
</property>
<property>
<name>hadoop.proxyuser.hue.groups</name>
<value>*</value>
</property>
<!--Zookeeper连接超时的设置-->
<property>
<name>ha.zookeeper.session-timeout.ms</name>
<value>6000000</value>
</property>
<property>  
<name>ha.failover-controller.cli-check.rpc-timeout.ms</name>  
<value>6000000</value>  
</property>  
<property>  
<name>ipc.client.connect.timeout</name>  
<value>6000000</value>  
</property>
</configuration>

hdfs-site.xml:

<configuration>
<!--hdfs元数据存放路径-->
<property>
<name>dfs.name.dir</name>  
<value>/data2/hadoop/hdfs/name</value>  
</property>
<!--hdfs数据目录,可配置多个-->
<property>
<name>dfs.data.dir</name>  
<value>/data2/hadoop/hdfs/data</value>  
</property>
<!--节点上剩下多少空间时不再写入,配置为6G,手动调整-->
<property>
<name>dfs.datanode.reserved</name> 
<value>6000000000</value> 
</property>
<!--节点访问控制-->
<property>
<name>dfs.hosts</name>
<value>/usr/local/bigdata/hadoop/etc/hadoop/datanode-allow.list</value>
</property>
<property>
<name>dfs.hosts.exclude</name>
<value>/usr/local/bigdata/hadoop/etc/hadoop/datanode-deny.list</value>
</property>
<!--Namenode服务名-->
<property>
<name>dfs.nameservices</name>
<value>ns1</value>
</property>
<!--Namenode配置-->
<property>
<name>dfs.ha.namenodes.ns1</name>
<value>nn1,nn2</value>
</property>
<property>
<name>dfs.namenode.rpc-address.ns1.nn1</name>
<value>hadoop1:9000</value>
</property>
<property>
<name>dfs.namenode.http-address.ns1.nn1</name>
<value>hadoop1:50070</value>
</property>
<property>
<name>dfs.namenode.rpc-address.ns1.nn2</name>
<value>hadoop2:9000</value>
</property>
<property>
<name>dfs.namenode.http-address.ns1.nn2</name>
<value>hadoop2:50070</value>
</property>
<!--journalnode配置-->
<property>
<name>dfs.namenode.shared.edits.dir</name> 
<value>qjournal://hadoop4:8485;hadoop5:8485;hadoop6:8485/ns1</value>
</property>
<property>
<name>dfs.journalnode.edits.dir</name>
<value>/data2/hadoop/journal</value>
</property>
<!--其他-->
<property>
<name>dfs.ha.automatic-failover.enabled</name>
<value>true</value>
</property>
<property>
<name>dfs.client.failover.proxy.provider.ns1</name>
<value>
org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider
</value>
</property>
<property>
<name>dfs.ha.fencing.methods</name>
<value>
sshfence
shell(/bin/true)
</value>
</property>
<property>
<name>dfs.ha.fencing.ssh.private-key-files</name>
<value>/home/hadoop/.ssh/id_rsa</value>
</property>
<property>
<name>dfs.ha.fencing.ssh.connect-timeout</name>
<value>30000</value>
</property>
<!--为hue开启webhdfs-->
<property>
<name>dfs.webhdfs.enabled</name>
<value>true</value>
</property>
<property>
<name>dfs.permissions</name>
<value>false</value>
</property>
<!--连接超时的一些设置-->
<property>
<name>dfs.qjournal.start-segment.timeout.ms</name>
<value>600000000</value>
</property>
<property>
<name>dfs.qjournal.prepare-recovery.timeout.ms</name>
<value>600000000</value>
</property>
<property>
<name>dfs.qjournal.accept-recovery.timeout.ms</name>
<value>600000000</value>
</property>
<property>
<name>dfs.qjournal.prepare-recovery.timeout.ms</name>
<value>600000000</value>
</property>
<property>
<name>dfs.qjournal.accept-recovery.timeout.ms</name>
<value>600000000</value>
</property>
<property>
<name>dfs.qjournal.finalize-segment.timeout.ms</name>
<value>600000000</value>
</property>
<property>
<name>dfs.qjournal.select-input-streams.timeout.ms</name>
<value>600000000</value>
</property>
<property>
<name>dfs.qjournal.get-journal-state.timeout.ms</name>
<value>600000000</value>
</property>
<property>
<name>dfs.qjournal.new-epoch.timeout.ms</name>
<value>600000000</value>
</property>
<property>
<name>dfs.qjournal.write-txns.timeout.ms</name>
<value>600000000</value>
</property>
<property>
<name>ha.zookeeper.session-timeout.ms</name>
<value>6000000</value>
</property>
</configuration>

dfs.name.dir和dfs.data.dir分别是存储hdfs元数据信息和数据的目录,如果没有配置则默认存储到hadoop.tmp.dir中。
其中dfs.name.dir可以配置为多个目录,相当于备份,以免出现元数据被破坏的情况。

mapred-site.xml:

<configuration>
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
<property>
<name>mapreduce.jobhistory.webapp.address</name>
<value>hadoop1:19888</value>
</property>
</configuration>

yarn-site.xml:

<configuration>
<property>
<name>yarn.resourcemanager.hostname</name>
<value>hadoop1</value>
</property>
<property> 
<name>yarn.nodemanager.aux-services</name> 
<value>mapreduce_shuffle</value> 
</property>
<property>
<name>yarn.log-aggregation-enable</name>
<value>true</value>
</property>
<property>
<name>yarn.nodemanager.remote-app-log-dir</name>
<value>/data2/bigdata/hadoop/logs/yarn</value>
</property>
<property>
<name>yarn.log-aggregation.retain-seconds</name>
<value>259200</value>
</property>
<property>
<name>yarn.log-aggregation.retain-check-interval-seconds</name>
<value>3600</value>
</property>
<property>
<name>yarn.nodemanager.webapp.address</name>
<value>0.0.0.0:8042</value>
</property>
<property>
<name>yarn.nodemanager.log-dirs</name>
<value>/data2/bigdata/hadoop/logs/yarn/containers</value>
</property>
</configuration>

修改slaves文件将各个子节点主机名加入
将配置好的hadoop通过scp拷贝到其他节点

第一次格式化HDFS

启动journalnode(在hadoop1上启动所有journalnode,注意:是调用的hadoop-daemons.sh这个脚本,注意是复数s的那个脚本)
进入hadoop/sbin目录:

./hadoop-daemons.sh start journalnode

运行jps命令检验,hadoop4、hadoop5、hadoop6上多了JournalNode进程

格式化HDFS(在bin目录下),在hadoop1上执行命令:

./hdfs namenode -format

格式化后会在根据core-site.xml中的hadoop.tmp.dir配置生成个文件,将对应tmp目录拷贝到hadoop2对应的目录下(hadoop初次格式化之后要将两个nn节点的tmp/dfs/name文件夹同步)。

格式化ZK(在hadoop1上执行即可,在bin目录下)

./hdfs zkfc -formatZK

之后启动hdfs和yarn,并用jps命令检查

HBase

解压之后配置hbase集群,要修改3个文件
注意:要把hadoop的hdfs-site.xml和core-site.xml 放到hbase/conf下,让hbase节点知道hdfs的映射关系,也可以在hbase-site.xml中配置

hbase-env.sh

  1. JAVA_HOME
  2. HBASE_MANAGES_ZK设置为false,使用外部的zk
  3. HBASE_CLASSPATH设置为hadoop配置文件的目录
  4. HBASE_PID_DIR
  5. HBASE_LOG_DIR

hbase-site.xml

<configuration>
<property>
<name>hbase.rootdir</name>
<value>hdfs://ns1/hbase</value>
</property>
<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>
<property>
<name>hbase.zookeeper.quorum</name>
<value>hadoop4:2181,hadoop5:2181,hadoop16:2181</value>
</property>
<property>
<name>hbase.master</name>
<value>hadoop11</value>
</property>
<property>
<name>zookeeper.session.timeout</name>
<value>6000000</value>
</property>
</configuration>

在regionservers中添加各个子节点的主机名并把zoo.cfg 拷贝到hbase的conf目录下

使用scp将配置好的hbase拷贝到集群的各个节点上,在hadoop1上通过hbase/bin/start-hbase.sh来启动

Spark

安装scala

将scala包解压到/usr/local下,配置环境变量即可

上传spark包到/usr/local/bigdata下并解压缩

进入conf目录,修改slaves,将各个子节点的主机名加入

spark-env.sh

  1. SPARK_MASTER_IP:master主机名
  2. SPARK_WORKER_MEMORY:子节点可用内存
  3. JAVA_HOME:java home路径
  4. SCALA_HOME:scala home路径
  5. SPARK_HOME:spark home路径
  6. HADOOP_CONF_DIR:hadoop配置文件路径
  7. SPARK_LIBRARY_PATH:spark lib目录
  8. SCALA_LIBRARY_PATH:值同上
  9. SPARK_WORKER_CORES:子节点的可用核心数
  10. SPARK_WORKER_INSTANCES:子节点worker进程数
  11. SPARK_MASTER_PORT:主节点开放端口
  12. SPARK_CLASSPATH:其他需要添加的jar包路径
  13. SPARK_DAEMON_JAVA_OPTS:”-Dspark.storage.blockManagerHeartBeatMs=6000000”
  14. SPARK_LOG_DIR:log目录
  15. SpARK_PID_DIR:pid目录

spark配置详见:
Spark 配置

将hadoop1上配置好的spark和scala通过scp复制到其他各个节点上(注意其他节点上的~/.bash_profle文件也要配置好)

通过spark/sbin/start-all.sh启动

Hue

安装hue要求有maven环境和其他环境,具体见:

  • ant
  • asciidoc
  • cyrus-sasl-devel
  • cyrus-sasl-gssapi
  • gcc
  • gcc-c++
  • krb5-devel
  • libtidy (for unit tests only)
  • libxml2-devel
  • libxslt-devel
  • make
  • mvn (from maven package or maven3 tarball)
  • mysql
  • mysql-devel
  • openldap-devel
  • python-devel
  • sqlite-devel
  • openssl-devel (for version 7+)

上传hue的安装包到/usr/local/bigdata,解压缩并进入目录,执行:

make apps

进行编译,期间会下载各种依赖包,如果默认中央仓库的地址链接太慢可以换成CSDN的中央仓库:
修改maven/conf/settings.xml,在中添加:

<profile>
<id>jdk-1.4</id>
<activation>
<jdk>1.4</jdk>
</activation>
<repositories>
<repository>
<id>nexus</id>
<name>local private nexus</name>
<url>http://maven.oschina.net/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>nexus</id>
<name>local private nexus</name>
<url>http://maven.oschina.net/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</profile>

如果还是出现相关依赖的错误,可以尝试修改hue/maven/pom.xml,将

2.3.0-mr1-cdh5.0.1-SNAPSHOT

编译成功之后进入hue/desktop/conf修改pseudo-distributed.ini配置文件:

# web监听地址
http_host=0.0.0.0
# web监听端口
http_port=8000
# 时区
time_zone=Asia/Shanghai
# 在linux上运行hue的用户
server_user=hue
# 在linux上运行hue的用户组
server_group=hue
# hue默认用户
default_user=hue
# hdfs配置的用户
default_hdfs_superuser=hadoop

# hadoop->hdfs_clusters->default的选项下
# hdfs访问地址
fs_defaultfs=hdfs://ns1
# hdfs webapi地址
webhdfs_url=http://hadoop1:50070/webhdfs/v1
# hdfs是否使用Kerberos安全机制
security_enabled=false
# hadoop配置文件目录
umask=022
hadoop_conf_dir=/usr/local/bigdata/hadoop/etc/hadoop

# hadoop->yarn_clusters->default的选项下
# yarn主节点地址
resourcemanager_host=hadoop1
# yarn ipc监听端口
resourcemanager_port=8032
# 是否可以在集群上提交作业
submit_to=True
# ResourceManager webapi地址
resourcemanager_api_url=http://hadoop1:8088
# 代理服务地址
proxy_api_url=http://hadoop1:8088

# hadoop->mapred_clusters->default的选项下
# jobtracker的主机
jobtracker_host=hadoop1

# beeswax选项下(hive)
# hive运行的节点
hive_server_host=zx-hadoop1
# hive server端口
hive_server_port=10000
# hive配置文件路径
hive_conf_dir=/usr/local/bigdata/hive/conf
# 连接超时时间等
server_conn_timeout=120
browse_partitioned_table_limit=250
download_row_limit=1000000


# zookeeper->clusters->default选项下
# zk地址
host_ports=hadoop4:2181,hadoop5:2181,hadoop6:2181

# spark选项下
# spark jobserver地址
server_url=http://hadoop1:8090/

这里hue只配置了hadoop,hive(连接到spark需要部署spark jobserver)其余组件需要时进行配置即可。

进入hive目录执行启动metastrore和hiveserver2服务(如果已经启动就不需要了):

bin/hive --service metastore
bin/hiveserver2

进入hue,执行:

build/env/bin/supervisor 

进入hadoop:8000即可访问到hue的界面

相关的异常信息

1、hue界面没有读取hdfs的权限

错误现象:使用任何用户启动hue进程之后始终无法访问hdfs文件系统。
异常提示:WebHdfsException: SecurityException: Failed to obtain user group information:
pache.hadoop.security.authorize.AuthorizationException: User: hue is not allowed to impersonate admin (error 401)
原因分析:用户权限问题。
解决方案:需要在hue的配置文件中设置以hue用户启动web进程,并且该用户需要在hadoop用户组中。

2、hue界面无法获取hdfs信息

错误现象:使用任何用户启动hue进程之后始终无法访问hdfs文件系统。
异常提示:not able to access the filesystem.
原因分析:hue通过hadoop的web api进行通讯,无法获取文件系统可能是这个环节出错。
解决方案:在pdfs-site.xml文件中添加dfs.webhdfs.enabled配置项,并重新加载集群配置!

使用rsync进行集群文件同步

参考:使用rsync进行多服务器同步

集群端口一览表

端口名用途
50070Hadoop Namenode UI端口
50075Hadoop Datanode UI端口
50090Hadoop SecondaryNamenode 端口
50030JobTracker监控端口
50060TaskTrackers端口
8088Yarn任务监控端口
60010Hbase HMaster监控UI端口
60030Hbase HRegionServer端口
8080Spark监控UI端口
4040Spark任务UI端口
9000HDFS连接端口
9090HBase Thrift1端口
8000Hue WebUI端口
9083Hive metastore端口
10000Hive service端口

不定时更新。

有时候各个集群之间,集群内部各个节点之间,以及外网内网等问题,如果网络组策略比较严格的话,会经常要求开通端口权限,可以参考这个表的内容,以免每次都会漏过一些端口影响效率。

其他一些可用技能

集群中的datanode出现数据分布不均匀的时候可以用hadoop的balancer工具将数据打散

# 进行数据的balancer操作,直到该节点的磁盘使用率低于集群的平均使用率的15%
bin/start-balancer.sh -threshold 15

检查hdfs中出现损坏的block块

bin/hadoop fsck file -blocks -files -locations

作者:@小黑

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐