
聊到CDH及软件安装部署我脑海里最先冒出来的不是安装成功后的绿色对勾而是去年在一家客户现场整整一周都在和parcel下载较劲的那个画面。当时机房没有外网安装包是拷进内网的结果agent连上Cloudera Manager后界面一直显示“正在下载分布式软件包”进度条半天不动那种焦虑做过的人都懂。本文就是围绕CDH及软件安装部署这件事把我从环境准备、安装链路、验证排错到上线调优的完整过程写出来。适合准备自建大数据平台的数据工程师、运维同学也适合只在网上看过别人搭集群、自己还没完整走一遍的初学者。1. 为什么我把核心组件选型压在了CDH这套发行版上1.1 版本碎片化带来的兼容性成本早期搭Hadoop集群最痛苦的其实不是安装本身而是把一堆开源组件拼在一起。今天拉一个Hadoop 2.7的包明天装一个Hive 2.1的版本后天再遇到Spark和Hive的shaded版本冲突整个集群就像一辆每个零件都来自不同厂商的拼装车跑起来也不知道什么时候会散。我见过不少人花了一周时间把组件全都装好最后卡在Spark读取Hive元数据时的类冲突上光是排查compatible版本就用了三天。CDH这套发行版解决的正是这个问题。它把Hadoop生态里的HDFS、YARN、Hive、HBase、Impala、Kafka等组件统一打成一个大版本包官方已经把相互之间的依赖关系仲裁过了。你装CDH 6.3.x的时候拿到的Hive、HDFS、Spark、ZooKeeper等都是一套经过验证的版本组合不用自己逐个去查兼容性矩阵。1.2 CDH的核心价值在于“版本仲裁”和统一管理很多人以为CDH就是“把开源软件打了个包”其实不止。它真正值钱的地方是两个一个是上面说的版本仲裁另一个是Cloudera Manager这套管理工具。CM会把所有节点的Agent统一连接起来组件安装、配置下发、角色启停、监控报警、滚动升级都可以在Web界面上完成。举个例子你手动部署三台节点的HDFS要改core-site.xml、hdfs-site.xml、slaves文件还要一台台同步、一台台重启。在CM里你在界面上改完配置点“应用”它会自动下发到集群中所有相关主机并重启受影响角色省掉的不只是敲命令的时间更重要的是避免了“某一台漏改”的低级错误。parcel的分发机制也很有意思它把所有组件打包成一个二进制分发单元CM把包分发到每台节点后统一解压这样就能保证所有主机上跑的是完全一致的组件版本。1.3 什么场景适合、什么场景不建议我做了几个项目后的判断是CDH非常适合三类场景传统企业内网或私网环境下载外网包不方便需要离线部署业务方要求快速交付、稳定优先不希望团队成员花大量时间搞版本仲裁已有的自建集群需要平滑升级用CM的滚动升级能减少业务中断时间。但也有不适合的情况。如果你所在团队是深度定制Hadoop源码、要改底层内核或者整个基础设施已经全面容器化倾向直接用Kubernetes来管理那么原生开源组件搭配自动化运维工具可能更顺手。CDH在容器上跑不是不行但毕竟它的管理优势是围绕物理机和虚拟机设计出来的硬搬到容器里反而会浪费掉一部分能力。工具选型这件事不是越“新”越好而是越适合现状越好。对比维度CDH发行版自编译/原生组件拼装组件兼容性官方仲裁过省心需要自己逐个验证安装运维CM统一管理界面操作手动配置脚本维护离线部署支持parcel机制成熟依赖镜像制作水平二次开发改动源码困难自由但维护成本高适合规模几台到几百台都能覆盖更适合强定制小规模2. 部署前四个决定成败的细节硬件、JDK、外部数据库、离线仓库2.1 硬件规划与系统初始化先关掉那些“看不见的坑”规划阶段最容易被忽视的不是CPU和内存而是系统底层的默认参数。CDH对操作系统的要求不算苛刻生产环境我用过CentOS 7.6和7.9内核版本保持默认都没有问题。但有几个参数必须提前处理否则安装到一半会莫名其妙出故障。首先关闭SELinux。安装部署阶段如果开着SELinuxagent和server之间的通信经常会因为策略限制出现奇怪的问题比如parcel解压权限失败、进程无法监听端口等。折腾一圈发现是SELinux拦截非常浪费时间。其次是防火墙。内网环境如果确定没有外部访问需求最简单的做法就是禁掉firewalld如果公司安全要求必须开着那就把必需的端口放行。7180是CM前端Web页面端口7182是agent和server通信端口8020或9000是NameNode RPC端口50070HDFS 2.x或9870HDFS 3.x是NameNode Web UI8088是YARN的ResourceManager Web UI。还有个很容易被忽略的透明大页THP问题。CDH的官方文档明确建议关闭THP因为大数据组件大量使用内存映射文件THP的内存合并策略会让类似HBase这类延迟敏感型服务的响应时间变得很不稳定。执行方式很简单echo never /sys/kernel/mm/transparent_hugepage/enabled echo never /sys/kernel/mm/transparent_hugepage/defrag不过这个修改重启后会失效需要写进/etc/rc.local确保开机自动设置。swap也要调整。建议把vm.swappiness设为1或直接关掉否则节点内存紧张时系统会频繁把进程换到swap分区最直接的表现就是DataNode或NodeManager的响应延迟突增。最后是时间同步。很多初学者会忽略NTP但Kerberos、HDFS租约、CM的健康检查全都依赖一致的时间。集群里哪怕只有一台节点时间偏差超过几十秒都会看到一堆莫名其妙的“连接超时”或“块丢失”告警。部署前把所有节点的chrony或ntpd配置好、确认时间源可用这个步骤一定要排在前面。硬件方面我的建议是CM Server节点单独放一台机器不要和NameNode挤在一起。CM Server本身不承担计算任务但它需要和所有agent保持长连接还要维护大量监控数据内存建议16GB起步。NameNode节点内存要按元数据量估算如果集群里有几十万个文件、上百万个Block堆内存给到32GB并不过分。DataNode节点内存可以稍微宽松但每台至少8GB以上同时数据磁盘建议单独挂载。2.2 JDK版本别再让系统自带Java捣乱CDH对JDK版本有明确要求我用的CDH 6.x系列标配JDK 8CDH 7.x部分组件也能跟上JDK 11但为了避免麻烦我在CDH 6.x上统一使用Oracle JDK 8或OpenJDK 8。常见问题出在系统预装的OpenJDK上。CentOS默认会装OpenJDK但版本可能是1.7或1.11直接拿来跑Cloudera Manager很可能起不来。更麻烦的是有些机器上存在多个Java版本JAVA_HOME指向不统一CM的各个服务启动时各找各的Java环境变量互相打架。我的操作习惯是先卸载系统自带的OpenJDK然后手动安装JDK 8到统一目录比如/usr/local/java/jdk1.8.0_xxx。同时会用alternatives命令把java、javac指向新安装的路径。还有一个地方容易漏就是/etc/profile和/etc/environment里的JAVA_HOME必须全局生效不要只在某个用户的.bashrc里写。判断Java是否准备好不要只看java -version还要检查javac版本和编译工具完整性。因为Cloudera Manager的许多组件初始化时会调用javac编译临时代码缺了编译环境会触发一些比较隐蔽的错误。2.3 外部数据库CM的“大脑存储”CDH安装向导中会让你选择数据库类型CM默认支持内嵌的PostgreSQL或者外置的MySQL/MariaDB。我强烈建议用外置MySQL不要用默认的内嵌数据库。原因是CM不仅存配置信息还有大量监控数据、历史告警、报告数据都落在库里默认的Derby或者内嵌PostgreSQL在这种压力下表现不好而且数据量大了以后几乎没法迁移。数据库规划时我习惯在一台单独的机器上安装MySQL 5.7。CDH 7.x也支持MySQL 8但6.x时代我用的都是5.7稳定。部署前需要为CM创建对应的账号和数据库。我通常会创建名为cm的数据库和一个具有全部权限的cmadmin账号密码强度别设得太复杂因为安装脚本会在命令行参数里出现复杂的特殊字符反而容易让命令解析出错。MySQL安装完成后记得下载MySQL JDBC驱动把mysql-connector-java.jar放到CM Server节点的/usr/share/java/目录下并重命名成public class匹配的mysql-connector-java.jar。很多部署失败的问题就是漏了这一步CM Server找不到JDBC驱动数据库初始化时直接报“No suitable driver found”。2.4 离线仓库没有公网环境时必须提前完成的事情经历过一次“在线安装卡在parcel下载”之后我再也不指望安装时现场下载。CDH的parcel包动辄几个GB在学校或企业内网这种网络环境不稳定的场景下中断几次就得从头再来体验非常糟糕。正确的做法是在有外网的机器上提前下载好CDH的parcel包例如CDH-6.3.2-1.cdh6.3.2.p0.1605554-el7.parcel同名但后缀为.sha1或.sha256的校验文件如果有Hive、Spark、Kafka等组件需要也一并下载对应parcel版本。然后把所有文件放到CM Server主节点的/opt/cloudera/parcel-repo目录下。CM启动后会自动扫描这个目录识别parcel和对应的校验文件后续通过Web界面安装时就不再从外网下载而是直接从这个目录分发到各台agent。如果你有多台机器需要分发最简单的方式是在CM Server节点上用nginx或python的http.server把/opt/cloudera/parcel-repo目录暴露出去agent从同一个地址拉取。实际操作中我会把parcel-repo放在独立的大分区里因为一个版本CDH加上几个常用组件的parcel总容量可能超过20GB磁盘太小的节点会很尴尬。3. 从Cloudera Manager Server到Agent安装流程每一步在做什么3.1 安装顺序背后的逻辑接触过CDH的人都会发现它的安装顺序是先装Server端组件再装Agent最后在Web界面里添加主机。这个顺序背后有它的逻辑CM Server是整个集群的“大脑”需要先把大脑和数据存储准备好agent才有地方上报心跳。如果你先把agent装好并启动它默认连的server_host还是localhost虽然不会造成太大问题但会造成后续重新配置的麻烦。Server和Agent最好在一台机器上先安装完成然后通过Web向导批量部署到其他节点。这样能避免手动到每台机器上配config文件、启动服务省时且减少出错。CDH本身支持的模板批量添加让我一般不在其他节点上手动安装agent而是靠CM首批添加主机时的安装过程来分发。3.2 配置CM仓库并安装主节点组件最简单的方式是使用系统包管理器安装。需要先创建YUM仓库文件例如/etc/yum.repos.d/cloudera-manager.repo里面指向CDH版本的repo地址。如果是离线环境需要准备RPM包和依赖包构建本地仓库。[cloudera-manager] nameCloudera Manager baseurlhttp://实际仓库地址/cm/6.3.x/ gpgcheck0 enabled1我习惯把gpgcheck设为0因为离线环境下导入GPG密钥经常会引入额外风险公司内网又没有暴露给外部的风险校验问题不大。如果你对安全有更高要求可以在线导入官方密钥再把gpgcheck调成1。然后执行安装yum -y install cloudera-manager-daemons cloudera-manager-agent cloudera-manager-server这个命令会把daemons、agent和server三个包都装上。安装完成后agent的配置文件位于/etc/cloudera-scm-agent/config.ini需要把server_host改成CM Server的主机名或IP否则agent会一直去找本地端口。3.3 初始化数据库并启动服务数据库初始化是整个安装过程中最容易被“想当然”的部分。我见过有人在MySQL里手动建了好几个库结果跑到最后发现每个服务的库都没有对应的初始表其实是应该用官方脚本统一完成初始化。CDH提供了初始化脚本用法大致如下/opt/cloudera/cm/schema/scm_prepare_database.sh mysql -h 数据库主机名 cm cmadmin 密码脚本执行成功后会自动创建CM所需的schema和初始表包括各个服务的配置表、任务表、审计表等。执行完成后建议立刻在mysql客户端里查看一下是否有cm库并检查一下关键表是否存在。接着启动agent和serversystemctl start cloudera-scm-agent systemctl start cloudera-scm-server启动之后别急着看界面先用日志确认服务正常。CM Server的日志位置在/var/log/cloudera-scm-server/cloudera-scm-server.log。你可以tail -f观察日志直到出现类似“Started Jetty server”的信息才说明Web服务真正起来了。首次启动可能需要几分钟因为CM要初始化大量配置并做自动探测别一看界面打不开就重复重启反而让初始化进程互相打断。3.4 浏览器端安装向导与角色分配浏览器访问http://CM-Server:7180默认账号密码都是admin。首次登录会进入安装向导就像普通软件安装一样按提示走但有几个地方要格外小心。添加主机时CM会让你输入一组主机的IP或主机名。它会通过SSH自动在这些主机上安装agent。这里要求CM Server能通过SSH免密登录到目标主机同时目标主机要提前装好Python和pssh依赖否则自动化流程会失败。接下来选择“使用Parcel”安装组件时就应该选择我们之前准备好的CDH版本。如果之前把parcel和校验文件放到了/opt/cloudera/parcel-repo目录CM会识别到“已下载”状态只需要在线分发就可以了。分发和校验阶段耗时较长通常是整个安装过程中最长的等待期但它是一次性的后面扩容和升级都能复用。角色分配时我通常在界面上手动规划不太依赖默认分配。NameNode建议放在CM Server之外的独立机器上Standby NameNode放另一台这样单点故障时不会同时挂掉。ZooKeeper尽量分配奇数台节点至少3台。ResourceManager也放到物理机上单独部署。Hive和Hue可以共存在同一台机器上因为它们对资源的占用模式和NameNode不太一样。4. 服务部署完之后先别急着交差验证与踩坑实录4.1 部署完成后的第一轮验证清单集群安装完成只是一个开始很多人看到界面上所有角色变绿就觉得大功告成我一般会再做一轮完整的验证避免“漂亮的界面下藏着不可用服务”。我会先检查进程jps在每台节点上确认对应角色进程已经跑起来。HDFS的NameNode进程、DataNode进程、YARN的ResourceManager和NodeManager、ZooKeeper的QuorumPeerMain如果这些进程都在说明基础服务正常。然后做命令级验证hdfs dfsadmin -report yarn node -list hdfs dfs -mkdir /test hdfs dfs -put testfile /test hdfs dfs -cat /test/testfile如果文件能正常写入和读取HDFS链路才算真正打通。NameNode的Web UI、YARN的ResourceManager UI也都要扫一眼确认能够访问。这些验证步骤看起来基础但真的能发现很多问题比如DataNode因为磁盘空间不足而无法上报、YARN队列配置错误导致任务提交被拒绝等。4.2 踩坑一Parcel校验异常或长时间卡在下载最常见的是parcel一直被卡在“下载”状态进度条长时间没有任何变化。如果你确认CM Server节点根本无法访问外网那基本可以断定是parcel仓库里缺少校验文件或者CM识别不到本地parcel。排查时先看目录ls -lh /opt/cloudera/parcel-repo/正常情况应同时存在parcel文件、对应的.sha1或.sha256文件以及manifest.json文件。sha文件内容是一个哈希值CM会用它来校验parcel包完整性。很多人只把parcel复制进去忘了复制sha文件CM就会一直尝试自己计算校验值甚至会触发重新下载。另一种情况是磁盘空间或inode不足。parcel解压需要原文件将近两倍的空间因为要先解压到/opt/cloudera/parcels再生成符号链接。我在一台只有60GB磁盘的节点上遇到过解压到一半提示空间不足CM界面却显示“正在分发”的情况最后检查日志才发现是磁盘满了。4.3 踩坑二主机名/FQDN不一致导致Agent失联添加主机时可以成功安装agent但在分配角色时却提示“主机尚未完成运行”或者agent明明在运行但CM界面上一直显示“主机运行状态未知”。这类问题十有八九是主机名和/etc/hosts配置不一致导致的。CM对FQDN比较敏感。比如一台主机hostname设置成node01但/etc/hosts里写的是node01.internal格式的域名agent上报的主机名就会和CM预期的不匹配心跳注册就会失败。后来我在所有节点上统一只使用短主机名并保证/etc/hosts中每一行都同时写清楚短主机名和完整域名之后再没有出现过这种问题。如果已经卡在这种状态重装agent不一定有效。正确做法是先把/etc/hosts、/etc/sysconfig/network里所有主机名统一然后重启agent等它重新上报新主机名后再在CM里删除旧主机、重新添加。4.4 踩坑三HDFS元数据clusterID冲突这个坑很容易发生在“加了新节点”或者“重新初始化NameNode”之后的集群上。现象是新加的DataNode启动后反复刷Connection refused或者NameNode Web UI里DataNode一直显示“未知”状态。打开DataNode日志通常会看到类似“Incompatible clusterIDs in .../VERSION”的信息。原因也很简单NameNode格式化时生成一个clusterID存到fsimage元数据中DataNode首次启动时如果数据目录里已经有旧的VERSION文件就会带着旧clusterID上报。新老clusterID不一致NameNode直接拒绝注册。解决办法也比较直接找到新DataNode的datanode数据目录备份后删除VERSION文件重新启动DataNode让它从NameNode获取当前集群的clusterID。如果你是新装集群遇到这个问题最常见的原因是复制了模板虚拟机所有节点的datanode数据目录带着同一个clusterID这时需要逐一清理DataNode的数据目录。4.5 踩坑四外部数据库连接反复报错一次Hive服务部署后Hive metastore一直起不来日志报“Unable to connect to MySQL”。排查时发现CM配置的hive-site.xml里javax.jdo.option.ConnectionURL写的是jdbc:mysql://localhost:3306/hive直接把localhost替换成了真正部署MySQL的主机名连接就通了。这类问题的根源通常在于安装向导让你输入数据库主机名时默认值可能是localhost但你真正安装的元数据库在另一台机器上。等到CM把配置文件下发到远端节点后让各agent通过这些配置去连接localhhost指向的IP地址自然就无法连接。另外JDBC驱动也必须同时放在所有运行metastore服务的节点上不只是CM Server。Hive metastore进程启动时需要加载JDBC驱动类如果路径不对或类名不匹配同样会报“No suitable driver found”。部署前我会在所有相关节点上统一放一份mysql-connector-java.jar并设置正确权限这一步能省掉后续很多麻烦。5. 角色参数调优与小集群运维建议5.1 默认参数为什么“不够用”集群跑起来之后各项服务的默认参数基本都是CDH官方给出的保守值它能保证服务稳定运行但离“好用”还有一段距离。默认配置最大的问题有两个一是各角色的Java堆内存设置偏保守二是YARN的资源估算未必贴合你节点的实际硬件。比如HDFS的DataNode和NameNode的堆大小CM默认可能只有1GB到2GB。如果你的集群有几十个节点、每天写入几千万个文件NameNode很快就需要更多堆内存来维护文件系统元数据否则就会出现Full GC频繁、NameNode进入SafeMode或响应卡顿。5.2 三个最值得先调的内存参数我最先调的参数通常有三个NameNode堆内存建议设为物理内存的一半再稍微留一点比如32GB物理内存的机器NameNode堆设16GB比较稳妥。如果机器主要只跑NameNode也可以考虑20~24GB。DataNode堆内存主要用于维护数据块和流式读写堆一般不需要太大8GB以内通常够用更关键的是留给Page Cache足够的内存。YARN容器内存在yarn-site.xml里yarn.nodemanager.resource.memory-mb要基于每台节点的实际内存来配置。例如节点内存64GB系统本身和其他服务预留16GB那给YARN的资源就可以是48GB。除了这三个我还会调整yarn.scheduler.maximum-allocation-mb默认值通常只有8GB左右如果跑Spark任务需要更大的executor就会触发“容器内存超出限额”的报错。把这些参数改完后再跑一轮基准测试观察YARN的resource界面和日志看是否存在频繁重试或内存溢出。5.3 日常运维与备份习惯CDH装好之后日常维护的核心不是“会不会装”而是“别让问题发生到不可挽回”。我每次做完初始部署第一件事就是在CM里配置好自动备份Cloudera Manager Server的数据库。CM的配置信息、集群定义、健康检查状态都在这套数据库里如果数据库丢了安装就算白干。备份策略我用每天一次mysqldump保留近7天即可同时把/opt/cloudera/parcel-repo里已经用到的parcel和sha文件也做一次快照后续扩容或重装时直接拿来用。磁盘监控也很关键。HDFS数据节点的数据盘要盯inode和空间使用率达到85%就要开始规划扩容。我遇到过一次DataNode因为inode耗尽无法创建新块那个问题界面上根本看不出来只有看日志和df -i才能发现。日志轮转也要提前配置。Cloudera Manager本身自带日志管理但HDFS的namenode日志、datanode日志、YARN的container日志如果不轮转半年后就能吃掉上百GB磁盘空间。建议用logrotate统一管理每周轮转一次保留4到8周即可。5.4 后续扩展思路CDH集群不是装完就算完运维期的扩展往往比安装期更重要。扩容节点时只需要保证新节点满足同样的系统初始化要求包括关闭THP、配置hosts、时间同步等然后在CM里通过“添加主机”引导它安装agent再分配角色就行。只要parcel在CM仓库里完整可用新增节点会自动从既有仓库拉取对应组件包不需要再单独拷文件。版本升级方面CDH 6.x升级到7.x我的经验是先在一个测试环境完整演练一遍再对生产环境做滚动升级。过程中要特别关注Hive和Hue的兼容性问题因为这两个组件的配置结构变化比较大升级脚本可能会改写hive-site.xml导致表结构不兼容。升级前一定要备份CM数据库并在测试环境跑通Hive的所有核心查询再做生产迁移。如果你想在这个集群上增加其他组件比如Kafka、Kudu或Impala直接在CM的组件列表里添加对应parcel并分配角色就可以了。由于一切都由CM统一管理后续就算有人误改了配置文件也可以通过CM的“部署客户端配置”一键恢复。最后再分享一个小经验安装完CDH后先把/opt/cloudera/parcel-repo目录整体做一个归档备份放到独立的存储里。下次无论是扩容、重装节点还是搭建第二个环境你都能直接复用这份离线仓库。我因为这个习惯帮自己和团队省下了好多次在无外网环境下重新下载parcel的折磨也算是在CDH及软件安装部署这条路上走了几趟之后最想提醒大家的一件事。