如果您已经拥有多个正在运行在线服务的ACK集群,并希望在不影响这些服务的情况下,充分利用集群的空闲资源来运行Spark作业,您可以利用ACK One舰队的多集群Spark作业调度和分发能力来提高资源利用率。本文将介绍如何通过ACK One舰队和ACK Koordinator组件,根据各集群实际剩余资源(而非请求资源)来调度和分发多集群Spark作业,帮助您最大化多集群中闲置资源的利用效率,并通过优先级控制和离线混合部署能力,确保在线服务的正常运行。
背景信息
基于集群实际剩余资源的多集群Spark作业的调度和分发方案,主要依赖以下三部分能力:
ACK One舰队的多集群Spark作业的调度和分发,包括对实际剩余资源的感知调度。
ACK Spark Operator支持Koordinator在离线混部特性。
ACK Koordinator的单集群在离线混部能力。
整体流程如下:
将多个ACK集群关联到舰队,并在各关联集群中安装ACK Koordinator组件和ACK Spark Operator组件。
为舰队创建
SparkApplication
和PropagationPolicy
。舰队的多集群调度组件(Global Scheduler)会根据每个关联子集群的剩余资源,来匹配Spark作业资源请求完成调度。
对集群版本为1.28及以上的子集群,舰队支持通过资源预占来提高Spark作业调度的成功率。
舰队调度完作业后,通过多集群应用分发
SparkApplication
至调度选中的关联集群中。在关联集群中,ACK Spark Operator负责运行Spark作业的
driver
和executor
。同时舰队会监视子集群中Spark作业运行状态,若driver
由于资源不足而无法运行,舰队会在一定时间后回收该SparkApplication
,并重调度到其他资源充足的关联集群中。
前提条件
舰队实例已添加多个关联集群,且关联集群版本为1.18及以上。具体操作,请参见管理关联集群。
已授予RAM用户AliyunAdcpFullAccess权限。具体操作,请参见为RAM用户授权。
已安装AMC命令行工具。
子集群已安装ack-spark-operator组件,且版本为2.1.2及以上。
步骤一:在关联集群中配置ack-koordinator
登录容器服务管理控制台,在左侧导航栏选择集群列表。
在集群列表页面,单击目标集群名称,然后在左侧导航栏,选择 。
在配置项页面,单击使用YAML创建资源,使用以下示例内容添加配置。详情请参见在离线混部快速入门。
#ConfigMap ack-slo-config样例。 apiVersion: v1 kind: ConfigMap metadata: name: ack-slo-config namespace: kube-system data: colocation-config: |- { "enable": true } resource-qos-config: |- { "clusterStrategy": { "lsClass": { "cpuQOS": { "enable": true }, "memoryQOS": { "enable": true }, "resctrlQOS": { "enable": true } }, "beClass": { "cpuQOS": { "enable": true }, "memoryQOS": { "enable": true }, "resctrlQOS": { "enable": true } } } } resource-threshold-config: |- { "clusterStrategy": { "enable": true } }
步骤二:(可选)在舰队中创建命名空间,并下发到子集群
在各子集群安装ack-spark-operator之前,需要确保各子集群已有待分发的spark应用的命名空间,否则组件安装会异常。可以通过在舰队中创建命名空间,使用ClusterPropagationPolicy
将其分发至各集群。本文示例命名空间为spark
。
使用舰队的KubeConfig连接舰队实例,执行以下命令,创建相应命名空间。
kubectl create ns spark
使用
ClusterPropagationPolicy
将舰队的命名空间下发至指定子集群,如想下发到所有舰队的关联集群,可以省略clusterAffinity
字段整个内容。apiVersion: policy.one.alibabacloud.com/v1alpha1 kind: ClusterPropagationPolicy metadata: name: ns-policy spec: resourceSelectors: - apiVersion: v1 kind: Namespace name: spark placement: clusterAffinity: clusterNames: - ${cluster1-id} # 您的集群ID。 - ${cluster2-id} # 您的集群ID。 replicaScheduling: replicaSchedulingType: Duplicated
步骤三:在关联集群中安装ack-spark-operator
请在期望运行Spark作业的子集群上安装ack-spark-operator组件,且版本为2.1.2及以上。
登录容器服务管理控制台,在左侧导航栏选择 。
在应用市场页面单击应用目录页签,然后搜索并选中ack-spark-operator。
在ack-spark-operator页面,单击一键部署。
在创建面板中,选择集群和命名空间,然后单击下一步。
在参数配置页面,设置相应参数,选择Chart 版本为2.1.2或更高版本,
jobNamespaces
中添加spark
,然后单击确定。必须将
SparkApplication
所在的namespace
添加到spark.jobNamespaces
中下表列出了部分配置参数的说明。完整的参数配置详情,您可以在ack-spark-operator页面中的配置项查看。
参数
描述
示例值
参数
描述
示例值
controller.replicas
控制器副本数量。
1(默认值)
webhook.replicas
Webhook副本数量。
1(默认值)
spark.jobNamespaces
可运行Spark任务的命名空间列表。包含空字符串表示允许所有命名空间。多个命名空间使用英文半角逗号
,
隔开。["default"]
(默认值)[""]
(所有命名空间)["ns1","ns2","ns3"]
(多个命名空间)
spark.serviceAccount.name
Spark作业会在
spark.jobNamespaces
指定的每个命名空间中自动创建名为spark-operator-spark
的ServiceAccount和RBAC资源并进行相关授权。您可以自定义ServiceAccount名称,后续提交Spark作业时请指定自定义创建的ServiceAccount名称。spark-operator-spark
(默认值)
步骤四:在舰队上创建PriorityClass,并分发到子集群
为了保证提交的Spark作业不会抢占在线服务资源、影响在线服务产品的正常运行,建议对要提交的Spark作业设置低优先级。
使用舰队的KubeConfig,创建一个低优先级的
PriorityClass
,其value
设置为负数。apiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: low-priority value: -1000 globalDefault: false description: "Low priority for Spark applications"
在舰队中创建
ClusterPropagationPolicy
,将PriorityClass
分发到指定集群中。若您希望将PriorityClass
分发到所有关联集群,可以将clusterAffinity
部分删除。apiVersion: policy.one.alibabacloud.com/v1alpha1 kind: ClusterPropagationPolicy metadata: name: priority-policy spec: preserveResourcesOnDeletion: false resourceSelectors: - apiVersion: scheduling.k8s.io/v1 kind: PriorityClass placement: clusterAffinity: clusterNames: - ${cluster1-id} # 您的集群ID。 - ${cluster2-id} # 您的集群ID。 # labelSelector: # matchLabels: # key: value replicaScheduling: replicaSchedulingType: Duplicated
步骤五:在舰队中提交在离线混部策略的SparkApplicaiton
在舰队中创建如下
PropagationPolicy
,可以将所有sparkoperator.k8s.io/v1beta2
的SparkApplication
资源都分发到相应的集群中,若要分发到所有关联集群,可以省略clusterAffinity
整个字段内容。apiVersion: policy.one.alibabacloud.com/v1alpha1 kind: PropagationPolicy metadata: name: sparkapp-policy namespace: spark spec: preserveResourcesOnDeletion: false propagateDeps: true placement: clusterAffinity: clusterNames: - ${cluster1-id} # 您的集群ID。 - ${cluster2-id} # 您的集群ID。 # labelSelector: # matchLabels: # key: value replicaScheduling: replicaSchedulingType: Divided customSchedulingType: Gang resourceSelectors: - apiVersion: sparkoperator.k8s.io/v1beta2 kind: SparkApplication
在舰队中创建Spark作业。可以通过在
SparkApplication
中添加注解sparkoperator.k8s.io/koordinator-colocation: "true"
来标识driver
和executor
是否需要根据实际剩余资源进行调度。本例配置如下所示,表示driver
和executor
都需要根据实际剩余资源进行调度。apiVersion: sparkoperator.k8s.io/v1beta2 kind: SparkApplication metadata: name: spark-pi namespace: spark spec: arguments: - "50000" driver: coreLimit: 1000m cores: 1 memory: 512m priorityClassName: low-priority template: metadata: annotations: sparkoperator.k8s.io/koordinator-colocation: "true" spec: containers: - name: spark-kubernetes-driver serviceAccount: spark-operator-spark executor: coreLimit: 1000m cores: 1 instances: 1 memory: 1g priorityClassName: low-priority template: metadata: annotations: sparkoperator.k8s.io/koordinator-colocation: "true" spec: containers: - name: spark-kubernetes-executor image: registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/spark:3.5.4 mainApplicationFile: local:///opt/spark/examples/jars/spark-examples_2.12-3.5.4.jar mainClass: org.apache.spark.examples.SparkPi mode: cluster restartPolicy: type: Never sparkVersion: 3.5.4 type: Scala
步骤六:查看Spark作业状态
在舰队中执行以下命令,查看舰队中Spark作业的状态。
kubectl get sparkapp -nspark
预期输出:
NAME STATUS ATTEMPTS START FINISH AGE spark-pi RUNNING 1 2025-03-05T11:19:43Z <no value> 48s
在舰队中执行以下命令,在事件中查看Spark作业调度至哪个关联集群。
kubectl describe sparkapp spark-pi -nspark
预期输出:
Normal ScheduleBindingSucceed 2m29s default-scheduler Binding has been scheduled successfully. Result: {c6xxxxx:0,[{driver 1} {executor 1}]}
在舰队中执行以下命令,查看资源调度分发状态。
kubectl get rb spark-pi-sparkapplication -nspark
预期输出:
NAME SCHEDULED FULLYAPPLIED OVERRIDDEN ALLAVAILABLE AGE spark-pi-sparkapplication True True True True
在舰队中执行以下命令,查看关联集群中Spark作业的状态。
kubectl amc get sparkapp -M -nspark
预期输出:
NAME CLUSTER STATUS ATTEMPTS START FINISH AGE ADOPTION spark-pi c6xxxxxxx COMPLETED 1 2025-02-24T12:10:34Z 2025-02-24T12:11:20Z 61s Y
在舰队中执行以下命令,查看Pod状态。
kubectl amc get pod -M -nspark
预期输出:
NAME CLUSTER READY STATUS RESTARTS AGE spark-pi-3c0565956608ad6d-exec-1 c6xxxxxxx 1/1 Running 0 2m35s spark-pi-driver c6xxxxxxx 1/1 Running 0 2m50s
在舰队中执行以下命令,查看关联集群中Spark作业的详情。
kubectl amc get sparkapp spark-pi -m ${member clusterid} -oyaml -nspark
- 本页导读 (1)
- 背景信息
- 前提条件
- 步骤一:在关联集群中配置ack-koordinator
- 步骤二:(可选)在舰队中创建命名空间,并下发到子集群
- 步骤三:在关联集群中安装ack-spark-operator
- 步骤四:在舰队上创建PriorityClass,并分发到子集群
- 步骤五:在舰队中提交在离线混部策略的SparkApplicaiton
- 步骤六:查看Spark作业状态