云服务器搭建hadoop集群思路与报错整理

我的版本:hadoop:3.2.3 jdk: 11 centOS:7.6

建议在配置之前全部打一个快照方便出错搞混或者解决不了时回滚!为了避免后续启动集群各种各样连接超时,连接错误,禁止访问等问题,需在云服务器商提供的控制台开放所有端口。

大纲

创建hadoop用户与程序准备

创建hadoop用户与主机名配置

我将使用三台云服务器搭建一个一主两从的服务器集群,搭建前先使用xshell或者其他连接工具连接上三台云服务器,选定一台配置较高的服务器当做主服务器(Master),(Master:2核4G,Slave1: 1核2G,Slave2:1核2G)。先配置Master在配置其他两台从机。

租服务器时不做设置登录上都是root用户,在xshell上执行命令

1
useradd -m hadoop -s /bin/bash   # 创建新用户hadoop

修改hadoop用户密码,两遍确认

1
passwd hadoop      

为hadoop用户增加管理员权限

1
visudo

编辑页面按下:100然后按下i在root那一行下添加一行hadoop ALL=(ALL) ALL

image-20220525183337888

esc然后:wq保存

在每一台机器创建hadoop用户

配置主机名

为了后续搭建集群和配置更简单直观,改一下主机名,并配置hosts文件。云服务器集群和虚拟机集群的hosts配置有所不同

1
vim /etc/hostname   # 修改主机名

image-20220525184907212

**注:**主服务器改为Master,其他两台为Slave1和Slave2并且不能有空格

配置hosts文件

1
vim /etc/hosts         # 注意每台机器的hosts都不一样

Master的hosts文件追加

1
2
3
内网ip  Master  Master
外网ip Slave1 Slave1
外网ip Slave2 Slave2

内网ip可以通过ifconfig查看(如下192.168.0.4),外网ip即连接xshell的ip

image-20220525185712355

不能出现127.0.0.1 Master这样的记录

Slave1上

1
2
3
内网ip  Slave1  Slave1
外网ip Master Master
外网ip Slave2 Slave2

其他从机同理

重启三台云服务器

重启后即可用xshell连接每台的hadoop用户

image-20220525190341634

在每台机器上ping其他节点看是否成功

image-20220525190550081

没ping通再检查一边配置或者重新配置。

配置ssh免密登录

之后的操作默认都在hadoop用户下操作。

CentOS默认安装有SSH使用命令查看

1
rpm -qa | grep ssh

image-20220525192617321

未安装执行:

1
2
sudo yum install openssh-clients
sudo yum install openssh-server

执行命令测试

1
ssh localhost   # 如果可以登录 使用exit退出

在Master节点生成公钥

1
2
3
cd ~/.ssh               # 如果没有该目录,先执行一次ssh localhost
rm ./id_rsa* # 删除之前生成的公匙(如果有)
ssh-keygen -t rsa # 一直按回车就可以

让Master无密码ssh本机

1
cat ./id_rsa.pub >> ./authorized_keys  # 执行后使用 ssh Master 验证

分发公钥给所有从节点

1
scp ~/.ssh/id_rsa.pub hadoop@Slave1:/home/hadoop/  # 其他从节点同理

在从节点上将ssh公钥授权(Slave1为例)

1
2
3
mkdir ~/.ssh       # 如果不存在该文件夹需先创建,若已存在则忽略
cat ~/id_rsa.pub >> ~/.ssh/authorized_keys
rm ~/id_rsa.pub # 用完就可以删掉了

在Master上测试

1
ssh Slave1   

如果还是连不上,在每台从机上执行如下操作

1
2
3
4
cd ~/.ssh
chmod 700 ../
chmod 700 .
chmod 600 authorized_keys

image-20220525193633677

xsync文件分发脚本(尚硅谷)

1
2
cd ~/bin  # 如果提示找不到路径 先执行mkdir ~/bin再执行cd 命令
vim xsync # 加入下面的脚本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#!/bin/bash

