能否通过Spark Kubernetes Operator控制Spark应用的总资源使用量?
解决Spark迁移K8s后动态资源分配全局资源失控问题
针对你提到的Spark从Standalone迁移到K8s后,多个开启动态资源分配的应用可能无限制扩容占用集群资源的问题,无需直接自行开发调度器,以下是几种可行的落地方案:
1. 基于K8s原生ResourceQuota做全局限制
给Spark应用所在的Namespace配置ResourceQuota,限定该Namespace下所有Pod的CPU、内存总请求/限制值。Spark的Driver和Executor都是K8s Pod,所有应用的资源总和会被这个配额约束,当总资源触达阈值时,新的Executor Pod会进入Pending状态,Spark的动态资源分配会自动停止扩容,直到有Executor释放资源。
示例ResourceQuota配置:
apiVersion: v1 kind: ResourceQuota metadata: name: spark-global-quota namespace: spark-apps spec: hard: requests.cpu: "100" requests.memory: "200Gi" limits.cpu: "150" limits.memory: "300Gi"
2. 轻量改造现有Spark Operator添加全局管控逻辑
基于官方或Kubeflow Spark Operator扩展,新增一个全局资源统计模块:
- 实时对接K8s API,统计当前Namespace下所有Spark Driver和Executor Pod的资源使用总和
- 在Operator处理SparkApplication的扩容请求时,校验总资源是否超过预设的全局阈值,若超过则拒绝新的Executor创建请求
- 也可以给单个SparkApplication配置最大扩容上限,结合全局阈值做双重管控
这种方案无需重写调度器,只是在现有Operator的控制器逻辑中增加校验环节,开发成本较低。
3. 利用Apache YuniKorn的队列配额机制
YuniKorn支持按队列设置资源配额,将所有Spark应用统一调度到指定队列,并给该队列设置最大资源上限:
- 在YuniKorn的配置中创建一个专门的Spark队列,设置
resources.max指定该队列的CPU、内存总配额 - 在Spark应用配置中指定调度器为YuniKorn:
spark.kubernetes.scheduler.name=yunikorn - 确保Spark应用的Pod被分配到目标队列(可通过YuniKorn的队列规则或Spark配置指定)
YuniKorn在调度时会严格管控队列内的总资源使用,当队列资源耗尽时,新的Executor Pod会进入等待状态,直到有资源释放。
4. 通过Volcano调度器的队列资源管控
Volcano同样支持队列级别的资源配额,配置方式类似YuniKorn:
- 创建Volcano Queue,设置
spec.resources.max限定队列的CPU、内存总资源 - 在Spark应用中指定调度器为Volcano:
spark.kubernetes.scheduler.name=volcano - 将Spark应用提交到该队列
Volcano会确保队列内所有Job(包括Spark的Executor Pod)的总资源不超过配额,避免集群资源被无限制占用。
内容的提问来源于stack exchange,提问作者KilyenOrs
相关产品推荐
相关产品推荐

