大数据开发入门必备:Hadoop 架构原理、集群规划、环境准备、安装配置、高可用配置、性能调优、故障排查,从 0 到 1 搭建生产级 Hadoop 集群
📌 前言
为什么学习 Hadoop 集群搭建?
面试必问:
- "你们公司 Hadoop 集群多大?"
- "NameNode 内存多少?"
- "如何配置高可用?"
- "遇到 DataNode 宕机怎么处理?"
有集群搭建经验,面试加分!
工作需要:
- 搭建测试环境(开发/测试)
- 扩容生产集群
- 故障排查和恢复
- 性能调优
学习价值:
- 理解 Hadoop 架构(NameNode/DataNode/ResourceManager)
- 掌握大数据生态(Hive/Spark/Flink 都依赖 Hadoop)
- 提升运维能力(监控/告警/故障处理)
🏗️ Hadoop 架构深度解析
Hadoop 核心组件
Hadoop 3.x 架构:
┌─────────────────────────────────────────────────────────────┐
│ HDFS(分布式文件系统) │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ NameNode │ ← 主节点 │ Secondary │ │
│ │ (元数据) │ │ NameNode │ │
│ └──────┬──────┘ └─────────────┘ │
│ │ │
│ ┌────┴────┬────────────┬────────────┐ │
│ ↓ ↓ ↓ ↓ │
│ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │
│ │Data │ │Data │ │Data │ │Data │ ← 数据节点 │
│ │Node │ │Node │ │Node │ │Node │ │
│ └──────┘ └──────┘ └──────┘ └──────┘ │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ YARN(资源调度系统) │
│ ┌─────────────┐ │
│ │ResourceManager│ ← 资源管理器 │
│ └──────┬──────┘ │
│ │ │
│ ┌────┴────┬────────────┬────────────┐ │
│ ↓ ↓ ↓ ↓ │
│ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │
│ │Node │ │Node │ │Node │ │Node │ ← 节点管理器 │
│ │Manager│ │Manager│ │Manager│ │Manager│ │
│ └──────┘ └──────┘ └──────┘ └──────┘ │
└─────────────────────────────────────────────────────────────┘
组件职责:
| 组件 | 职责 | 重要性 |
|---|---|---|
| NameNode | 管理 HDFS 元数据(文件/目录/权限) | ⭐⭐⭐⭐⭐ |
| DataNode | 存储实际数据块 | ⭐⭐⭐⭐⭐ |
| Secondary NameNode | 辅助 NameNode(合并 fsimage) | ⭐⭐⭐ |
| ResourceManager | 集群资源管理和调度 | ⭐⭐⭐⭐⭐ |
| NodeManager | 单节点资源管理 | ⭐⭐⭐⭐ |
Hadoop 高可用(HA)架构
生产环境必须配置 HA(避免单点故障):
┌─────────────────────────────────────────────────────────────┐
│ HDFS HA │
│ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ NameNode1 │ ←───→ │ NameNode2 │ │
│ │ (Active) │ Journal│ (Standby) │ │
│ │ │ Nodes │ │ │
│ └─────────────┘ └─────────────┘ │
│ ↑ ↑ │
│ └──────────┬──────────┘ │
│ ↓ │
│ ┌─────────────┐ │
│ │ ZooKeeper │ ← 故障转移 │
│ │ (Journal) │ │
│ └─────────────┘ │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ YARN HA │
│ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ResourceManager1│ ←─→ │ResourceManager2│ │
│ │ (Active) │ ZKFC │ (Standby) │ │
│ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────┘
HA 关键组件:
| 组件 | 作用 | 数量 |
|---|---|---|
| JournalNode | 共享编辑日志 | 3 或 5(奇数) |
| ZooKeeper | 故障检测和选举 | 3 或 5(奇数) |
| ZKFC | ZooKeeper 故障转移客户端 | 每个 NameNode 一个 |
📋 集群规划
生产环境推荐配置
小型集群(10 节点以下):
| 节点类型 | 数量 | CPU | 内存 | 磁盘 | 用途 |
|---|---|---|---|---|---|
| Master | 2 | 16 核 | 64GB | 500GB SSD | NameNode + RM |
| Worker | 5-10 | 32 核 | 128GB | 10TB HDD | DataNode + NM |
| 边缘节点 | 1 | 8 核 | 32GB | 500GB SSD | 客户端 |
中型集群(10-50 节点):
| 节点类型 | 数量 | CPU | 内存 | 磁盘 | 用途 |
|---|---|---|---|---|---|
| Master | 2 | 32 核 | 128GB | 1TB SSD | NameNode + RM |
| Worker | 10-50 | 32-64 核 | 256GB | 20-50TB | DataNode + NM |
| 边缘节点 | 2-5 | 16 核 | 64GB | 500GB SSD | 客户端 |
大型集群(50+ 节点):
| 节点类型 | 数量 | CPU | 内存 | 磁盘 | 用途 |
|---|---|---|---|---|---|
| Master | 3-5 | 64 核 | 256GB+ | 2TB SSD | NameNode + RM |
| Worker | 50+ | 64 核 | 512GB | 50TB+ | DataNode + NM |
| 边缘节点 | 5-10 | 16 核 | 64GB | 500GB SSD | 客户端 |
本教程集群规划(3 节点测试环境)
┌──────────────┬──────────────┬──────────────┐
│ hadoop1 │ hadoop2 │ hadoop3 │
│ 192.168.1.101│ 192.168.1.102│ 192.168.1.103│
├──────────────┼──────────────┼──────────────┤
│ NameNode │ NameNode │ │
│ (Active) │ (Standby) │ │
│ ResourceManager │ ResourceManager │ │
│ NodeManager │ NodeManager │ NodeManager │
│ DataNode │ DataNode │ DataNode │
│ JournalNode │ JournalNode │ JournalNode │
│ ZooKeeper │ ZooKeeper │ ZooKeeper │
└──────────────┴──────────────┴──────────────┘
软件版本:
- CentOS 7.9
- Hadoop 3.3.6
- JDK 1.8.0_301
- ZooKeeper 3.7.1
🔧 环境准备
1. 系统配置(所有节点)
主机名配置:
# 修改主机名
hostnamectl set-hostname hadoop1
hostnamectl set-hostname hadoop2
hostnamectl set-hostname hadoop3
# 配置 hosts
cat >> /etc/hosts << EOF
192.168.1.101 hadoop1
192.168.1.102 hadoop2
192.168.1.103 hadoop3
EOF
# 验证
ping hadoop1
ping hadoop2
ping hadoop3
关闭防火墙:
# 关闭防火墙
systemctl stop firewalld
systemctl disable firewalld
# 关闭 SELinux
setenforce 0
sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
# 验证
systemctl status firewalld # 应显示 inactive
getenforce # 应显示 Disabled
创建用户:
# 创建 hadoop 用户
useradd -m hadoop
passwd hadoop # 设置密码
# 配置 sudo(可选)
echo "hadoop ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
# 切换到 hadoop 用户
su - hadoop
2. JDK 安装(所有节点)
# 创建目录
sudo mkdir -p /opt/module
sudo chown hadoop:hadoop /opt/module
# 下载 JDK
cd /opt/module
wget https://download.oracle.com/java/8u301/jdk-8u301-linux-x64.tar.gz
# 解压
tar -zxvf jdk-8u301-linux-x64.tar.gz
mv jdk1.8.0_301 jdk1.8
# 配置环境变量
cat >> ~/.bashrc << 'EOF'
# JAVA
export JAVA_HOME=/opt/module/jdk1.8
export PATH=$PATH:$JAVA_HOME/bin
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
EOF
# 生效
source ~/.bashrc
# 验证
java -version
3. SSH 免密登录(所有节点)
# 生成密钥
ssh-keygen -t rsa # 一路回车
# 分发公钥(在 hadoop1 执行)
ssh-copy-id hadoop1
ssh-copy-id hadoop2
ssh-copy-id hadoop3
# 验证(无需密码)
ssh hadoop1
ssh hadoop2
ssh hadoop3
🔧 Hadoop 安装配置
1. Hadoop 安装(所有节点)
# 下载 Hadoop
cd /opt/module
wget https://archive.apache.org/dist/hadoop/common/hadoop-3.3.6/hadoop-3.3.6.tar.gz
# 解压
tar -zxvf hadoop-3.3.6.tar.gz
mv hadoop-3.3.6 hadoop-3.3.6
# 配置环境变量
cat >> ~/.bashrc << 'EOF'
# Hadoop
export HADOOP_HOME=/opt/module/hadoop-3.3.6
export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin
export HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoop
export YARN_CONF_DIR=$HADOOP_HOME/etc/hadoop
EOF
# 生效
source ~/.bashrc
# 验证
hadoop version
2. Hadoop 配置文件
core-site.xml:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<!-- HDFS 默认地址 -->
<property>
<name>fs.defaultFS</name>
<value>hdfs://mycluster</value>
</property>
<!-- 临时目录 -->
<property>
<name>hadoop.tmp.dir</name>
<value>/opt/module/hadoop-3.3.6/data/tmp</value>
</property>
<!-- 回收站时间(分钟) -->
<property>
<name>fs.trash.interval</name>
<value>1440</value>
</property>
<!-- 启用回收站 -->
<property>
<name>fs.trash.checkpoint.interval</name>
<value>1440</value>
</property>
<!-- ZooKeeper 地址 -->
<property>
<name>ha.zookeeper.quorum</name>
<value>hadoop1:2181,hadoop2:2181,hadoop3:2181</value>
</property>
</configuration>
hdfs-site.xml:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<!-- 副本数 -->
<property>
<name>dfs.replication</name>
<value>3</value>
</property>
<!-- NameNode 数据目录 -->
<property>
<name>dfs.namenode.name.dir</name>
<value>file:///opt/module/hadoop-3.3.6/data/namenode</value>
</property>
<!-- DataNode 数据目录 -->
<property>
<name>dfs.datanode.data.dir</name>
<value>file:///opt/module/hadoop-3.3.6/data/datanode</value>
</property>
<!-- 集群 ID -->
<property>
<name>dfs.nameservices</name>
<value>mycluster</value>
</property>
<!-- NameNode ID -->
<property>
<name>dfs.ha.namenodes.mycluster</name>
<value>nn1,nn2</value>
</property>
<!-- NameNode RPC 地址 -->
<property>
<name>dfs.namenode.rpc-address.mycluster.nn1</name>
<value>hadoop1:8020</value>
</property>
<property>
<name>dfs.namenode.rpc-address.mycluster.nn2</name>
<value>hadoop2:8020</value>
</property>
<!-- NameNode HTTP 地址 -->
<property>
<name>dfs.namenode.http-address.mycluster.nn1</name>
<value>hadoop1:9870</value>
</property>
<property>
<name>dfs.namenode.http-address.mycluster.nn2</name>
<value>hadoop2:9870</value>
</property>
<!-- JournalNode 地址 -->
<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://hadoop1:8485;hadoop2:8485;hadoop3:8485/mycluster</value>
</property>
<!-- 故障转移代理 -->
<property>
<name>dfs.client.failover.proxy.provider.mycluster</name>
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>
<!-- fencing 方法 -->
<property>
<name>dfs.ha.fencing.methods</name>
<value>sshfence</value>
</property>
<property>
<name>dfs.ha.fencing.ssh.private-key-files</name>
<value>/home/hadoop/.ssh/id_rsa</value>
</property>
<!-- JournalNode 数据目录 -->
<property>
<name>dfs.journalnode.edits.dir</name>
<value>/opt/module/hadoop-3.3.6/data/journalnode</value>
</property>
<!-- 启用自动故障转移 -->
<property>
<name>dfs.ha.automatic-failover.enabled</name>
<value>true</value>
</property>
</configuration>
yarn-site.xml:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<!-- 启用 ResourceManager HA -->
<property>
<name>yarn.resourcemanager.ha.enabled</name>
<value>true</value>
</property>
<!-- 集群 ID -->
<property>
<name>yarn.resourcemanager.cluster-id</name>
<value>mycluster</value>
</property>
<!-- ResourceManager ID -->
<property>
<name>yarn.resourcemanager.ha.rm-ids</name>
<value>rm1,rm2</value>
</property>
<!-- ResourceManager 地址 -->
<property>
<name>yarn.resourcemanager.hostname.rm1</name>
<value>hadoop1</value>
</property>
<property>
<name>yarn.resourcemanager.hostname.rm2</name>
<value>hadoop2</value>
</property>
<!-- ZooKeeper 地址 -->
<property>
<name>yarn.resourcemanager.zk-address</name>
<value>hadoop1:2181,hadoop2:2181,hadoop3:2181</value>
</property>
<!-- NodeManager 配置 -->
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<!-- 环境变量白名单 -->
<property>
<name>yarn.nodemanager.env-whitelist</name>
<value>JAVA_HOME,HADOOP_COMMON_HOME,HADOOP_HDFS_HOME,HADOOP_CONF_DIR,CLASSPATH_PREPEND_DISTCACHE,HADOOP_YARN_HOME,HADOOP_MAPRED_HOME</value>
</property>
<!-- 内存配置 -->
<property>
<name>yarn.scheduler.maximum-allocation-mb</name>
<value>8192</value>
</property>
<property>
<name>yarn.scheduler.minimum-allocation-mb</name>
<value>512</value>
</property>
<!-- 虚拟内存检查(关闭,避免任务被杀) -->
<property>
<name>yarn.nodemanager.vmem-check-enabled</name>
<value>false</value>
</property>
</configuration>
mapred-site.xml:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<!-- MapReduce 框架 -->
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
<!-- 历史服务器地址 -->
<property>
<name>mapreduce.jobhistory.address</name>
<value>hadoop1:10020</value>
</property>
<property>
<name>mapreduce.jobhistory.webapp.address</name>
<value>hadoop1:19888</value>
</property>
<!-- 内存配置 -->
<property>
<name>mapreduce.map.memory.mb</name>
<value>1024</value>
</property>
<property>
<name>mapreduce.reduce.memory.mb</name>
<value>2048</value>
</property>
<property>
<name>mapreduce.map.java.opts</name>
<value>-Xmx800m</value>
</property>
<property>
<name>mapreduce.reduce.java.opts</name>
<value>-Xmx1600m</value>
</property>
</configuration>
workers(从节点):
# 编辑 workers 文件
cat > $HADOOP_HOME/etc/hadoop/workers << EOF
hadoop1
hadoop2
hadoop3
EOF
3. ZooKeeper 配置(所有节点)
# 下载 ZooKeeper
cd /opt/module
wget https://archive.apache.org/dist/zookeeper/zookeeper-3.7.1/apache-zookeeper-3.7.1-bin.tar.gz
# 解压
tar -zxvf apache-zookeeper-3.7.1-bin.tar.gz
mv apache-zookeeper-3.7.1-bin zookeeper-3.7.1
# 创建数据目录
mkdir -p /opt/module/zookeeper-3.7.1/data
# 配置 myid(每个节点不同)
# hadoop1:
echo "1" > /opt/module/zookeeper-3.7.1/data/myid
# hadoop2:
echo "2" > /opt/module/zookeeper-3.7.1/data/myid
# hadoop3:
echo "3" > /opt/module/zookeeper-3.7.1/data/myid
# 配置 zoo.cfg
cat > /opt/module/zookeeper-3.7.1/conf/zoo.cfg << EOF
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/opt/module/zookeeper-3.7.1/data
clientPort=2181
# 集群配置
server.1=hadoop1:2888:3888
server.2=hadoop2:2888:3888
server.3=hadoop3:2888:3888
EOF
🚀 集群启动
1. 分发配置(在 hadoop1 执行)
# 分发 Hadoop
scp -r /opt/module/hadoop-3.3.6 hadoop2:/opt/module/
scp -r /opt/module/hadoop-3.3.6 hadoop3:/opt/module/
# 分发 ZooKeeper
scp -r /opt/module/zookeeper-3.7.1 hadoop2:/opt/module/
scp -r /opt/module/zookeeper-3.7.1 hadoop3:/opt/module/
# 分发环境变量
scp ~/.bashrc hadoop2:~
scp ~/.bashrc hadoop3:~
2. 启动顺序
第一步:启动 ZooKeeper(所有节点):
# 在所有节点执行
/opt/module/zookeeper-3.7.1/bin/zkServer.sh start
# 验证
/opt/module/zookeeper-3.7.1/bin/zkServer.sh status
# 应显示 leader 或 follower
第二步:初始化 HDFS(仅 hadoop1):
# 格式化 NameNode(仅第一次)
hdfs namenode -format
# 初始化共享存储
hdfs zkfc -formatZK
# 启动 JournalNode
hdfs --daemon start journalnode
第三步:启动 HDFS(所有节点):
# 启动 DataNode
hdfs --daemon start datanode
# 启动 ZKFC(故障转移)
hdfs --daemon start zkfc
第四步:启动 YARN(所有节点):
# 启动 ResourceManager
yarn --daemon start resourcemanager
# 启动 NodeManager
yarn --daemon start nodemanager
3. 验证集群
HDFS 验证:
# 查看 NameNode 状态
hdfs haadmin -getServiceState nn1
hdfs haadmin -getServiceState nn2
# 应显示 active 和 standby
# 查看 HDFS 空间
hdfs dfsadmin -report
# 测试 HDFS
hdfs dfs -mkdir /test
hdfs dfs -put /etc/hosts /test
hdfs dfs -ls /test
YARN 验证:
# 查看节点
yarn node -list
# 提交测试任务
hadoop jar $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.3.6.jar pi 10 100
# 查看应用
yarn application -list
Web UI 验证:
HDFS NameNode:
- http://hadoop1:9870
- http://hadoop2:9870
YARN ResourceManager:
- http://hadoop1:8088
- http://hadoop2:8088
⚠️ 常见故障排查
故障 1:DataNode 无法启动
现象:
hdfs dfsadmin -report
DataNodes: 0
排查:
# 1. 查看日志
tail -100 $HADOOP_HOME/logs/hadoop-hadoop-datanode-hadoop1.log
# 2. 常见原因
# - 磁盘空间不足
df -h
# - 端口被占用
netstat -tunlp | grep 9864
# - 权限问题
ls -ld /opt/module/hadoop-3.3.6/data/datanode
# 3. 解决方案
# 清理数据目录(测试环境)
rm -rf /opt/module/hadoop-3.3.6/data/datanode/*
# 重新启动
hdfs --daemon stop datanode
hdfs --daemon start datanode
故障 2:NameNode 无法切换 Active
现象:
hdfs haadmin -getServiceState nn1
# 一直显示 standby
排查:
# 1. 查看 ZKFC 日志
tail -100 $HADOOP_HOME/logs/hadoop-hadoop-zkfc-hadoop1.log
# 2. 检查 ZooKeeper
/opt/module/zookeeper-3.7.1/bin/zkCli.sh
ls /hadoop-ha
# 3. 检查 fencing
# 确保 SSH 免密配置正确
ssh hadoop1 hostname
# 4. 手动切换
hdfs haadmin -transitionToActive nn1 --forceactive
故障 3:YARN 任务失败
现象:
Container killed by YARN for exceeding memory limits
解决:
<!-- yarn-site.xml -->
<property>
<name>yarn.nodemanager.vmem-check-enabled</name>
<value>false</value>
</property>
<!-- mapred-site.xml -->
<property>
<name>mapreduce.map.memory.mb</name>
<value>2048</value>
</property>
<property>
<name>mapreduce.map.java.opts</name>
<value>-Xmx1600m</value>
</property>
📋 性能调优
HDFS 调优
<!-- hdfs-site.xml -->
<!-- NameNode 内存优化 -->
<property>
<name>dfs.namenode.handler.count</name>
<value>100</value>
</property>
<!-- 数据块大小 -->
<property>
<name>dfs.blocksize</name>
<value>134217728</value> <!-- 128MB -->
</property>
<!-- 副本放置策略 -->
<property>
<name>dfs.namenode.replication.rack-awareness.policy</name>
<value>org.apache.hadoop.hdfs.server.namenode.RackAwarePlacerDefaultImpl</value>
</property>
YARN 调优
<!-- yarn-site.xml -->
<!-- ResourceManager 内存 -->
<property>
<name>yarn.resourcemanager.scheduler.maximum-allocation-mb</name>
<value>16384</value>
</property>
<!-- NodeManager 内存 -->
<property>
<name>yarn.nodemanager.resource.memory-mb</name>
<value>32768</value>
</property>
<!-- 虚拟 CPU 核心数 -->
<property>
<name>yarn.nodemanager.resource.cpu-vcores</name>
<value>16</value>
</property>
📋 最佳实践清单
安装部署
- 配置主机名和 hosts
- 关闭防火墙和 SELinux
- 配置 SSH 免密登录
- 配置 NTP 时间同步
- 配置 HA(生产环境必须)
参数配置
- 合理设置副本数(测试 1,生产 3)
- 配置数据目录(多磁盘)
- 开启回收站
- 配置日志级别
监控运维
- 配置监控告警(Prometheus + Grafana)
- 定期清理日志
- 定期备份元数据
- 定期巡检(磁盘/CPU/内存)
安全加固
- 配置 Kerberos(生产环境)
- 配置 Ranger(权限管理)
- 开启审计日志
- 限制访问 IP
📌 总结
核心要点
| 组件 | 关键配置 | 重要性 |
|---|---|---|
| HDFS HA | JournalNode + ZooKeeper | ⭐⭐⭐⭐⭐ |
| YARN HA | ResourceManager HA | ⭐⭐⭐⭐⭐ |
| 参数调优 | 内存 + 并行度 | ⭐⭐⭐⭐ |
| 监控告警 | Prometheus + Grafana | ⭐⭐⭐⭐ |
实践原则
1. 测试环境从简
3 节点即可,快速验证
2. 生产环境 HA
必须配置高可用,避免单点故障
3. 监控先行
先配置监控,再上线业务
4. 文档沉淀
记录配置和故障处理
💡 Hadoop 集群搭建是大数据工程师的基本功,建议动手实践!
👋 感谢阅读!
🔗 系列文章
- [01-SQL 窗口函数从入门到精通](./01-SQL 窗口函数从入门到精通.md)
- [02-Spark 性能优化 10 个技巧](./02-Spark 性能优化 10 个技巧.md)
- 03-数据仓库分层设计指南
- 04-维度建模实战
- [05-Flink 实时数仓实战](./05-Flink 实时数仓实战.md)
- [06-Kafka 消息队列实战指南](./06-Kafka 消息队列实战指南.md)
- [07-Hive 性能优化实战](./07-Hive 性能优化实战.md)
- [08-Linux 大数据开发必备工具](./08-Linux 大数据开发必备工具.md)
- [09-缓慢变化维 SCD Type 2 详解](./09-缓慢变化维 SCD Type2 详解.md)
- [10-Flink 时间语义与 Watermark 详解](./10-Flink 时间语义与 Watermark 详解.md)
- 11-Hadoop 集群搭建完整教程(本文)
- [下一篇:Spark SQL 进阶实践](./12-Spark SQL 进阶实践.md)