资讯动态

虚拟机搭建Zookeeper+Hadoop+HBase三节点集群实战指南

发布时间:2026/10/20 18:40:04 来源:尧图企业网站定制
1. 为什么要在虚拟机里搭这套三件套集群先把结论摆在前面这套组合——Zookeeper Hadoop HBase是很多大数据入门者绕不开的一道坎。你可能是为了跑通一个课程实验可能是为了本地复现一套分布式存储环境也可能是为了给上层的数据分析任务准备一个稳定的底座。不管出于什么目的在单台物理机上用虚拟机搭一套三节点集群是成本最低、容错最高、也最适合反复折腾的方案。我选择 Ubuntu 18.04 作为基础系统不是因为它新恰恰是因为它“旧得刚刚好”。这个版本的内核、glibc、systemd 行为都非常稳定社区里针对它的踩坑记录最全Hadoop 和 HBase 的官方文档也大量以它为参考环境。你换成更新的发行版反而容易在 SSH、主机名解析、Java 版本这些地方遇到意料之外的兼容问题。虚拟机平台用 VMware Workstation理由更直接快照功能太香了。集群搭建过程中你会反复修改配置文件、重启服务、格式化数据目录一旦某一步把环境搞脏了回滚快照比逐条排查快十倍。这套集群能做什么简单说Zookeeper 负责分布式协调Hadoop 的 HDFS 提供底层分布式文件存储YARN 负责资源调度HBase 则在这之上提供列式存储和随机读写能力。三者叠起来你就有了一个可以跑真实分布式程序的迷你环境。适合谁来参考我认为是三类人一是刚接触大数据、需要动手理解“分布式”到底怎么回事的学生或转行者二是需要本地验证 HBase 表结构、RowKey 设计、Region 分裂行为的开发人员三是想在不依赖云服务的前提下把整套链路摸清楚的运维初学者。需要提前说明的是下面所有操作都基于我自己的实践总结涉及的主机名、IP 段、目录路径都是示例你完全可以根据自己的机器情况调整。但调整的时候要理解每一处改动背后的原因否则出了问题你连从哪查起都不知道。2. 集群整体设计与资源规划思路2.1 三节点角色分配与为什么这么分很多人一上来就问我能不能只用一个节点能但那就失去了搭集群的意义。HBase 强依赖 ZookeeperHadoop 的 HDFS 又需要 NameNode 和 DataNode 分离才能体现分布式特性。我的建议是最小化三节点方案角色分配如下主机名IP 示例承担角色node1192.168.10.101NameNode、ResourceManager、HMaster、Zookeepernode2192.168.10.102DataNode、NodeManager、HRegionServer、Zookeepernode3192.168.10.103DataNode、NodeManager、HRegionServer、Zookeeper为什么把主控角色都放在 node1因为在小集群里NameNode 和 ResourceManager 本身并不吃太多 CPU真正吃资源的是 DataNode 和 RegionServer。把主控集中在一个节点可以减少跨节点通信带来的配置复杂度。Zookeeper 则必须凑够奇数个节点才能形成有效的选举 quorum三个是最小可用规模。你如果只部署两个 Zookeeper一旦其中一个挂掉整个集群就失去多数派HBase 会直接不可用。2.2 虚拟机资源配置的取舍每台虚拟机的配置我建议这样给CPU2 核起步4 核更稳。HBase 的 Compaction 和 Hadoop 的 Shuffle 都是吃 CPU 的操作。内存4GB 是底线8GB 会舒服很多。Zookeeper 默认堆 512MBHadoop 各守护进程加起来约 2GBHBase 的 RegionServer 默认 1GB再算上系统本身4GB 会非常紧张。磁盘每台 40GB 以上。HDFS 副本系数默认是 3你存 1GB 数据实际占 3GB再加上 HBase 的 WAL 和 StoreFile磁盘消耗比想象中快。网络VMware 用 NAT 模式即可关键是三台机器之间要能互相 ping 通并且能通过主机名解析。这里有个容易被忽略的点虚拟机磁盘类型尽量选“单个文件”而不是“拆分成多个文件”虽然单个文件在宿主机上看起来很大但读写性能更好快照管理也更简单。另外三台虚拟机的时钟要同步Zookeeper 的选举和 HBase 的租约机制都对时间敏感。你可以在每台机器上装 ntp 服务或者干脆在 VMware 里开启时间同步。2.3 版本选型的逻辑版本搭配是这套集群最容易翻车的地方。我的经验是不要追最新版要选经过大量验证的稳定组合。以下是我实测下来比较稳的一套Ubuntu 18.04.6 LTSJDK 8必须是 8Hadoop 2.x 和 HBase 1.x/2.x 对 JDK 9 以上支持很差Hadoop 2.7.7 或 3.1.xHBase 1.4.x 或 2.1.xZookeeper 3.4.14 或 3.5.7为什么强调 JDK 8因为 Hadoop 2.x 的很多脚本里硬编码了对tools.jar的依赖而 JDK 9 之后这个包被移除了。你如果非要用高版本 JDK就得自己改脚本得不偿失。HBase 和 Zookeeper 虽然对 JDK 版本宽容一些但为了统一环境全部用 JDK 8 最省心。3. 基础环境准备与系统调优3.1 主机名、Hosts 与 SSH 免密三台机器装好 Ubuntu 之后第一件事是改主机名。在 node1 上执行sudo hostnamectl set-hostname node1node2 和 node3 同理。改完之后记得重启或者重新登录让提示符生效。接着编辑每台机器的/etc/hosts把三台机器的 IP 和主机名对应关系写进去192.168.10.101 node1 192.168.10.102 node2 192.168.10.103 node3这一步极其重要。Hadoop 和 HBase 的配置文件里到处都在用主机名如果解析不了服务启动时会报UnknownHostException而且报错信息往往很隐晦新手很难定位。SSH 免密是集群操作的基石。在 node1 上生成密钥对ssh-keygen -t rsa一路回车即可。然后把公钥分发到三台机器包括 node1 自己ssh-copy-id node1 ssh-copy-id node2 ssh-copy-id node3验证方式很简单在 node1 上执行ssh node2如果不需要密码就能登录说明配置成功。这里有个坑有些教程让你只做 node1 到其他节点的免密但 HBase 的启动脚本可能会从任意节点发起 SSH 连接所以三台机器之间最好两两免密。最省事的做法是在每台机器上都生成密钥然后互相 copy。3.2 JDK 安装与环境变量我习惯把 JDK 装在/usr/local/java目录下。下载好 JDK 8 的压缩包后sudo mkdir -p /usr/local/java sudo tar -zxvf jdk-8uXXX-linux-x64.tar.gz -C /usr/local/java然后编辑/etc/profile在末尾追加export JAVA_HOME/usr/local/java/jdk1.8.0_XXX export PATH$JAVA_HOME/bin:$PATH export CLASSPATH.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar执行source /etc/profile后用java -version验证。三台机器都要做同样的操作。注意JAVA_HOME的路径一定要写对后面 Hadoop 和 HBase 的配置都会引用这个变量。3.3 关闭防火墙与 SELinux 的考量Ubuntu 默认没有 SELinux但防火墙可能是开启的。为了避免端口被拦截我通常直接关闭 ufwsudo ufw disable有人会问这样安全吗在实验环境里虚拟机处于 NAT 网络内部不直接暴露公网关闭防火墙是可以接受的。但如果你是在桥接模式下并且网络环境复杂建议不要关闭而是按需放行端口。Hadoop 和 HBase 涉及的端口非常多逐个放行很麻烦实验环境下关闭是最实际的选择。3.4 时间同步与文件句柄数调整时间同步前面提过这里补充具体操作。安装 ntpsudo apt-get install ntp然后编辑/etc/ntp.conf指定一个可靠的时间源。如果实验环境没有外网可以让 node1 作为时间服务器node2 和 node3 同步 node1 的时间。文件句柄数也要调。HBase 在数据量大时会打开大量文件默认的 1024 不够用。编辑/etc/security/limits.conf追加* soft nofile 65536 * hard nofile 65536改完后重新登录生效。你可以用ulimit -n查看当前值。4. Zookeeper 集群部署与验证4.1 安装与配置文件的写法把 Zookeeper 解压到/usr/local/zookeeper然后进入conf目录复制一份配置模板cp zoo_sample.cfg zoo.cfg编辑zoo.cfg核心内容如下tickTime2000 initLimit10 syncLimit5 dataDir/usr/local/zookeeper/data dataLogDir/usr/local/zookeeper/logs clientPort2181 server.1node1:2888:3888 server.2node2:2888:3888 server.3node3:2888:3888这里解释几个关键参数。tickTime是 Zookeeper 的基本时间单元单位毫秒其他超时时间都是它的倍数。initLimit是 follower 与 leader 建立连接时的最大心跳数syncLimit是 follower 与 leader 之间同步的最大心跳数。dataDir和dataLogDir建议分开因为事务日志的写入频率很高分开存放可以减少 I/O 竞争。server.N的配置里2888是 follower 连接 leader 的端口3888是选举端口。这两个端口不要和其他服务冲突。4.2 myid 文件与启动顺序在dataDir指定的目录下每台机器创建一个myid文件内容分别是 1、2、3对应zoo.cfg里的server.N编号。这个文件不能有扩展名也不能有多余的空格或换行。启动顺序没有严格要求但建议先启动 node1再启动 node2 和 node3。每台机器执行/usr/local/zookeeper/bin/zkServer.sh start然后用zkServer.sh status查看状态。你应该看到一台是leader另外两台是follower。如果三台都是standalone说明它们没有组成集群大概率是zoo.cfg或myid配错了。4.3 用客户端验证集群一致性在任意一台机器上执行/usr/local/zookeeper/bin/zkCli.sh -server node1:2181进入客户端后创建一个节点create /test hello然后在另一台机器上连接执行get /test如果能读到hello说明集群数据同步正常。这个验证步骤很多人会跳过但它能提前暴露很多配置问题。注意Zookeeper 的dataDir目录如果被误删重启后 myid 文件也会丢失服务会启动失败。建议把 myid 文件的内容记下来或者干脆把整个 dataDir 纳入快照管理。5. Hadoop 集群配置与启动5.1 核心配置文件逐项拆解Hadoop 的配置集中在etc/hadoop目录下。需要修改的文件有core-site.xml、hdfs-site.xml、mapred-site.xml、yarn-site.xml以及hadoop-env.sh和slaves文件。先看core-site.xmlconfiguration property namefs.defaultFS/name valuehdfs://node1:9000/value /property property namehadoop.tmp.dir/name value/usr/local/hadoop/tmp/value /property /configurationfs.defaultFS指定了 HDFS 的访问入口客户端和 DataNode 都通过这个地址找到 NameNode。hadoop.tmp.dir是 Hadoop 的临时目录很多运行时数据都放在这里建议显式指定不要用默认的/tmp因为系统重启可能会清理/tmp。hdfs-site.xmlconfiguration property namedfs.replication/name value3/value /property property namedfs.namenode.name.dir/name value/usr/local/hadoop/data/name/value /property property namedfs.datanode.data.dir/name value/usr/local/hadoop/data/data/value /property /configurationdfs.replication设为 3因为我有三个 DataNode。如果你只有两个 DataNode设 3 会导致副本永远无法满足HDFS 会一直报副本不足的警告。name.dir和data.dir分开存放便于管理和备份。mapred-site.xml需要先从模板复制configuration property namemapreduce.framework.name/name valueyarn/value /property /configuration这表示 MapReduce 任务跑在 YARN 上而不是本地模式。yarn-site.xmlconfiguration property nameyarn.resourcemanager.hostname/name valuenode1/value /property property nameyarn.nodemanager.aux-services/name valuemapreduce_shuffle/value /property /configurationyarn.nodemanager.aux-services必须配成mapreduce_shuffle否则 MapReduce 任务会卡在 shuffle 阶段。5.2 环境变量与 slaves 文件在hadoop-env.sh里显式指定JAVA_HOMEexport JAVA_HOME/usr/local/java/jdk1.8.0_XXX虽然系统环境变量里已经有了但 Hadoop 的启动脚本有时不会加载/etc/profile显式写一遍最保险。slaves文件Hadoop 3.x 里叫workers里写上node2 node3这告诉启动脚本哪些节点要启动 DataNode 和 NodeManager。注意不要把 node1 写进去因为 node1 是主控节点不承担数据存储角色。5.3 格式化与启动的先后逻辑第一次启动前必须格式化 NameNodehdfs namenode -format这个操作只能做一次。如果你重复格式化NameNode 的集群 ID 会变而 DataNode 还保留着旧的集群 ID导致 DataNode 无法注册。如果确实需要重新格式化必须先把所有节点的data目录清空。启动 HDFSstart-dfs.sh这个脚本在 node1 上执行它会通过 SSH 连接到 node2 和 node3 启动 DataNode。启动完成后用jps检查进程node1 上应该有 NameNode 和 SecondaryNameNodenode2 和 node3 上应该有 DataNode。启动 YARNstart-yarn.shnode1 上会出现 ResourceManagernode2 和 node3 上会出现 NodeManager。5.4 用 Web UI 和命令验证HDFS 的 Web UI 默认在http://node1:50070Hadoop 3.x 是 9870YARN 的在http://node1:8088。打开浏览器能看到集群概况重点看 Live Nodes 是不是 2也就是 node2 和 node3。命令行验证hdfs dfs -mkdir -p /test hdfs dfs -put /etc/hosts /test/ hdfs dfs -cat /test/hosts如果文件能上传并读取说明 HDFS 工作正常。实操心得start-dfs.sh启动时如果卡住不动大概率是 SSH 免密没配好或者/etc/hosts解析有问题。可以先手动ssh node2试试确认能免密登录再启动。6. HBase 集群部署与联调6.1 HBase 与 Hadoop、Zookeeper 的关系HBase 是构建在 HDFS 之上的列式数据库它自己不存储实际数据而是把数据以 HFile 的形式存在 HDFS 上。同时HBase 依赖 Zookeeper 来管理 RegionServer 的状态、Master 的选举以及元数据的定位。所以 HBase 的配置必须正确指向已有的 HDFS 和 Zookeeper 集群。6.2 hbase-site.xml 的关键配置编辑conf/hbase-site.xmlconfiguration property namehbase.rootdir/name valuehdfs://node1:9000/hbase/value /property property namehbase.cluster.distributed/name valuetrue/value /property property namehbase.zookeeper.quorum/name valuenode1,node2,node3/value /property property namehbase.zookeeper.property.dataDir/name value/usr/local/zookeeper/data/value /property /configurationhbase.rootdir必须和core-site.xml里的fs.defaultFS保持一致否则 HBase 会写到本地文件系统而不是 HDFS。hbase.cluster.distributed设为 true 表示分布式模式。hbase.zookeeper.quorum列出所有 Zookeeper 节点。这里有个细节HBase 自带了一个 Zookeeper 实例如果你用外部的 Zookeeper需要把hbase.zookeeper.property.dataDir指向外部 Zookeeper 的 dataDir并且确保 HBase 不会去启动自己的 ZK。更稳妥的做法是在hbase-env.sh里设置export HBASE_MANAGES_ZKfalse这明确告诉 HBase 不要管理 Zookeeper用我们之前搭好的那套。6.3 regionservers 与环境变量在conf/regionservers文件里写入node2 node3这和 Hadoop 的 slaves 文件类似指定哪些节点启动 HRegionServer。hbase-env.sh里同样要指定JAVA_HOME并且可以调整堆大小export JAVA_HOME/usr/local/java/jdk1.8.0_XXX export HBASE_HEAPSIZE1024如果内存紧张可以把HBASE_HEAPSIZE调小但不要低于 512MB。6.4 启动 HBase 与验证读写启动命令start-hbase.sh启动后node1 上应该有 HMasternode2 和 node3 上应该有 HRegionServer。用jps确认。进入 HBase shellhbase shell创建一个测试表create test_table, cf插入数据put test_table, row1, cf:name, value1读取数据get test_table, row1如果能看到value1说明 HBase 集群工作正常。你还可以在 HDFS 上查看/hbase目录应该能看到 HBase 的文件结构。注意HBase 启动时如果报Connection refused连接 Zookeeper 失败先检查 Zookeeper 是否正常运行再检查hbase-site.xml里的 quorum 配置是否和实际主机名一致。7. 常见问题与排查技巧实录7.1 启动失败类问题速查现象可能原因排查方法DataNode 启动后立即消失集群 ID 不一致查看 DataNode 日志确认是否提示ClusterId mismatch清空 data 目录重新格式化HBase Master 启动失败Zookeeper 连接不上用zkCli.sh手动连接 ZK确认 quorum 配置YARN 任务卡在 ACCEPTEDNodeManager 未注册检查 node2/node3 的 NodeManager 日志确认 ResourceManager 地址SSH 启动脚本卡住免密未配置或 hosts 解析失败手动 ssh 测试检查/etc/hosts7.2 端口冲突与进程残留Hadoop 和 HBase 涉及的端口很多如果你之前装过其他服务可能会冲突。比如 8080 端口经常被 Tomcat 占用而 YARN 的 Web UI 默认也是 8088一般不会冲突但 50070 可能被其他 Hadoop 实例占用。排查方法是netstat -tlnp | grep 端口号如果发现进程残留用jps找到进程号然后kill -9强制结束。但要注意直接 kill 可能会导致数据损坏尤其是 NameNode 和 HBase Master。更优雅的方式是用对应的 stop 脚本。7.3 时间不同步引发的诡异问题Zookeeper 的选举对时间非常敏感。如果三台机器的时间差超过tickTime的若干倍follower 会认为 leader 失联触发重新选举。表现就是集群频繁切换 leaderHBase 连接时断时续。排查方法是date在三台机器上分别执行看时间是否一致。如果不一致检查 ntp 服务是否正常运行。7.4 内存不足导致的 OOM虚拟机内存给得不够时Java 进程会被系统 OOM Killer 杀掉。表现是某个服务莫名其妙消失日志里可能有Killed字样。排查dmesg | grep -i kill如果确认是 OOM要么加内存要么调小各服务的堆大小。Hadoop 的HADOOP_HEAPSIZE、HBase 的HBASE_HEAPSIZE、Zookeeper 的JAVA_OPTS都可以调整。7.5 格式化 NameNode 后的连锁反应前面提过重复格式化 NameNode 会导致 DataNode 无法注册。如果你不小心格式化了解决办法是停止所有 Hadoop 服务清空所有节点的dfs.datanode.data.dir目录然后重新启动。注意这会丢失 HDFS 上的所有数据所以格式化前一定要确认。8. 集群日常维护与扩展思路8.1 快照管理与回滚策略VMware 的快照是这套环境的救命稻草。我的习惯是每完成一个阶段就拍一个快照比如“基础环境就绪”“Zookeeper 集群正常”“Hadoop 集群正常”“HBase 集群正常”。这样一旦后续操作把环境搞坏可以精确回滚到某个健康状态而不用从头再来。快照命名要有意义不要用“快照1”“快照2”这种。另外快照会占用磁盘空间如果宿主机磁盘紧张可以删除旧快照但保留最近一个健康状态的快照。8.2 日志查看的基本方法Hadoop 和 HBase 的日志都在各自的logs目录下。排查问题时优先看对应服务的日志文件比如 NameNode 看hadoop-用户名-namenode-主机名.log。日志文件可能很大用tail -f实时查看或者用grep过滤关键字。Zookeeper 的日志在logs目录下重点关注zookeeper.out。8.3 增加节点时的注意事项如果你后续想从三节点扩展到四节点或五节点步骤是准备新虚拟机配置主机名和 hosts配置 SSH 免密安装 JDK同步 Hadoop 和 HBase 的安装目录和配置文件修改 slaves 和 regionservers 文件然后启动新节点上的 DataNode、NodeManager 和 HRegionServer。Zookeeper 的扩展稍微麻烦一些需要修改所有节点的zoo.cfg加入新节点的server.N配置然后滚动重启。扩展时要注意HDFS 的副本系数不会自动调整如果你从三节点扩到五节点副本系数还是 3新节点上的数据分布可能不均匀。可以用hdfs balancer命令手动触发数据均衡。8.4 这套环境还能怎么用搭好之后你可以在这套集群上做很多事情跑 MapReduce 作业、用 HBase 存储时序数据、测试 Hive 或 Spark 连接 HBase、验证 Phoenix 的 SQL 查询。甚至可以把这套环境当作学习分布式系统原理的沙盘手动 kill 掉某个节点观察集群的容错和恢复行为。我个人在实际操作中的体会是这套集群最大的价值不在于“搭起来”而在于“折腾坏再修好”的过程。每一次故障排查都会让你对分布式系统的理解更深一层。最后再分享一个小技巧把常用的启动、停止、状态检查命令写成 shell 脚本放在/usr/local/bin下能省下大量重复输入的时间。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