#1. 判断参数个数
if [ $# -lt 1 ]
then
echo Not Enough Arguement
exit;
fi

#2. 遍历集群所有机器
for host in Slave1 Slave2
do
echo ===================== $host =====================
#3. 遍历所有目录,挨个发送

for file in $@
do
#4. 判断文件是否存在
if [ -e $file ]
then
#5. 获取父目录
pdir=$(cd -p $(dirname $file); pwd)

#6. 获取当前文件的名称
fname=$(basename $file)
ssh $host "mkdir -p $pdir"
rsync -av $pdir/$fname $host:$pdir
else
echo $file does not exists!

fi
done
done

保存退出

添加环境变量

1
2
3
chmod 777 xsync # 增加文件可执行权限
vim ~/.bashrc # 添加一行 export PATH=$PATH:/home/hadoop/bin
source ~/.bashrc

如果想在root用户或者其他用户下也能使用,其他环境变量同理

1
2
sudo vim /etc/profile
source /etc/profile

验证

1
2
3
4
5
6
cd ~
xsync bin # 向从节点发送bin目录
ssh Slave1
cd ~
ll # 如果看到bin目录就成功了
exit

如果提示错误信息:rsync common not found

执行如下操作:

1
sudo yum install rsync -y 

安装jdk

下载地址:oracle

在Master上

1
2
cd /usr/local
mkdir devtools # 开发工具目录

下载完成通过把xftp或者其他工具上传压缩包到devtools目录

解压:

1
sudo tar -zvxf jdk-11.0.15.1_linux_bin.tar.gz

添加环境变量(开发环境最好加到全局环境变量里面,所有用户都能使用)

1
2
3
4
5
6
7
8
9
10
11
sudo vim /etc/profile # 增加如下环境变量

# JAVA Environment
export JAVA_HOME=/usr/local/devtools/jdk-11.0.15.1
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export PATH=$PATH:$JAVA_HOME/bin

source /etc/profile # 使生效
# 验证
java -version
echo $JAVA_HOME

分发给所有节点

1
2
cd /usr/local
xsync devtools/ # 分发到节点

在所有从节点上配置JAVA环境变量并验证

安装hadoop

下载地址:镜像站

Master上,上传压缩包到/usr/local目录

1
2
3
4
5
6
7
8
9
10
11
cd /sur/local
sudo tar -zxf hadoop-3.2.3.tar.gz # 解压
sudo mv ./hadoop-3.2.3/ /hadoop # 将文件夹改名
sudo chown -R hadoop:hadoop ./hadoop # 修改文件权限
vim ~/.bashrc # 修改环境变量,添加如下内容
export HADOOP_HOME=/usr/local/hadoop/
export PATH=$PATH:$HADOOP_HOME/bin
export PATH=$PATH:$HADOOP_HOME/sbin

source ~/.bashrc # 别忘了source
hadoop version# 验证是否安装成功

分发:

1
2
cd /usr/local
xsync hadoop/

集群配置

集群部署参考尚硅谷hadoop教程,如下:

Master Slave1 Slave2
HDFS NameNode
DataNode
DataNode SecondaryNameNode
DataNode
YARN NodeManager ResourceManager
NodeManager
JobHistoryServer
NodeManager
SPARK Worker
HistoryServer
Worker Worker

配置文件

在Master上:

workers

1
vim /usr/local/hadoop/etc/hadoop/workers  # 添加内容如下

image-20220525211535417

core-site.xml

1
2
cd /usr/local/hadoop/etc/hadoop
vim core-site.xml

<configuration></configuration>中添加:

1
2
3
4
5
6
7
8
9
10
11
<!-- 指定HDFS中NameNode的地址 -->
<property>
<name>fs.defaultFS</name>
<value>hdfs://Master:9000</value>
</property>

<!-- 指定Hadoop运行时产生文件的存储目录 -->
<property>
<name>hadoop.tmp.dir</name>
<value>/usr/local/hadoop/data</value>
</property>

hdfs-site.xml

1
2
3
cd /usr/local/hadoop/etc/hadoop
vim hadoop-env.sh # 添加如下环境变量
export JAVA_HOME=jdk安装目录
1
vim hdfs-site.xml  # 添加如下
1
2
3
4
5
6
7
8
9
10
11
12
<!-- 指定NameNode的webui端口 -->
<property>
<name>dfs.namenode.http-address</name>
<value>Master:9870</value>
</property>

<!-- 指定SecondaryNameNode的webui端口 -->
<property>
<name>dfs.namenode.secondary.http-address</name>
<value>Slave2:9868</value>
</property>

yarn-site.xml

1
2
3
cd /usr/local/hadoop/etc/hadoop
vim yarn-env.sh
export JAVA_HOME=jdk安装目录
1
vim yarn-site.xml   # 添加如下
1
2
3
4
5
6
7
8
9
10
11
12
<!-- Reducer获取数据的方式 -->
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>

<!-- 指定YARN的ResourceManager的地址 -->
<property>
<name>yarn.resourcemanager.hostname</name>
<value>Slave1</value>
</property>

mapred-site.xml

1
2
3
cd /usr/local/hadoop/etc/hadoop
vim mapred-env.sh
export JAVA_HOME=jdk安装目录
1
vim mapred-site-xml  # 添加如下
1
2
3
4
5
<!-- 指定MR运行在Yarn上 -->
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>

分发配置文件

1
2
cd /usr/local/hadoop/etc
xsync hadoop/

集群启动

关闭每台服务器的防火墙:

1
2
sudo systemctl stop firewalld  # 临时关闭防火墙
sudo systemctl disable firewalld # 防止重启后防火墙启动

在Master上:

1
2
3
4
cd /usr/local/hadoop
hadoop namenode -format # 如果集群没启动过则先执行此格式化再启动
sbin/start-dfs.sh
jps # 查看启动进程情况

image-20220525204738989

**注:**因为我后续配置了Spark历史服务器的原因所以有HistoryServer进程

在Slave1上:

1
2
3
cd /usr/local/hadoop
sbin/start-yarn.sh
jps # 查看进程情况

如果报错permission denied 需要在Slave1上配置Master和Slave2的ssh登录,即在Slave1上生成公钥再在Master和Slave2上给公钥授权

image-20220525204859435

**注:**因为我后续配置了yarn历史服务器的原因所以有JobHistoryServer进程

在Slave2上:

1
jps   # 查看hadoop进程

image-20220525204942832

服务器进程开启情况和预期部署规划一致,证明没有什么问题。

查看ui界面:

**注:**因为我在windows host文件添加了主机IP映射所以用Master:9870可以访问

hdfs ui:

image-20220525205052308

yarn ui

image-20220525210153756

集群关闭

1
2
3
cd /usr/local/hadoop
sbin/stop-yarn.sh # 在Slave1上关闭yarn
sbin/stop-dfs.sh # 在Master上关闭hdfs

报错与处理办法

NameNode启动一段时间就挂掉了(hdfs过一段时间就不能访问了)

jps查看进程信息,发现NameNode没了,cd到/usr/local/hadoop/logs找到namenode的日志查看发下报错信息:

1
ERROR org.apache.hadoop.hdfs.server.namenode.NameNode: RECEIVED SIGNAL 15: SIGTERM

有以下几种可能解决办法:

(1)

1
2
3
cd /usr/local/hadoop
sbin/hadoop-daemon.sh start namenode
hadoop dfsadmin -refreshNodes

(2)

关闭集群,做如下配置,然后重启hadoop:

1
2
3
4
5
6
7
cd /usr/local/hadoop/etc/hadoop
vim hadoop-env.sh # 添加如下内容,根据云服务器配置从上往下调,直到NameNode不会挂

export HADOOP_HEAPSIZE_MAX=1000M
export HADOOP_HEAPSIZE_MIN=100M

xsync hadoop-env.sh

(3)

删除所有节点hadoop目录下的data和logs文件夹,重新进行格式化,启动集群。(没有办法的办法)不要轻易重新格式化因为这可能造成ID不一致,NameNode启动不了(到时候还得再重新格式化)。

(4) 被病毒程序占用系统资源

分析:经StackOverflow这是一个系统问题,并不是hadoop的错误,在hadoop运行过程中系统态cpu占用率太高被系统kill掉了,使用top命令查看cpu使用率一度到了96%,在关闭hadoop集群以后,top查看仍有hadoop用户的进程,并且cpu占用率还高达50%。这个进程kill掉后还会自启,并且pid还会改变。所以可以推断这是遭恶意攻击了。

原因:

可能是之前在用vpn看StackOverflow时,没关闭vpn的情况下直接用xshell连接过服务器导致ip暴露了

解决:

查询正在使用socket的此进程名的直接ip

1
netstat -anp | grep zapppp  # 通过top查看占用资源的进程COMMAND为zapppp

经查,查询到的ip是国外的,禁掉ip

1
iptables -A INPUT -p tcp -s 目标ip -j DROP

程序进程停了一段时间又重启了,关掉pam后门:

Linux留后门

1
sudo yum reinstall pam

还是要自启,关闭定时服务,删除进程对应的目录:

1
2
3
4
5
6
7
crontab -e        # 注释掉所有内容(每行前加一个#)
ps aux | grep zapppp # 拿到pid
ll /proc/pid # 找到进程的绝对路径,如下
cd /home/hadoop/.cache_....
ll # 查看里面有可执行文件
cd ..
rm -rf .cache../ # 删除整个目录

目前暂时没有出现那个进程了,cpu占用率也基本是百分之零点几。

NameNode启动不了

Connection time out / Connection refused

关闭防火墙

1
2
sudo systemctl stop firewalld  
sudo systemctl disable firewalld

启动时报错hadoop0: ERROR: Cannot set priority of datanode process 2518或者其他端口

开启云服务器全部端口

NameNode DataNodeID不一致failed to start namenode

所有节点删除hadoop目录的tmp,data和logs文件夹,重新格式化,启动集群。