ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Hadoop单节点集群优化部署:从解压到跑通全指南

Hadoop单节点集群优化部署:从解压到跑通全指南 这一篇把 Hadoop 单节点集群从解压到跑通一条链路全部讲完重点是“优化版”三个字——网上的安装教程大多直接套默认配置跑通是能跑通但后续要么丢数据、要么内存爆炸、要么 DataNode 莫名消失折腾成本特别高。我在给学生讲 Hadoop以及自己做实验时反复用过这套流程所有踩过的坑都提前标好了跟着走基本一遍过。标题里写的第 3 篇、002 篇意思是前面几篇已经聊过 Hadoop 组件结构和环境准备工作这一篇就是真正动手把整套进程拉起来。单节点集群又叫伪分布式模式本质是在一台机器上同时启动 NameNode、DataNode、SecondaryNameNode、ResourceManager、NodeManager 五个核心守护进程完整模拟一个 Hadoop 集群的存储与计算逻辑。它最大的价值是成本极低、反馈极快——你在它上面学 HDFS 文件块机制、副本机制、YARN 资源调度、MapReduce 任务提交流程跟真实多节点集群走的是完全同一套代码路径只是物理机器少了几台而已。这套搭建方案适合三种人刚接触大数据、需要直观体感的新手正在做 Hadoop 课程设计、需要快速跑通环境的学生以及面试前想手动把完整集群折腾一遍、加深理解的求职者。1. 单节点集群的定位与优化思路1.1 伪分布式到底在模拟什么先把这五个进程的角色捋清楚后面配置和排错时你才知道谁出了问题该找谁。NameNode 是 HDFS 的“管理者”负责维护文件系统的元数据也就是目录树、文件名、文件块与 DataNode 的映射关系。DataNode 是真正“干苦力”的负责实际存储文件块并响应读写请求。SecondaryNameNode 经常被误解成 NameNode 的热备其实不是——它的职责是定期拉取 NameNode 的 edits 日志和 fsimage 镜像合并生成新的 fsimage帮 NameNode 减轻启动和恢复时的压力。ResourceManager 是整个集群的资源调度中枢。NodeManager 是每台机器上的资源管理进程负责启动和监控容器。在单节点模式下这五个进程挤在一台机器上共享同一份内存和磁盘所以资源规划特别重要这也是“优化版”里要专门调内存参数的原因。很多人觉得伪分布式是“玩具”只能拿来跑 demo。实际不是。HDFS 的写入管线、副本选择策略、心跳机制YARN 的容器调度、资源隔离MapReduce 的分片、排序、shuffle 流程在单节点上全部真实发生。课程设计里要做的数据分析、面试中要讲的提交过程这套环境完全够用。1.2 默认配置必踩的四个大坑官方文档里下载完解压就能跑但那是在理想条件下。真实环境里默认配置至少有四个地方让新手吃尽苦头。第一个坑是临时目录。hadoop.tmp.dir默认指向/tmp下的某个路径而/tmp在系统重启时经常被清理一旦元数据丢了NameNode 根本起不来报错信息还特别隐晦。所以优化版第一件事就是把所有数据目录从/tmp挪出去放到单独的/data/hadoop下。第二个坑是副本数。默认dfs.replication3单节点只有一台 DataNode存三份副本既浪费磁盘又会在写入时因为副本数不满足而卡住或者报错。单节点副本必须改成 1。第三个坑是内存分配。YARN 默认按物理内存的一定比例分配资源在 4GB 甚至 2GB 的小虚拟机上NodeManager 动不动就吞掉大部分内存MapReduce 任务跑着跑着就把机器拖死。内存参数必须显式给定。第四个坑比较隐蔽是 Ubuntu 系统里/etc/hosts默认有条127.0.1.1映射会导致主机名解析到错误的 IP表现症状就是 DataNode 起来几秒钟就掉线日志里报 UnknownHostException。这个问题在 CentOS 上几乎遇不到但在 Ubuntu 上十个新手九个踩。把这四个坑提前避开就是所谓“优化版”的核心含义。后面每一步配置我都会解释为什么这么写。2. 环境准备版本、用户、目录三板斧2.1 版本选型为什么是 Hadoop 3.3.6 JDK 8版本选不对配置再对也白搭。这里我直接给一套经过大量实操验证的组合Ubuntu 20.04 或 22.04 LTSJDK 8OpenJDKHadoop 3.3.6。为什么选 Hadoop 3.x因为 2.x 已经逐渐退出主流很多新特性比如 Cloud Storage 支持、YARN 时间线服务重构都在 3.x 里而且现在课程设计、面试题基本都以 3.x 为背景。3.3.6 是 3.x 系列里很稳定的一个版本坑相对少。下载时认准 Apache 官方镜像站的hadoop-3.3.6.tar.gz二进制包不要下 source 源码包不然还得自己编译。JDK 方面Hadoop 3.x 官方支持 Java 8 和 Java 11。我建议学习环境用 OpenJDK 8原因是生态兼容性最好整个大数据组件体系里对 JDK 8 的支持最成熟网上能搜到的排错经验也最多。JDK 11 能跑但某些组件在 JMX 连接、Kerberos 配置上会有差异化问题新手没必要在这上面增加变量。集群的“单节点”虽然只有一台机器但虚拟机内存建议至少 4GB2GB 也能跑但跑 WordCount 时内存会很紧张。磁盘给 30GB 起步Hadoop 的日志和临时文件比你想象中占空间。2.2 用户、目录与基础组件Hadoop 的守护进程强烈建议用独立用户运行不要用 root。官方虽然没强制但用 root 启动会引发一系列文件属主问题后续 HDFS 目录权限、日志权限会乱成一锅粥。创建一个专用用户hadoop后面所有操作都以这个用户身份执行。sudo useradd -m -s /bin/bash hadoop sudo passwd hadoop然后创建数据目录。注意这个目录规划是优化的关键把元数据目录、数据块目录、临时目录分开出现问题方便定位也方便日后扩容。sudo mkdir -p /data/hadoop/tmp sudo mkdir -p /data/hadoop/namenode sudo mkdir -p /data/hadoop/datanode sudo chown -R hadoop:hadoop /data/hadoop还需要确认两个基础组件安装了ssh和rsync。Hadoop 的启停脚本通过 SSH 在各个节点上启动守护进程即使单节点也要用 SSH 连回 localhost所以 SSH 必须可用rsync 是 HDFS 数据均衡和部分运维操作要用到的。sudo apt update sudo apt install -y ssh rsync openjdk-8-jdk java -version安装完 JDK 后记一下路径后面配置 JAVA_HOME 要用。Ubuntu 上 OpenJDK 8 的默认路径一般是/usr/lib/jvm/java-8-openjdk-amd64可以用readlink -f $(which java)确认。接下来解压 Hadoop 并做属主转换。我习惯放在/usr/local/hadoop并且通过软链或者直接重命名方式去掉版本号后缀这样环境变量写起来干净以后升级版本也方便。sudo tar -zxvf hadoop-3.3.6.tar.gz -C /usr/local sudo mv /usr/local/hadoop-3.3.6 /usr/local/hadoop sudo chown -R hadoop:hadoop /usr/local/hadoop最后配置环境变量。编辑hadoop用户家目录下的~/.bashrc追加以下内容export JAVA_HOME/usr/lib/jvm/java-8-openjdk-amd64 export HADOOP_HOME/usr/local/hadoop export PATH$PATH:$JAVA_HOME/bin:$HADOOP_HOME/bin:$HADOOP_HOME/sbin执行source ~/.bashrc后输入hadoop version能正常显示版本号说明环境变量生效了。2.3 网络与 hosts 修正单节点集群虽然不涉及跨机器通信但 Hadoop 进程对主机名解析极度敏感。这一步非常关键先说正解sudo vim /etc/hosts内容如下127.0.0.1 localhost 127.0.0.1 ubuntu这里的ubuntu要替换成你机器的主机名用hostname命令查看。最重要的是把 Ubuntu 默认生成的那行127.0.1.1 ubuntu注释掉或删掉。为什么要这么做因为127.0.1.1是 Ubuntu 在 DHCP 环境下为机器名分配的映射Hadoop 进程在解析主机名时如果拿到的是127.0.1.1而 NameNode 恰好绑定在127.0.0.1DataNode 和 NameNode 之间就完全找不到对方。这个问题的典型症状我后面会再讲。改完执行sudo systemctl restart systemd-hostnamed或者重启网络服务再执行ping ubuntu确认解析指向127.0.0.1。这一步做完单节点环境的网络部分就干净了。3. 核心配置文件逐项拆解与参数逻辑所有配置文件都在$HADOOP_HOME/etc/hadoop/目录下。这一节是全篇的重中之重我把五个文件逐个拆开告诉你每一行参数是干什么的为什么这么配。3.1 hadoop-env.shJAVA_HOME 与守护进程用户第一个要动的是hadoop-env.sh。虽然前面已经在~/.bashrc里设过 JAVA_HOME但这个文件是 Hadoop 脚本独立读取的很多启动脚本不一定加载你的 bashrc所以必须在这里再显式指定一次。vim /usr/local/hadoop/etc/hadoop/hadoop-env.sh确认或者添加这一行export JAVA_HOME/usr/lib/jvm/java-8-openjdk-amd64如果你平时习惯用 root 执行启停命令那还要加上以下内容否则 Hadoop 3.x 会直接报错拒绝运行提示缺少 HDFS_NAMENODE_USER 等变量export HDFS_NAMENODE_USERhadoop export HDFS_DATANODE_USERhadoop export HDFS_SECONDARYNAMENODE_USERhadoop export YARN_RESOURCEMANAGER_USERhadoop export YARN_NODEMANAGER_USERhadoop我的建议是始终切到hadoop用户操作这样上面这些变量加不加都行。但加上有益无害如果你哪天不小心用 root 执行了也不会被卡住。3.2 core-site.xml默认文件系统与临时目录core-site.xml是 Hadoop 核心配置主要定义默认文件系统地址和临时目录。configuration property namefs.defaultFS/name valuehdfs://localhost:9000/value /property property namehadoop.tmp.dir/name value/data/hadoop/tmp/value /property property namefs.trash.interval/name value1440/value /property /configurationfs.defaultFS指定了默认的 NameNode 地址客户端执行hdfs dfs命令时会自动连接这里。端口 9000 是 HDFS RPC 通信的常用端口也可以写成 8020保持默认约定用 9000 就行。hadoop.tmp.dir是全局临时目录的根基NameNode 和 DataNode 的很多元数据默认的父目录在这里。前面说过的优化核心就在这一步——把它从默认的/tmp/hadoop-${user}迁移到/data/hadoop/tmp避免系统清理。fs.trash.interval是回收站保留时间单位是分钟1440 就是一天。加上这个配置后在 HDFS 里执行删除操作不会立即销毁而是先进回收站给你留一条后悔药。这是我自己加车习惯里收益很大的一笔配置。3.3 hdfs-site.xml副本数与数据目录hdfs-site.xml负责 HDFS 元数据目录、数据块目录、副本数这些关键属性。configuration property namedfs.replication/name value1/value /property property namedfs.namenode.name.dir/name value/data/hadoop/namenode/value /property property namedfs.datanode.data.dir/name value/data/hadoop/datanode/value /property property namedfs.namenode.secondary.http-address/name valuelocalhost:9868/value /property /configurationdfs.replication改成 1 是单节点必做的操作。集群里默认 3 是为了分布式环境下数据可靠性但单节点只有一个 DataNode存 3 份没有任何意义纯浪费磁盘。假如你忘了改default 副本数达不到写入时会一直等待副本确认流程会卡住或者报异常。dfs.namenode.name.dir和dfs.datanode.data.dir分别指定 NameNode 的元数据持久化目录和 DataNode 的数据块存储目录。我把它们分开是因为 NameNode 的数据是绝对核心将来做备份时可以直接盯它一个目录不用跟数据块混在一起。dfs.namenode.secondary.http-address设置 SecondaryNameNode 的 HTTP 端口默认值是开机自动推3.x 默认是 9868这里显式写出来防止某些版本解析异常。3.4 yarn-site.xml 与 mapred-site.xml资源与计算框架YARN 负责资源调度。单节点模式下yarn-site.xml的优化重点在资源上限和内存检查。configuration property nameyarn.nodemanager.aux-services/name valuemapreduce_shuffle/value /property property nameyarn.resourcemanager.hostname/name valuelocalhost/value /property property nameyarn.nodemanager.resource.memory-mb/name value2048/value /property property nameyarn.nodemanager.vmem-check-enabled/name valuefalse/value /property /configurationyarn.nodemanager.aux-services固定填mapreduce_shuffle这是 MapReduce 任务在 YARN 上运行必需的后台服务忘记配的话任务会报 Shuffle 错误。yarn.nodemanager.resource.memory-mb是 NodeManager 能支配的物理内存总量。默认值是物理内存的 80%在 4GB 的虚拟机上就是 3.2GB留给操作系统和 NameNode 的空间就不够了很容易 OOM。这里我按 4GB 机器的场景设为 20482GB具体取值规则我单独在下一节讲。yarn.nodemanager.vmem-check-enabled设置为 false是关闭 YARN 对容器虚拟内存使用量的严格校验。小内存机器上经常发生容器物理内存没用满但虚拟内存超限被判定失败的情况说白了就是这个检查过于敏感学习环境直接关掉最省心。mapred-site.xml需要先从模板复制一份cp $HADOOP_HOME/etc/hadoop/mapred-site.xml.template $HADOOP_HOME/etc/hadoop/mapred-site.xml然后编辑configuration property namemapreduce.framework.name/name valueyarn/value /property property namemapreduce.map.memory.mb/name value1024/value /property property namemapreduce.reduce.memory.mb/name value1024/value /property /configurationmapreduce.framework.name必须设成yarn否则 MapReduce 跑在本地模式LocalJobRunner压根不经过 YARN也就学不到资源调度流程。map和reduce的 memory.mb 指定每个 Map 或 Reduce 容器申请的内存单节点 4GB 机器设 1024 比较合适。这两个参数会影响容器申请配太大超过 NodeManager 总量会直接导致任务无法启动。3.5 内存参数怎么定才不炸内存规划这块值得单独拿出来说。一台 4GB 的虚拟机要把 NameNode、DataNode、ResourceManager、NodeManager 全塞进去还要留出操作系统余量四舍五入就是精打细算。我的经验值参考这张表物理内存NodeManager 总量单 Map/Reduce 容器内存适用场景2GB1024512只是验证启动跑小数据4GB20481024跑 WordCount、课程设计8GB40962048多任务并发、跑稍大实验按这个比例NameNode 默认堆内存 1GB 左右DataNode 和 NodeManager 各拿一部分系统还能剩出 1GB 左右不会被拖死。如果机器内存不够与其硬调参数不如先升级虚拟机配置参数优化救不了物理资源的短缺。所有配置改完后别忘了检查workers文件Hadoop 3.x 里替代了旧版 slaves 文件的角色确保里面只有一行localhost。这个文件告诉 start-dfs.sh 从哪些节点启动 DataNode如果这里为空你的 DataNode 永远不会被启动。4. 初始化、启动与全链路验证4.1 SSH 免密登录配置前面说了 Hadoop 启停脚本要通过 SSH 连接节点所以必须先给hadoop用户配好 localhost 免密。切换成hadoop用户后执行ssh-keygen -t rsa -P -f ~/.ssh/id_rsa cat ~/.ssh/id_rsa.pub ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys第一条命令生成空密码的密钥对-P 表示私钥没有 passphrase不然每次启动脚本都会停下来问你密码。第二条把自己的公钥写进 authorized_keys第三条严格限定权限。这一步做完执行ssh localhost如果不需要输密码直接回到终端就说明通了。第一次连接可能提示确认主机指纹输入 yes 即可也可以用ssh-keyscan localhost ~/.ssh/known_hosts提前把指纹写进去。4.2 格式化 NameNode这是整个搭建过程中唯一一次需要小心翼翼的操作。执行hdfs namenode -format格式化做了三件事生成集群的 NamespaceID创建 fsimage 镜像文件建立 NameNode 赖以启动的目录结构。格式化完成后日志里能看到类似successfully formatted的输出。这个操作有一个铁律只能在第一次启动前格式化以后非必要不重复执行。很多人后来重启集群发现 NameNode 起不来脑子一热又 format 一次结果 DataNode 的目录里还是旧的 clusterID两边对不上DataNode 起来又掉越折腾越乱。如果真的走到必须重来那一步我会在第 5 节告诉你怎么做才算完整清理。4.3 启动集群与 jps 验证启动命令很简单start-dfs.sh start-yarn.sh注意不要偷懒用start-all.sh虽然它能一次拉起全部但你没法区分 HDFS 和 YARN 各自的启动日志出问题时排查范围被扩大了。分开启动各查各的日志这是实操习惯。启动后第一件事就是验证进程。终端执行jps正常情况下能看到这五个进程NameNode DataNode SecondaryNameNode ResourceManager NodeManager一个不多一个不少。少的那个就是有问题的直接去第 5 节对号入座。然后再看两个 Web 页面。Hadoop 3.x 的 HDFS 管理页是http://localhost:9870打开能看到 NameNode 状态、集群容量、DataNode 列表。YARN 资源调度页面是http://localhost:8088/cluster能看到 NodeManager 注册状态和资源总量。两个页面能正常打开说明集群已经可以在浏览器里管起来了。4.4 用 WordCount 跑通完整链路进程全起来只是第一步真正检验集群能否干活的标准是跑一个 MapReduce 作业。WordCount 是 Hadoop 自带的示例程序也是所有学习路线里的第一个作业验证 HDFS 读写、YARN 调度、MapReduce 执行全过程。先准备一个测试文件echo hello hadoop hello world /home/hadoop/word.txt上传到 HDFS 并运行hdfs dfs -mkdir -p /demo/input hdfs dfs -put /home/hadoop/word.txt /demo/input/ hadoop jar /usr/local/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.3.6.jar \ wordcount /demo/input /demo/output作业运行结束后查看结果hdfs dfs -cat /demo/output/part-r-00000输出应该是hadoop 1 hello 2 world 1看到这个结果说明你的单节点集群从 HDFS 到 YARN 到 MapReduce 全部打通了。这时候可以顺手看看http://localhost:8088/cluster上的历史任务记录之前跑过的作业、消耗的资源、执行耗时都有这是理解 YARN 应用生命周期的第一手素材。5. 踩坑实录与高频报错排查这一节是整篇里含金量最高的部分。以下问题我全部在实际环境里遇到过按照“现象——原因——处理”的方式整理成速查表建议截图保存。5.1 高频报错速查表现象大概率原因处理办法jps 里只看到 Java 命令没有 DataNodeworkers文件里没有 localhost编辑etc/hadoop/workers写入 localhost重启集群9870 端口能通一会儿刷新就断DataNode 与 NameNode 的 clusterID 不一致清空namenode和datanode目录下的 current 文件夹重新格式化日志报UnknownHostExceptionUbuntu 的/etc/hosts里有127.0.1.1映射删掉那一行把主机名固定映射到 127.0.0.1跑任务报物理内存超限、Container 被杀小内存机器上 vmem 检查过于敏感yarn.nodemanager.vmem-check-enabled设为 falselocalhost:9000连接拒绝NameNode 没启动或端口被占用看 NameNode 日志、检查fs.defaultFS配置第二次格式化后 NameNode 起不来只清了 namenode 目录没清 datanode 目录两个目录全部清理后再 format上传文件成功读文件时报块缺失DataNode 没完全注册就写入等 jps 五个进程全部稳定后再操作 HDFSWeb 页面能开8088 显示 NodeManager 为 0NodeManager 未注册多半是 yarn-site 配置问题检查 resourcemanager.hostname确认 NodeManager 进程还在作业提交后一直卡在 ACCEPTED容器内存申请大于 NodeManager 剩余内存调小 map/reduce 的 memory.mb或加大虚拟机内存网络访问 9870/8088 超时防火墙拦截sudo ufw allow 9870/tcp和8088/tcp排查的通用套路遵循一个顺序先看jps确认进程在不在再确认端口通不通最后翻日志。日志在$HADOOP_HOME/logs目录下命名规则是hadoop-用户名-进程名-主机名.log比如hadoop-hadoop-datanode-ubuntu.log。看报错先看最后 50 行尤其关注Exception、ERROR、WARN关键字。5.2 三个容易被忽略的细节第一个细节是重复格式化。网上很多排错帖让你“重新 format 就好了”如果你照着做却只执行hdfs namenode -format大概率会遇到 DataNode 起不来的新问题。原因是格式化重建了 NameNode 的 clusterID但 DataNode 目录里还存着旧 clusterID两边对不上。正确做法是先把/data/hadoop/namenode和/data/hadoop/datanode两个目录下的current子目录整个删掉再执行格式化。这一条如果记牢能帮你省掉很多次“格式化-失败-再格式化”的死循环。第二个细节是 Hadoop 3.x 的 Web 端口跟 2.x 不一样。网上大量旧教程写的是 50070那是 Hadoop 2.x 的 NameNode 页面端口3.x 改成了 9870。如果你照着旧教程访问 localhost:50070页面永远打不开这不是集群坏了是麻瓜了。同样SecondaryNameNode 的默认端口从 50090 变成了 9868。第三个细节是启动脚本跟 bashrc 的读档顺序。前面配置的环境变量在~/.bashrc里但某些终端工具远程执行命令时不会加载~/.bashrc导致hadoop、jps之类命令提示找不到。遇到这种情况不要慌先手动执行source /etc/profile或者export HADOOP_HOME/usr/local/hadoop再跑命令。要根治就把环境变量同时写一份到/etc/profile.d/hadoop.sh。还有一个不算坑但要提醒的操作习惯关闭集群用stop-dfs.sh和stop-yarn.sh不要直接关虚拟机。HDFS 的元数据需要优雅落盘Write-ahead 日志没写完就断电下次启动大概率要恢复很久甚至失败。真急着关机也要等 stop 命令执行完毕。6. 几个直接影响使用体验的习惯这套环境跑通之后我自己实测下来有几个小习惯能明显减少后续折腾分享给你。第一个习惯是只认hadoop用户不碰 root。每次开机后第一步就是su - hadoop所有 HDFS 操作和数据目录都归属它。这样能保证 HDFS 目录权限和 Linux 文件权限始终一致不会出现 java 进程能写但 shell 删不掉的文件也不会出现 HDFS 里创建不了目录的权限困惑。第二个习惯是把启停命令封装成一个脚本。单节点集群要敲的命令其实不多但每次输入一长串还是烦。我建议在hadoop用户 home 下建一个cluster.sh内容就是两条 aliasalias hstartstart-dfs.sh start-yarn.sh alias hstopstop-dfs.sh stop-yarn.sh写入~/.bashrc后以后管理集群只要输hstart和hstop。这个习惯也能平滑迁移到将来多节点集群提前养成用脚本管理进程的意识。第三个习惯是善用快照和镜像。搭好一套干净环境后在虚拟机管理软件里打一个快照或者封成一个模板镜像后续学 Hive、Spark、HBase 时需要多个实验环境直接克隆就行不用再从头搭一遍。我一度专门准备了一个单节点集群的 Docker 镜像用来做对照实验破坏性操作比如格式化、清理数据块都在镜像里折腾等到完全确认无副作用了再动主环境。对于还在学习阶段的人这个习惯能让你敢于踩坑而不心疼。第四个习惯是记录自己的操作日志。不是让你写详细文档而是每次改动配置前把原始内容备份一份比如cp core-site.xml core-site.xml.bak。Hadoop 配置文件的排错最怕的就是改来改去忘了原本长什么样有备份就能随时回滚这比任何排错技巧都实在。另外单节点这套流程跑通之后后面如果要继续深入 HA 高可用方向就会引入分布式协调组件而那个实验的基础就是你现在搭好的这一套 HDFS 和 YARN 环境。先把单节点吃透后续每一步都有落脚点。
返回列表