1. 为什么集群搭建的第一步不是装软件而是"清场"
很多人拿到"搭建Hadoop集群"这个任务,第一反应是赶紧找安装包、敲命令、启动进程。我在早期也这么干过,结果就是集群跑起来之后各种诡异问题:节点之间互相不认识、时间戳对不上导致任务莫名失败、防火墙把心跳包拦掉让节点频繁掉线。折腾了两天才发现,根子全在环境准备阶段没做干净。
所以这篇内容的核心不是教你敲哪条安装命令,而是把集群环境准备这件事讲透。它适合两类人:一是第一次接触分布式集群、准备在CentOS 7上搭一套实验环境的同学;二是搭过单机伪分布式、但没真正处理过多节点协同问题的开发者。环境准备做扎实了,后面装Hadoop、配YARN、跑MapReduce才会顺,否则你会在各种"看起来跟Hadoop无关"的地方反复卡壳。
这里说的"清场",具体指四件事:主机名与网络身份的统一、节点间的信任关系、时间基准的一致、以及系统层面的干扰项清理。这四件事任何一件没做好,集群都会以你意想不到的方式出问题。下面我按实际操作顺序,把每一步的原理、命令和踩坑点都拆开讲。
2. 集群规划:先想清楚几台机器各干什么
2.1 角色划分不是随便分的
在动手改任何配置之前,得先把集群的拓扑定下来。Hadoop集群里主要有这么几个角色:NameNode(管理文件系统元数据)、DataNode(存实际数据块)、ResourceManager(管计算资源调度)、NodeManager(单节点资源代理)、SecondaryNameNode(辅助合并元数据,注意它不是NameNode的备份)。
实验环境常见的做法是准备三台机器。一台做Master,承担NameNode和ResourceManager;另外两台做Slave,跑DataNode和NodeManager。SecondaryNameNode可以放在Master上,也可以单独放一台,实验环境放Master上够用。为什么是三台而不是两台?因为两台的集群体现不出"多节点协同"的真实感,副本机制、数据均衡这些特性很难观察到;而三台是能观察到分布式行为的最小规模。
我建议在规划阶段就用一张表把角色和主机名对应关系写清楚,避免后面配置时张冠李戴:
| 主机名 | IP地址(示例) | 承担角色 |
|---|---|---|
| master | 192.168.100.10 | NameNode、ResourceManager、SecondaryNameNode |
| slave1 | 192.168.100.11 | DataNode、NodeManager |
| slave2 | 192.168.100.12 | DataNode、NodeManager |
注意:IP地址用你自己实验环境的网段,我这里用的是一个常见的私有网段示例,不要照抄,否则可能和你现有网络冲突。
2.2 主机名规划里藏着的坑
主机名这件事看起来最简单,其实最容易埋雷。Hadoop内部大量使用主机名来标识节点,如果主机名和IP的映射关系不稳定,会出现"节点启动了但集群里看不到"的情况。
规划时遵守两条:第一,主机名用纯小写字母加数字,不要用下划线、不要用大写、不要用中文,因为部分组件对主机名字符有严格校验;第二,每台机器的主机名要和hosts文件里的记录完全一致,一个字符都不能差。我见过有人主机名设成Master,hosts里写的是master,结果NameNode启动时报"无法解析主机",排查了半天。
3. 网络身份统一:主机名与hosts文件的正确改法
3.1 修改主机名的两种方式及区别
CentOS 7改主机名有两种方式,效果不一样,得搞清楚用哪个。
第一种是临时修改,命令是hostname 新名字,重启就失效,只适合临时测试。第二种是永久修改,用hostnamectl set-hostname 新名字,这个命令会同时更新静态主机名,重启后依然生效。实际操作中我建议直接用hostnamectl,改完执行hostnamectl status确认一下,能看到"Static hostname"那一行变成了你设置的名字就对了。
改完主机名后,当前终端的提示符不会立刻变,需要重新登录或者执行bash开一个新shell才会刷新。这不是没生效,别被这个现象骗了。
3.2 hosts文件为什么必须三台机器都改
/etc/hosts文件的作用是把主机名解析成IP。在实验环境里我们通常没有内网DNS服务器,所以必须靠hosts文件来做解析。关键在于:三台机器(包括Master自己)的hosts文件内容必须完全一致,都要包含所有节点的映射。
为什么Master自己也要写?因为NameNode在启动时会解析自己的主机名,如果本机hosts里没有自己的记录,它可能解析失败或者解析到一个奇怪的地址。为什么三台要一致?因为任何一台机器都可能需要访问其他任意一台,解析表不全会导致单向可达、单向不可达的诡异现象。
具体操作是在每台机器的/etc/hosts末尾追加:
192.168.100.10 master 192.168.100.11 slave1 192.168.100.12 slave2改完之后,在每台机器上分别执行ping master、ping slave1、ping slave2,三个都能通才算过关。这里有个细节:ping的时候看返回的IP是不是你hosts里写的那个,如果返回的是别的地址,说明系统里有其他解析规则在干扰,需要排查。
3.3 网络连通性验证不能只看ping
ping通只代表ICMP协议可达,不代表Hadoop需要的端口能通。Hadoop各组件之间通信依赖一堆TCP端口,比如NameNode的8020、ResourceManager的8032等等。环境准备阶段虽然还没装Hadoop,但可以先用telnet或者nc测试一下基础连通性。
我的习惯是在Master上对每个Slave执行一次端口探测,确认网络层没有拦截。如果实验环境里开了防火墙,这一步就会暴露问题。关于防火墙的处理,后面单独讲。
4. 免密登录:让节点之间"互相信任"
4.1 为什么集群需要免密登录
Hadoop的启动脚本(比如start-dfs.sh)在Master上执行时,需要远程登录到各个Slave去启动对应的进程。如果每次都要输密码,脚本就没法自动化执行。所以必须配置SSH免密登录,让Master能无密码登录到所有Slave,同时Master也要能免密登录自己。
这里要澄清一个常见误解:免密登录不是"所有节点两两互免",而是"Master能免密到所有节点(含自己)"就够了。Slave之间不需要互相免密,因为启动脚本是从Master发起的。当然,如果你想让Slave也能免密到其他节点,多配一份也无妨,但实验环境没必要。
4.2 生成密钥对与分发的完整流程
第一步,在Master上生成密钥对:
ssh-keygen -t rsa -b 4096执行后会问保存路径,直接回车用默认的~/.ssh/id_rsa;然后问是否设置密码短语,这里必须直接回车留空,否则每次登录还是要输密码,免密就白配了。-b 4096是指定密钥长度,比默认的2048更安全,实验环境用2048也行,但4096也不费事。
第二步,把公钥分发到所有节点(包括Master自己):
ssh-copy-id master ssh-copy-id slave1 ssh-copy-id slave2ssh-copy-id会自动把公钥追加到目标机器的~/.ssh/authorized_keys里,并设置好权限。如果目标机器的.ssh目录不存在,它会自动创建。这一步会要求输入目标机器的密码,输一次就行。
第三步,验证。在Master上依次执行ssh master、ssh slave1、ssh slave2,如果都不需要密码就能登录进去,说明配置成功。第一次登录会问"是否信任该主机",输入yes即可。
4.3 免密登录失败的三个高频原因
配免密登录失败是新手最常见的卡点,我总结下来主要是三个原因。
第一个是权限问题。SSH对.ssh目录和authorized_keys文件的权限极其敏感,目录必须是700,文件必须是600。如果权限过宽,SSH会直接拒绝使用这个密钥。修复命令是chmod 700 ~/.ssh和chmod 600 ~/.ssh/authorized_keys。
第二个是密钥分发到了错误的用户。ssh-copy-id默认分发到目标机器的当前用户名下。如果你在Master上用root操作,但Slave上想用普通用户,就会对不上。解决办法是明确指定用户,比如ssh-copy-id 用户名@slave1。
第三个是SELinux在捣乱。CentOS 7默认开启SELinux,它可能阻止SSH读取密钥文件。如果权限都对了还是不行,可以临时把SELinux设为宽容模式测试:setenforce 0。如果这样就好了,说明是SELinux的问题,需要永久关闭(后面讲)。
5. 时间同步:被严重低估的集群稳定基石
5.1 时间不一致会引发什么后果
这一节我要重点讲,因为时间同步是环境准备里最容易被跳过、但后果最严重的一环。
Hadoop集群里,各个节点会互相发送心跳、记录日志、协调任务。如果节点之间的时间差太大,会出现这些问题:任务调度器认为某个节点的心跳"过期"了,把节点标记为失联;日志时间戳错乱,排查问题时完全理不清先后顺序;某些基于时间戳的一致性校验直接失败。我遇到过时间差了十几分钟导致DataNode反复被踢出集群的情况,查了半天才定位到是时间问题。
所以,集群所有节点的时间必须保持一致,误差控制在秒级以内。
5.2 用chrony做时间同步的实操
CentOS 7自带chrony作为时间同步工具(老版本用的是ntpd)。配置思路是:选一台机器作为时间源(通常就是Master),其他节点从Master同步时间。
在Master上,编辑/etc/chrony.conf,确保它作为服务端允许其他节点同步。关键配置是允许内网网段访问:
allow 192.168.100.0/24 local stratum 10allow指定允许哪些网段来同步,local stratum 10表示即使Master自己没连上外部时间源,也把自己当作一个可用的时间源对外提供服务。这在纯内网实验环境里很关键,因为实验机器往往连不上外网时间服务器。
在Slave上,编辑/etc/chrony.conf,把时间源指向Master:
server master iburstiburst表示启动时快速发送几个包来加速同步。改完后重启chrony服务:systemctl restart chronyd,并设置开机自启:systemctl enable chronyd。
验证同步效果用chronyc sources,能看到Master那一行前面有个^*符号就说明同步成功了。再用date命令对比三台机器的时间,应该基本一致。
5.3 时间同步的常见误区
有个误区是"我手动用date命令把三台机器时间设成一样就行了"。手动设置只能保证那一刻一致,机器运行久了时钟会漂移,几天后可能又差出好几秒。所以必须用chrony这类服务持续同步,不能靠手动。
另一个误区是只配了Slave同步Master,忘了Master自己也需要一个时间基准。如果Master的时间本身在漂移,所有Slave跟着一起漂,集群内部虽然"相对一致",但和外部系统交互时(比如读取带时间戳的数据文件)就会出问题。所以Master最好也配一个上游时间源,实在没有就用local stratum把自己当基准。
6. 防火墙与SELinux:该关的关,该放的放
6.1 实验环境为什么建议直接关防火墙
Hadoop集群内部通信涉及的端口非常多,NameNode、DataNode、ResourceManager、NodeManager、JobHistoryServer等等,每个组件都监听若干端口。在实验环境里,逐个开放端口既繁琐又容易漏,所以我通常建议直接把防火墙关掉。
关闭命令是:
systemctl stop firewalld systemctl disable firewalldstop是立即停止,disable是禁止开机自启,两个都要执行,否则重启后又开了。
注意:这里说的是实验环境。如果是生产环境,绝对不能一关了之,必须按最小权限原则精确开放所需端口。这个区别要拎清楚,别把实验环境的偷懒做法带到生产里去。
6.2 SELinux的处理方式
SELinux是CentOS的安全增强模块,它会限制进程能访问哪些文件、能绑定哪些端口。Hadoop的很多操作会触发SELinux的拦截,表现为"权限明明对,但就是访问不了"。
处理方式是修改/etc/selinux/config文件,把SELINUX=enforcing改成SELINUX=disabled,然后重启机器生效。临时生效可以用setenforce 0,但重启后会恢复,所以配置文件必须改。
改完用getenforce命令验证,输出Disabled就对了。这里要提醒一句:SELinux关闭后需要重启才彻底生效,别改完配置文件就直接往下走,否则可能还是遇到拦截。
6.3 一个容易被忽略的干扰项:swap
除了防火墙和SELinux,还有一个干扰项是swap分区。Hadoop在处理大数据时对内存和磁盘的交互很敏感,swap可能导致性能剧烈波动,甚至让节点被误判为不健康。实验环境里建议把swap关掉。
临时关闭用swapoff -a,永久关闭需要注释掉/etc/fstab里swap那一行。关掉之后用free -h确认swap那一行都是0。
7. JDK安装:版本选择与路径规范
7.1 为什么JDK版本要卡得这么死
Hadoop是用Java写的,运行离不开JDK。但JDK版本不是随便装一个就行,Hadoop对JDK版本有明确要求。以Hadoop 3.x为例,它要求JDK 8,而且对具体的小版本也有偏好。装JDK 11或更高版本,可能会遇到各种兼容性报错,比如某些内部API被移除导致的NoSuchMethodError。
所以我的建议是:先确定你要装的Hadoop版本,再根据它的官方文档选对应的JDK版本。不要先装JDK再选Hadoop,顺序反了容易返工。实验环境里Hadoop 3.x配JDK 8是最稳的组合。
7.2 安装路径的规范与多节点一致性
JDK要装在所有节点上,而且安装路径必须完全一致。为什么?因为Hadoop的配置文件里会写死JAVA_HOME的路径,如果各节点路径不同,配置就没法统一。
我习惯把JDK装在/usr/local/jdk这样的固定路径下,所有节点都用同一个路径。安装方式可以用包管理器(yum install),也可以下载压缩包手动解压。手动解压的好处是路径完全可控,不受包管理器默认路径的影响。
装完后配置环境变量,编辑/etc/profile,在末尾加上:
export JAVA_HOME=/usr/local/jdk export PATH=$JAVA_HOME/bin:$PATH然后执行source /etc/profile让配置生效。用java -version验证,能看到版本信息就说明装好了。这一步同样要在所有节点上做一遍,并且验证每台机器的java -version输出一致。
7.3 环境变量配置的一个细节
有个细节很多人会踩:/etc/profile的修改只对新开的shell生效,当前shell需要source一下。而且如果你是用ssh远程执行命令,非交互式shell可能不会加载/etc/profile,导致找不到java。这种情况可以在~/.bashrc里也加一份,或者用/etc/profile.d/目录下的脚本方式配置,兼容性更好。
8. 环境准备完成后的自检清单
环境准备做完,别急着装Hadoop,先做一轮系统自检。我整理了一份清单,逐项确认能省掉后面大量排查时间。
| 检查项 | 验证命令 | 合格标准 |
|---|---|---|
| 主机名 | hostname | 与规划一致 |
| hosts解析 | ping 各节点名 | 全部能通且IP正确 |
| 免密登录 | ssh 各节点名 | 无需密码直接进入 |
| 时间同步 | chronyc sources | 显示同步源且状态正常 |
| 防火墙 | systemctl status firewalld | 已停止且禁用 |
| SELinux | getenforce | 输出Disabled |
| swap | free -h | swap行为0 |
| JDK | java -version | 各节点版本一致 |
这份清单看着简单,但每一项背后都对应着后面可能出现的具体故障。比如免密登录没配好,start-dfs.sh会卡在输入密码;时间没同步,节点会莫名掉线;SELinux没关,会出现各种"权限对但访问不了"的怪问题。
9. 我在多次搭建中总结的几条经验
最后分享几条从实际操作里攒下来的经验,都是文档里不太会写、但确实能救命的。
第一条,改配置前先备份。/etc/hosts、/etc/profile、/etc/selinux/config这些文件,改之前先cp一份加个.bak后缀。改错了能快速回滚,比重装系统快得多。
第二条,每改完一项就验证一项,不要攒着一起验。环境准备涉及十几个改动点,如果全改完再统一测试,一旦出问题你根本不知道是哪个改动引起的。改一项、验一项,问题定位成本最低。
第三条,三台机器的配置要"复制式"一致。除了主机名和IP不同,其他配置(hosts内容、JDK路径、环境变量、时间源设置)应该尽量保持一致。配置差异越大,出问题的概率越高。我甚至会把一台机器的配置文件改好后,直接scp到其他机器,只改主机名相关的部分。
第四条,记录每一步的操作。环境准备阶段的操作很容易忘,尤其是隔了几天再回来继续搭的时候。我习惯用一个文本文件把执行的命令、改的文件、遇到的问题都记下来,后面装Hadoop出问题时,回头翻记录能快速定位是不是环境准备阶段埋的雷。
环境准备这件事,做的时候觉得繁琐,但它决定了整个集群的地基稳不稳。把这一关过了,后面装Hadoop、配集群、跑任务会顺畅很多。下一篇我会接着讲Hadoop的安装和核心配置文件怎么写,那部分才是真正让集群"跑起来"的环节。