上一篇讲了 Hadoop 生态。本篇讲现代大数据栈的演进——对象存储和 Kubernetes 如何逐步替代 HDFS 和 YARN。

云原生大数据栈常被简化成"把 Hadoop 搬到云上"。这个简化漏了核心架构变化。准确的说法是:现代大数据栈把 Hadoop 的"存储 + 计算 + 编排"三层各自独立演化——存储层从 HDFS 切到 S3 / OSS 等对象存储(彻底解耦存储与计算)、计算层从 MapReduce 演进到 Spark / Flink(内存优先 + 流批一体)、编排层从 YARN 切到 Kubernetes(弹性扩缩容 + 多租户隔离)。三层解耦后每个组件独立演化、独立计费、独立运维,让大数据栈从"集成式 Hadoop 集群"变成"组合式数据平台"。

本篇只抓一个问题:对象存储为什么能取代 HDFS、Spark on K8s 现在能取代 YARN 多少、现代大数据栈与 Hadoop 的具体架构差异、什么场景应该选哪种。

存储层:HDFS vs 对象存储

HDFS 在 Hadoop 1.x 时代是大数据存储的事实标准。它的核心设计是"专用集群 + NameNode 元数据 + DataNode 块存储"——节点既存数据又跑计算,通过本地读实现高吞吐。

对象存储(S3 2006、OSS 2013、GCS 2010、Azure Blob 2009)是公有云提供的托管存储服务。用户不接触底层节点,通过 HTTP API 读写 object。

两者的核心架构差异:

1
2
3
4
5
6
7
8
9
10
11
12
                          HDFS                         对象存储(S3 / OSS)
───────────────── ────────────────────── ──────────────────────────
存储模型 文件 + 目录 + Block Object + Bucket + Key
元数据 NameNode 全内存 Object metadata 服务
API POSIX-like(hdfs 命令) HTTP REST(PUT / GET)
一致性 Strong(写入立即可见) 全局强一致读写(2020-12 起)
延迟 低延迟本地/机架内访问 HTTP + 远端服务调用,需实测
吞吐 受集群规模限制 接近无限(按 object 并行)
元数据操作延迟 NameNode 内存元数据路径 远端元数据服务调用,需实测
持久性 3 副本 后端 11 个 9(多 AZ + EC)
运维 自建集群 + DIY 托管服务,按使用付费
成本模型 节点固定(CAPEX) 按 GB 月 + 请求次数(OPEX)

对象存储的几个关键优势让它逐步取代 HDFS:

第一,运营成本。HDFS 集群的固定节点成本与数据量线性相关——10 PB 数据需要至少 30 PB 物理存储(3 副本)+ NameNode 内存 + 运维人力。对象存储按 GB 月、请求次数和数据传输计费,不需要采购节点、不需要 NameNode 运维。具体谁更便宜要按当期云厂商价格、保留周期、请求量、出网费用和运维成本测算。

第二,弹性。HDFS 集群扩容需要采购新节点、配置机架、平衡数据(DataNode rebalancing 耗时几天)。对象存储容量"无限",无需规划扩容。

第三,持久性。S3 标准存储承诺 11 个 9(99.999999999%)的持久性,通过多 AZ + 纠删码实现。HDFS 3 副本在多个节点同时宕机时仍然可能丢数据(虽然概率极低)。

第四,与计算解耦。HDFS 的"计算与数据同节点"假设让集群规模与数据量绑定。对象存储的"存储独立、计算拉取"模式让计算集群可以按需扩缩,不需要承担存储责任。

代价是延迟和元数据操作效率。HDFS 可以利用节点本地或机架内访问,对象存储要经过 HTTP 与远端服务调用。MapReduce / Spark 的"数据本地化"优化在对象存储上失效——所有数据都要通过网络拉取,性能表现需要按对象大小、并发度和提交协议实测。

Hadoop 的对象存储支持并非都在 3.x 同时引入:S3A 随 Hadoop 2.6.0 落地,ABFS 是 3.2.0 的重点能力;Apache Hadoop 原生 gs:// connector 到 3.5.0 才加入,不属于本系列 3.4.1 基线。工具链从 HDFS 切换到对象存储仍需针对延迟、rename 和提交协议调优。

计算层:YARN vs Kubernetes

YARN 是 Hadoop 2.x 引入的资源管理层。它的设计假设是“长期集群 + 固定节点 + Container 配额”。默认 DefaultContainerExecutor 直接启动本地进程,不限 JVM;只有配置 LinuxContainerExecutor 与 cgroups resource handler 后才获得 cgroups 隔离。

