大数据的软件通常运行在环境一致、配置规范的集群环境中,允许底层硬件型号和规格的不同,但要充分做好规划和利用, 在软件层面尽量保证环境的一致性,仍然可以避免很多因为环境配置随意、不匹配带来的问题,也可以使问题的定位及处理更加高效,当前页面列出了大数据集群应该保持一致的通用基础或基础配置,有些是需要在集群规划阶段就要提前考虑到的点,能够节省后期不必要的调整,也可以作为对集群的checklist,方便调整配置。
集群的操作系统版本应该保持一致,例如都是CentOS或者都是Ubuntu,不同的发行版的程序包和配置方式都有所不同,为了避免不必要的配置成本,要求集群所有的操作系统环境一致。
单个集群的机器应分布在相同的网络环境中,所有节点的网络带宽、延迟应基本一致,推荐使用万兆网络,大数据系统对网络依赖比较大,良好的网络环境可以是集群正常运行的前提,在部署环境之前,建议使用iperf3
工具对网络带宽进行测试,确保网络和预期的一致。
下载iperf3
的rpm包,适用于CentOS x86
环境:
假如有两个节点分别为:node1
和node2
,测试带宽的方法是:
node1
上运行iperf3
服务:iperf3 -s
node2
上运行iperf3
客户端连接node1
上的服务进行测试:iperf3 -c node1
运行之后会报告带宽的情况。
其他系统版本的iperf工具下载:iperf download
集群之间的网络要保持畅通,如果开启了防火墙,建议将集群所有节点的ip加入到允许列表中,不建议使用端口号限制,端口号不确定而且临时添加较为繁琐。
每个机器要配置有意义的主机名,并且每个机器的/etc/hosts文件中都应该存在全部机器的列表,例如有如下3个机器:
192.168.0.10
, 192.168.0.11
, 192.168.0.12
需要先为每个机器设置主机名,假设按照上面的顺序分别为:node1
,node2
,node3
:
# 在192.168.0.10上执行
hostnamectl set-hostname node1
# 在192.168.0.11上执行
hostnamectl set-hostname node2
# 在192.168.0.12上执行
hostnamectl set-hostname node3
hostnamectl
工具是systemd
系列集合的一种,可以方便对主机名修改,修改后可以执行hostnamectl
查看当前的主机名。
然后编写hosts文件如下:
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
# 添加机器和ip列表
192.168.0.10 node1
192.168.0.11 node2
192.168.0.12 node3
其中最上面两行是系统自带的,需要保留,下面3条是需要手动添加的,每个机器的/etc/hosts
的文件内容都需要同步修改保持一致。
主机名本身就是域名,所以命名需要符合域名的规范,可以参考RFC 1035,不论何种规范必须保持统一,例如可以使用UN/LOCODE-项目名-机器编号
的方式命名,UN/LOCODE是通用的地点名称编码,机器编号可以是ip地址最后部分也可以是自定义的编号,例如:snz-fusion-21
,可以采用破折号-
或者点.
分割,切勿出现下划线_
,否则部分应用不认识会报错,不建议使用简拼地名,容易混淆,例如sz无法区分是深圳还是苏州。
一些大数据组件例如Hadoop,在启动停止或者运行时,都会通过SSH协议登录集群中的其他机器执行一些命令,这个时候就需要配置SSH免密登录或者SSH互信,才可以正常对集群进行管理,还是假设有3台机器,分别为node1
、node2
、node3
,假设主机名和hosts文件都已经配置正确,然后我们在所有机器上都操作生成密钥对,包括公钥和私钥:
# 所有节点都要执行一次{node1,node2,node3}
ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa
执行之后会在~/.ssh
下生成两个文件,分别是私钥id_rsa
和公钥id_rsa.pub
,私钥不要泄露只需要将公钥追加到对方节点的验证列表即可,上面如果为了方便想简化配置,也可以只在1个节点生成密钥,然后所有节点都相同即可。
然后在所有机器执行下面命令:
# 所有节点都要执行一次{node1,node2,node3}
# 都将自己的公钥发送至node1的authorized_keys中 这步操作需要输入密码
ssh-copy-id -i ~/.ssh/id_rsa.pub node1
这样操作的目的是让node1
节点的authorized_keys
中保存集群所有的公钥,然后再将node1
中的authorized_keys
文件同步至集群其他的节点,这样就可以实现整个集群中所有节点的两两互信:
# 在node1执行, 将authorized_keys文件发送至集群中所有其他节点 发送时均需要输入密码
scp ~/.ssh/authorized_keys node2:~/.ssh/
scp ~/.ssh/authorized_keys node3:~/.ssh/
这样操作之后,集群中node1
、node2
、node3
两两之间都可以实现免密登录了,注意第一次登录时需要输入yes
确认。
添加节点操作
如果此时集群中加入1个节点node4
,首先应该配置好node4
的主机名并且更新集群所有节点的hosts文件,这个不再详细叙述,然后要实现免密首先要在新加节点上生成公钥私钥,并将公钥发送至集群中原有的1个节点:
# 在node4上执行 生成密钥对
ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa
# 在node4上将密钥对同步至node1 需要输入密码
ssh-copy-id -i ~/.ssh/id_rsa.pub node1
此时node1
上面的公钥是全的,只需要再次同步到集群全部节点(包括新节点)即可:
# 在node1执行, 将authorized_keys文件发送至集群中所有其他节点 已经免密的节点不需要输入密码
scp ~/.ssh/authorized_keys node2:~/.ssh/
scp ~/.ssh/authorized_keys node3:~/.ssh/
# 发送到新加节点node4时需要输入密码
scp ~/.ssh/authorized_keys node4:~/.ssh/
现在新加的节点和集群中所有原有节点都可以实现免密了。
Hadoop生态中绝大部分组件都是采用Java或者JVM语言进行开发,所以Java环境已经成为部署大数据组件的基础配置,所以集群开始时就需要安装版本一致的Java环境,可以选择OpenJDK
也可以选择Oracle JDK
,有些系统发行版例如CentOS
安装时已经选择了JDK环境,这种情况下是不需要额外再进行安装的,检查Java环境是否存在可以使用:
java -version
像这种情况安装的就是OpenJDK环境。
目前安装Java环境要求是1.8.x
版本。
JAVA_HOME
环境变量设置:
对于OpenJDK来说,通常使用yum
或者apt
包管理工具安装,在/usr/lib/jvm
下有对应的安装目录,使用ll /usr/lib/jvm
查看:
所以这里就可以设置为:
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
当然OpenJDK安装时会在系统的PATH下生成对应的可执行文件链接,所以不需要配置环境变量,只在需要的时候设置JAVA_HOME
即可。
如果是OracleJDK,是采用二进制包的方式解压安装,这个可以自定义指定位置,例如/usr/local/jdk1.8.0_232
,需要在/etc/profile
或者~/.bashrc
中配置环境变量如下:
export JAVA_HOME=/usr/local/jdk1.8.0_232
export PATH=$PATH:$JAVA_HOME/bin
这样就可以正常使用java相关命令了。
无论是OpenJDK还是OracleJDK,在大数据组件中如果需要JAVA_HOME
变量时都需要单独进行配置。
OpenJDK和OracleJDK只能存在1个,同时安装会带来不可预知的问题!
大数据中的某些软件例如HBase
对时钟同步性依赖比较强,如果集群中节点时间偏离过大,可能导致系统不稳定或者服务终止,时钟同步通常依赖ntp
服务,在不同的Linux发行版会有所不同,例如在CentOS 7.x
中采用ntp
,在CentOS 8.x
中采用chrony
,而对于Ubuntu/Debian
较新的发行版中,时间同步的客户端依赖一个默认的系统服务systemd-timesyncd.service
进行,只需要简单配置一下时间服务器即可,所以不同发行版的配置是不一样的。
在配置ntp服务之前,首先要确保所有节点的时区完全一致,国内的时区建议都配置为:Asia/Shanghai
:
# 所有节点设置统一时区
timedatectl set-timezone Asia/Shanghai
# 查看当前设置
timedatectl
设置时区后可以继续配置ntp时钟同步服务,这里以CentOS 7.x
为例,在服务侧需要配置server以及允许客户端的列表,也就是说ntp服务端其实也是客户端,也需要从其他时间服务器同步数据,编辑/etc/ntp.conf
配置如下:
server 0.centos.pool.ntp.org iburst
server 1.centos.pool.ntp.org iburst
server 2.centos.pool.ntp.org iburst
server 3.centos.pool.ntp.org iburst
# 如果是离线状态也可以配置为自己本身
server 127.127.1.0
fudge 127.127.1.0 stratum 10
# 配置限制的主机列表
# 默认允许本机
restrict 127.0.0.1
restrict ::1
# 根据实际的集群新增
restrict 192.168.1.0 mask 255.255.255.0 nomodify notrap
然后保存配置并启动ntp服务:
systemctl start ntpd
# 设置开机自启动
systemctl enable ntpd
# 查看服务状态
systemctl status ntpd
然后在客户端同样编辑/etc/ntp.conf
配置要同步的服务器:
# 192.168.1.10是刚才时间服务节点的ip
server 192.168.1.10
# 同步时间间隔范围 6表示2的6次方秒即64s, 10表示1024s
minpoll 6
maxpoll 10
然后保存配置文件,同样启动ntp服务:
systemctl start ntpd
# 设置开机自启动
systemctl enable ntpd
# 查看服务状态
systemctl status ntpd
查看同步状态:
ntpstat
# 或者
ntpq -np
ntpq
工具用来查看和时间服务器的同步状态,参数表示为:
-n
:表示对源地址按照ip格式输出,默认是输出的主机名。
-p
: 打印对等节点以及状态摘要。
上面是在CentOS 7.x
发行版上基于ntp
对时钟同步的简要配置,其他Linux发行版的后续如有必要会继续补充。
注意ntp服务端如果有防火墙则必须开放服务允许客户端访问,如果是firewall
工具可以按照例如:firewall-cmd --add-service=ntp --permanent && firewall-cmd --reload
的方式添加。
大数据软件对资源利用的要求比较高,而系统有些默认参数无法满足需求,所以要调整至合适的值以提升性能,同时不同的框架或系统对参数的要求也不一样,在这里仅抽出一些比较通用的进行配置,其余的在专门的页面中单独介绍。
程序同时打开过多的文件时,会抛出常见的错误Too many open files.
,原因就是系统对进程所能打开的文件数量进行了限制,查看当前的文件数量限制:
ulimit -n
默认的数量是1024,ulimit
也可以查看其它全部的限制参数:
ulimit -a
其中包括文件大小、栈大小以及最大进程数等。
临时调大当前的文件数可以使用:
ulimit -n 65535
这个调整是临时的,当前会话被断开后也就失效了,只有在当前会话断开之前启动的进程才有效。
进程实际的运行状态保存在/proc/<pid>
目录中,其中/proc/<pid>/limits
是当前正在运行的进程所受到的限制,即使修改了最大文件数,也要确认进程实际的状态是否已经生效,例如:
# 查看pid为16891的进程limits
cat /proc/16891/limits
那么想实现用户会话建立后最大文件数自动生效,有下面两种配置方法。
在使用SSH连接时,如果开启PAM策略,就可以实现一系列的限制,例如登录失败次数限制、会话保持时长限制等,当然也包括最大文件数等资源的限制,可以编辑SSH的配置文件/etc/ssh/sshd_config
确认是否开启PAM:
UsePAM yes
确认开启后可以查看PAM关于登录的配置/etc/pam.d/login
确认其中以及include
的相关文件中,是否存在如下的配置:
session required pam_limits.so
默认这个配置都会存在的。
最后编辑配置文件/etc/security/limits.conf
,增加如下配置:
# *表示设置所有的用户的文件数 (注意: root用户除外)
* soft nofile 1000000
* hard nofile 1000000
# 设置root用户的文件数
root soft nofile 1000000
root hard nofile 1000000
注意有些发行版root用户需要单独配置,只配置*
是匹配不到的,文件数建议设置为100万。
注意:最大文件数的设置绝对不能超过内核参数fs.nr_open
的设置,默认这个值在Linux内核代码中被定义为1048576,设置先一定要通过sysctl fs.nr_open
确认该参数的值,超出这个值会报错最终导致无法登录系统,只能通过救援方式修改回来。
关于fs.nr_open
在Linux源码的fs/file.c
中有定义:
unsigned int sysctl_nr_open __read_mostly = 1024*1024;
unsigned int sysctl_nr_open_min = BITS_PER_LONG;
/* our min() is unusable in constant expressions ;-/ */
#define __const_min(x, y) ((x) < (y) ? (x) : (y))
unsigned int sysctl_nr_open_max =
__const_min(INT_MAX, ~(size_t)0/sizeof(void *)) & -BITS_PER_LONG;
这个值默认是1024*1024也就是1048576,并且最大值受限于sysctl_nr_open_max的值,这个值结果是2147483584,当设置超过这个值的时候也会报错。
在较新的Linux发行版中,systemd的版本也比较新,那么fs.nr_open
的值会被修改为1073741816。
总之这个fs.nr_open
内核参数不需要修改,只需要在设置之前确认不要超过即可。
保存/etc/security/limits.conf
后关掉当前shell客户端再重新连接查看确认生效。
可以通过环境变量配置文件如:/etc/profile
、~/.bashrc
或者~/.bash_profile
等环境变量配置文件来设置,添加内容如下:
ulimit -HSn 1000000
其中参数-H
和-S
分别指定硬限制和软限制。
保存后再次重新连接shell确认参数是否修改。
systemd管理的进程不受上面配置方式的影响,由具体的systemd独立的参数配置,上面设置的参数只应用于当前会话中直接启动的进程。
进程的VMA(虚拟内存区域),其实就是进程通过mmap等系统调用创建的虚拟内存空间,当然也包括文件映射I/O,但是操作系统默认对进程所能使用的虚拟内存数量是有限制的,默认值是65530,可以通过命令查看当前的值:
sysctl vm.max_map_count
显然这个值在很多大数据的系统中是比较小的,所以需要调大,这里设置为 2048000:
sysctl -w vm.max_map_count=2048000 >> /etc/sysctl.conf
设置默认是临时生效,所以在设置的同时添加-w
参数输出到/etc/sysctl.conf
之后下次开机也会自动生效了。
从文件中读取当前设置的参数可以使用-p
:
sysctl -p
交换分区是磁盘上的一块空间,可以在物理内存的空间不足时,将一些不太常用的页面换出到交换分区,从而支持更多的进程运行,但是交换分区一旦使用频繁系统运行将被严重拖慢,当我们查看内核进程kswapd0
的占用比较高,说明内存已经开始换入换出了,需要排查是哪个进程占用了大量的内存,是内存确实不够用还是应用程序设计缺陷导致,现在服务器的内存通常都比较大,为了保证运行的性能,建议将交换分区关闭掉或者降低交换分区的使用倾向,通过调整内核参数vm.swappiness
实现:
sysctl -w vm.swappiness=0 >> /etc/sysctl.conf
# 查看修改的文件内容
sysctl -p
默认vm.swappiness
的值为60,很容易就会使用交换分区,调整为0之后就可以降低交换分区的使用,如果最后内存确实不够用,操作系统仍然会使用交换分区,但是对物理内存的使用会激进一些,如果当前交换分区已经被占用可以通过重新开启交换分区来完成清理:
swapoff -a && swapon -a
free -h
这样就可以清理掉swap空间了。