对持续运行的大规模分析平台来说,Spark 作业能否按时开始,往往不只取决于代码和数据,还取决于指定规格的虚拟机当时是否有库存。固定机型、固定可用区的配置看似确定,遇到区域容量波动时却可能让整个数据管道停在集群创建阶段。
Yahoo 在 Google Cloud Managed Service for Apache Spark(原 Dataproc)中采用弹性 VM:为集群提供一组按优先级排列的可接受机型,并启用 Auto-Zone placement,让服务在整个区域内寻找容量。按照来源披露的数据,这一方案将由区域容量不足引起的集群预配失败减少了 85%。
固定机型为什么会成为单点约束
典型的静态配置同时锁定了两个条件:
- 集群只能在一个指定可用区创建;
- 主节点或工作节点只能使用一种机器类型。
只要该可用区暂时缺少对应机型,即使同一区域内的其他可用区或相近规格仍有容量,集群也可能延迟创建或直接失败。团队随后只能增加重试逻辑、临时修改机型,或者人工切换可用区。这些补救措施会把基础设施库存问题传播到 Airflow DAG、定时批处理任务和下游数据 SLA。
弹性 VM 的做法不是无限制地接受任何机器,而是提前定义一份容量策略。例如,将 e2-standard-8 设为首选,将 n2-standard-8 设为后备。当首选资源不可用时,服务可以继续尝试后备选项,而不必修改流水线代码。
其中,机型回退和跨区搜索必须配合使用。只配置候选机型却仍固定在单个 zone,能够搜索的容量范围依然有限;应传入区域并使用空 zone,让 Managed Service for Apache Spark 在该区域内执行 Auto-Zone placement。
一份可以直接改造的 gcloud 配置
下面的命令创建一个包含 10 个工作节点的集群。运行前需要完成 gcloud auth login,设置可用的项目 ID,并根据实际部署位置修改 REGION、集群名和机型列表。
export PROJECT_ID="your-project-id"
export REGION="us-central1"
export CLUSTER_NAME="analytics-cluster"
gcloud config set project "${PROJECT_ID}"
gcloud dataproc clusters create "${CLUSTER_NAME}" \
--region="${REGION}" \
--zone="" \
--num-workers=10 \
--master-instance-selection='{"machineTypes":["e2-standard-8"],"rank":0}' \
--master-instance-selection='{"machineTypes":["n2-standard-8"],"rank":1}' \
--worker-instance-selection='{"machineTypes":["e2-standard-8"],"rank":0}' \
--worker-instance-selection='{"machineTypes":["n2-standard-8"],"rank":1}'
这里有两个关键点:
--zone=""与--region共同启用区域级容量搜索;rank: 0是优先选项,数值更大的排名作为后备。
如果集群由编排系统创建,可以把同样的策略放进 Dataproc API 请求。以下请求体假设弹性策略应用于 8 个 secondary workers,可用于改造内部部署程序或 Managed Service for Apache Airflow DAG:
{
"projectId": "PROJECT_ID",
"clusterName": "analytics-cluster",
"config": {
"gceClusterConfig": {
"zoneUri": ""
},
"secondaryWorkerConfig": {
"numInstances": 8,
"instanceFlexibilityPolicy": {
"instanceSelectionList": [
{
"machineTypes": ["n2-standard-8"],
"rank": 0
},
{
"machineTypes": ["e2-standard-8", "t2d-standard-8"],
"rank": 1
}
]
}
}
}
}
实际接入时,还需要由调用方补充项目、区域、认证信息以及 API 所要求的其他集群字段。不要在 DAG 中临时拼接随机候选机型;更稳妥的方式是把批准的机型和排名维护成版本化配置,使变更可以审查和回滚。
弹性不等于机型可以随意混用
候选列表扩大了容量搜索范围,但各机型仍需保持资源对称,尤其是在启用 autoscaling 时。
保持核心数和内存接近。 主工作节点与辅助工作节点使用的候选机型,应具有相同或相近的 vCPU 数量和内存容量。若差距过大,扩容后的 executor 行为可能不一致。
统一 CPU 与内存比例。 YARN 和 Spark 的容器尺寸会受到工作节点资源比例影响。混用比例差异明显的机型时,最小比例可能成为有效容器配置的限制,造成部分机器资源闲置,甚至引入性能退化。
检查组件属性。 Managed Service for Apache Spark 会根据 VM 的核心数和内存推导系统属性。如果不同机型系列的可用资源或系统预留存在差异,应显式设置相关 YARN、Spark executor 和内存参数,并通过基准作业验证,而不是只确认集群能够创建。
区分普通容量与 Spot 容量。 secondary workers 可以承担更有弹性的负载,但使用 Spot 或高度动态的容量时,Spark 作业必须能承受节点丢失。涉及 shuffle 的任务需要采用可恢复的设计,避免单个辅助节点被回收后导致大范围 stage 重算或任务失败。
把候选列表升级为基础设施政策
大规模环境不应让每个团队自行选择回退机型。平台团队可以维护统一政策,至少覆盖以下内容:
- 每个区域允许使用的首选 VM 系列与后备系列;
- 默认启用 Auto-Zone placement;
- autoscaling 集群允许的核心数、内存和 CPU/内存比例;
- 必须显式覆盖的 YARN 与 Spark 属性;
- secondary workers 使用 Spot 时的 shuffle 与重试要求;
- 不同机型之间的价格边界以及 Flexible CUD 等成本策略;
- 集群创建失败率、候选机型命中率和启动耗时的监控指标。
候选顺序也可以承担硬件演进的作用:把新一代机型设为首选,把经过验证的旧机型保留为后备。这样可以逐步提高新硬件使用率,同时避免在新机型库存紧张时阻塞关键任务。
上线前检查
采用弹性 VM 前,先找出绑定特定机型、CPU 指令集或可用区的工作负载,再用代表性的批处理和流处理任务验证性能。上线时应从非关键集群开始,观察不同候选机型下的 executor 数量、容器尺寸、shuffle 稳定性、作业时长和成本。
弹性配置解决的是资源可获得性,而不是自动消除所有性能与成本差异。只有将跨区放置、规格对称、运行时参数和可观测性一起纳入标准,机型回退才能从一次性的故障规避手段,变成可预测的集群预配机制。