Kubernetes 是云原生时代的容器编排标准(Google 2014 开源,灵感来自 Borg)。K8s 通过 CRI 使用 containerd、CRI-O 等 runtime;Docker dockershim 已在 Kubernetes 1.24 移除。Pod 启动耗时取决于镜像缓存、runtime 和存储网络。

两者的核心架构差异:

1
2
3
4
5
6
7
8
9
10
11
                          YARN                          Kubernetes
───────────────── ────────────────────── ──────────────────────────
调度单位 Container Pod
隔离 默认进程监控;可配 cgroups namespace + cgroups + 容器
镜像 jar 文件(HDFS) OCI Image(Docker Registry)
启动开销 几秒 毫秒到几十秒
网络 每 container 使用节点网络端口 每 Pod 一个 IP;Pod 内 container 共享网络
存储挂载 本地目录 PersistentVolume / hostPath
弹性扩缩 不擅长(固定节点) Autoscaler 原生支持
多租户 通过队列 ACL 通过 namespace + RBAC
生态 Hadoop 工具链 云原生全栈

K8s 相对 YARN 的几个关键优势:

第一,弹性。K8s 集群可以按需扩缩节点(Cluster Autoscaler),作业提交时按需拉起 Pod,作业完成后释放。YARN 集群通常是固定的,扩容需要采购节点。云上 K8s(EKS / AKS / GKE)可以与云的弹性计算(EC2 / VM)联动,让大数据作业真正按需付费。

第二,多语言。YARN 默认是 JVM 生态(Container 启动 JVM 跑 task),非 JVM 任务(Python 训练脚本、C++ 计算库)需要包装层。K8s 的容器天然支持任何语言、任何运行时——Spark / Flink / TensorFlow / PyTorch / 自定义训练任务都可以跑。

第三,生态。K8s 有海量 Operator(数据库 Operator、消息队列 Operator、AI 训练 Operator),让大数据栈与云原生生态无缝集成。YARN 的生态局限于 Hadoop 项目内。

第四,可观测性。K8s 的 Prometheus + Grafana + Fluentd + Jaeger 是事实标准。YARN 的监控是 Hadoop 特有的(Metrics V2 + History Server),不如 K8s 标准化。

代价是延迟和稳定性。YARN Container 启动比 K8s Pod 快(JVM 已 cache,几秒;K8s 第一次拉镜像可能几十秒)。短作业(几秒到几分钟)在 YARN 上启动开销小于 K8s。

K8s 上的 Spark(Spark on K8s,Spark 2.3+)已经在很多场景替代 Spark on YARN。但 K8s 上的 Flink 仍然不如 YARN 成熟(Flink 的 State Backend 与 K8s PersistentVolume 集成有挑战)。MapReduce 几乎不在 K8s 上跑(没必要——MapReduce 是 Hadoop 老技术,新作业用 Spark / Flink)。

现代大数据栈的典型架构

云原生大数据栈的典型部署:

1
2
3
4
5
6
7
8
9
10
11
1. 存储:S3 / OSS / GCS(核心数据湖)+ HDFS(兼容性,可选)
2. 表格:Iceberg / Hudi / Delta Lake(在对象存储之上提供 ACID + Schema Evolution)
3. 计算:
- 批处理:Spark on K8s
- 流处理:Flink on K8s
- 交互式 SQL:Trino / Athena / Snowflake
- 实时 OLAP:ClickHouse / Druid / Pinot
4. 编排:K8s(计算) + Argo Workflows / Airflow(作业)
5. 元数据:AWS Glue / DataHub / Amundsen
6. 监控:Prometheus + Grafana
7. CI/CD:GitOps(ArgoCD / Flux)

这个 stack 与 Hadoop 时代的对比:

Hadoop 时代:"HDFS + YARN + Hive + MapReduce"是一个集成产品,所有组件来自 Apache Hadoop 生态。

云原生时代:每个层独立选择最佳组件,组合成数据平台。存储用对象存储,表格用 Iceberg / Hudi,计算用 Spark / Flink,SQL 用 Trino,编排用 K8s,监控用 Prometheus。

这种"组合式"架构让用户不被绑死在单一供应商,可以根据需求替换组件。但代价是集成复杂度上升——需要懂多个组件,而不是只懂 Hadoop。

数据湖格式:Iceberg / Hudi / Delta Lake

对象存储之上构建数据湖有一个核心问题——对象存储本身没有 ACID 事务、Schema Evolution、Time Travel 这些数据库特性。直接在 S3 上做"insert into / update / delete"很难(需要重写整个 object)。

数据湖格式(Netflix Iceberg 2018、Uber Hudi 2017、Databricks Delta Lake 2019)填补了这个空白。它们在对象存储之上构建"表格层",提供:

ACID 事务:多个写入者并发修改同一表,保证一致性。

Schema Evolution:添加 / 删除 / 重命名列不需要重写历史数据。

Time Travel:查询历史版本的表数据(例如查询昨天的状态)。

Upsert / Delete:支持 UPDATE 和 DELETE 操作(HDFS 时代不支持)。

这三种格式的设计略有差异(Iceberg 偏查询性能、Hudi 偏流式 upsert、Delta Lake 偏 Databricks 集成),但核心目标一致——让对象存储变成"可更新的数据库"。

数据湖格式直接挑战 Hive 的地位。Hive 的表格抽象(目录 + 文件)已经过时——现代 stack 用 Iceberg / Hudi 替代 Hive,但仍然用 Hive Metastore 做 schema 共享(Hive 留下的最大遗产)。

哪些场景仍然选 Hadoop

虽然云原生 stack 在很多场景取代 Hadoop,但 Hadoop 仍然在某些场景有优势:

第一,受监管行业的数据不能离开本地数据中心。银行、电信、政府的核心数据合规要求不允许部署到公有云。这种场景必须自建集群,Hadoop 仍然是自建大数据栈的最佳选择(成熟、稳定、文档齐全)。

第二,超大规模数据 + 高频本地计算。如果一个公司每天处理 PB 级数据,从对象存储拉数据的网络成本(云上 egress 费用)可能超过自建 HDFS 的成本。这种场景 HDFS 的"数据本地化"仍然有经济优势。

第三,已有 Hadoop 团队和工具链。如果公司已经投入大量人力维护 Hadoop 集群、有完善的 Hive / HBase 应用,迁移到云原生栈的迁移成本可能超过短期收益。这种场景应该渐进演化(例如在 Hadoop 之上加 Spark,逐步用对象存储替代部分 HDFS),而不是一刀切迁移。

第四,对延迟敏感的本地访问。HBase / HDFS 的本地读延迟(毫秒级)显著优于对象存储(HTTP 几十毫秒)。对延迟极敏感的场景(实时风控、广告投放)仍然需要本地存储。

其他场景(新项目、云上部署、小规模数据)应该优先考虑云原生 stack——成本更低、运维更简单、技术栈更现代化。

实验:观察两种 stack 的对比

实验状态:UNVERIFIED_RUNTIME。下面是验证步骤,本轮没有连接真实 Hadoop、Kubernetes 或云对象存储环境执行。

如果你的环境同时有 Hadoop 集群和 K8s 集群,提交同一个 Spark 作业到两个 stack:

1
2
3
4
5
# Spark on YARN
spark-submit --master yarn --deploy-mode cluster --class org.apache.spark.examples.SparkPi spark-examples_2.12-3.5.0.jar 1000

# Spark on K8s
spark-submit --master k8s://https://k8s-api:6443 --deploy-mode cluster --conf spark.kubernetes.container.image=spark:3.5.0 --class org.apache.spark.examples.SparkPi local:///opt/spark/examples/jars/spark-examples_2.12-3.5.0.jar 1000

观察两个作业的启动开销、执行时间、资源使用。K8s 上的 Spark 启动时间受镜像缓存、runtime 和网络影响;YARN 作业受队列、AM 启动和本地资源分发影响。不要在没有同环境实验前写固定优劣。

对象存储与 HDFS 的性能对比:

1
2
3
4
5
6
7
8
9
# 写入 100GB 数据到 HDFS
hadoop fs -put /local/100gb /hdfs/

# 写入 100GB 数据到 S3
aws s3 cp /local/100gb s3://bucket/

# 时间对比
# HDFS:以实际集群带宽和副本写入路径为准
# S3:以实际区域、并发度、对象大小和网络路径为准

对象存储写入和读取吞吐都取决于并发度、对象大小、网络路径和 connector 配置。读取可以通过并发 object 拉取提升吞吐,但 rename、commit 和大量小对象仍然是迁移时要实测的瓶颈。

模式提炼

现代大数据栈的演进体现的设计模式:

1
2
3
4
5
6
7
模式:分层解耦 + 托管服务 + 弹性扩缩 + 组合式架构

- 存储与计算解耦,各自独立演化
- 优先用托管服务(对象存储 / 托管 K8s / 托管 Spark)
- 弹性扩缩容(按需付费,不预留资源)
- 数据湖格式提供表格语义(ACID / Schema Evolution)
- 多组件组合(每个层选最佳组件,不绑死单一供应商)

这个模式与 Hadoop 时代的"集成式集群"形成对比。Hadoop 假设"所有组件来自 Apache Hadoop 项目",云原生 stack 假设"每个组件来自不同供应商,通过标准 API 集成"。

云原生大数据栈是 Hadoop 设计思想的进一步演化——Hadoop 提出的"分而治之 + 副本容错"在云原生时代仍然成立,只是实现方式从"自建集群"变成"组合托管服务"。

工程迁移表

Hadoop 概念 AWS 对应 Azure 对应 GCP 对应 开源对应
HDFS S3 ADLS Gen2 GCS MinIO / Ceph
YARN EMR / EKS AKS GKE / Dataproc Kubernetes
MapReduce EMR MapReduce HDInsight MapReduce Dataproc Spark / Flink
Hive Athena Synapse BigQuery Trino / Spark SQL
HBase DynamoDB Cosmos DB Bigtable Cassandra
Oozie Step Functions Logic Apps Workflows Argo Workflows
Flume Kinesis Event Hubs Pub/Sub Kafka + Kafka Connect
Hue QuickSight Power BI Looker Superset

三大云厂商都提供 Hadoop 兼容托管服务(EMR、HDInsight、Dataproc)。对象存储常作为推荐的数据湖存储;Kubernetes 或 serverless 是 EMR on EKS、Dataproc Serverless 等分支形态,不能概括成所有传统托管 Hadoop 都已从 YARN 切到 K8s。

常见误解

误解一:“对象存储完全取代了 HDFS”。对象存储在云上确实占主导,但自建数据中心里 HDFS 仍然广泛使用——监管行业、超大规模数据、对延迟敏感的场景。对象存储不是 HDFS 的完全替代品,是另一种部署选择。

误解二:“K8s 完全取代了 YARN”。K8s 在新部署里占主导,但 YARN 在已有 Hadoop 集群里仍然大量使用。Spark on K8s 的功能集在 Spark 3.x 才接近 Spark on YARN,Flink on K8s 仍然不如 Flink on YARN 成熟。

误解三:“迁移到云原生 stack 总是更便宜”。云原生 stack 减少了运维人力成本,但增加了云服务费用。对超大规模数据(PB+),云上 egress 费用 + 存储费用可能超过自建 Hadoop 成本。要做 TCO 测算,不能盲目假设云更便宜。

误解四:“数据湖格式(Iceberg / Hudi)取代了 Hive Metastore”。数据湖格式取代了 Hive 的表格抽象,但仍然用 Hive Metastore 做 schema 共享。Hive Metastore 是开源大数据生态的事实标准,被 Spark / Trino / Flink / Iceberg / Hudi 共同使用。

误解五:“Hadoop 已经死了,所有项目都应该迁移”。Hadoop 在受监管行业、超大规模数据、对延迟敏感的场景仍然有市场。盲目迁移可能成本超过收益。新项目优先云原生 stack,存量 Hadoop 按需渐进演化。

练习

  1. 在云上(AWS / Azure / GCP)创建一个 EMR / HDInsight / Dataproc 集群,观察底层存储是不是 HDFS(通常已经是对象存储)。提交一个 Hive 查询,对比与本地 Hadoop 集群的性能差异。

  2. 在 K8s 集群上提交一个 Spark 作业(Spark on K8s),观察 Driver Pod 和 Executor Pod 的启动过程。对比与 Spark on YARN 的启动开销差异。

  3. 阅读一篇数据湖格式的设计文档(Iceberg Spec 或 Delta Lake Protocol),理解它们在对象存储之上如何实现 ACID。

  4. 思考题:如果一个公司有 5 PB 历史数据存在自建 Hadoop 集群,想迁移到云原生 stack,应该按什么顺序迁移?哪些数据应该先迁移、哪些后迁移、迁移过程中如何保证业务连续性?

系列导航

序号 主题 状态
00 导读:节点总会失败
01 HDFS 架构与三层切分
02 文件写入路径与流水线
03 文件读取路径与副本选择
04 NameNode 内存模型与启动恢复
05 HDFS HA 与脑裂防御
06 HDFS 3.x 演进与纠删码
07 YARN 架构与三方契约
08 YARN 资源模型、Container 与 NodeLabel
09 YARN 调度器对比:FIFO、Capacity、Fair
10 YARN 应用程序生命周期
11 YARN HA 与 Federation
12 YARN Timeline Service v2
13 MapReduce 编程模型与分而治之
14 MapReduce Shuffle 全流程
15 MRv2 on YARN ApplicationMaster 与 Task Attempt
16 Hadoop RPC 协议栈
17 序列化与压缩
18 Hadoop 安全 Kerberos Token ProxyUser
19 监控与运维 Metrics JMX 日志聚合
20 Hadoop 生态 Hive HBase Pig 上一篇
21 Hadoop 与对象存储 Kubernetes 演进对比 本篇
22 Hadoop 设计遗产从 GFS MapReduce 到云原生 下一篇

参考资料