Use instâncias Fleet do ACK One (Distributed Cloud Container Platform for Kubernetes) para agendar e distribuir jobs do Apache Spark entre vários clusters. Essa abordagem permite executar workloads em lote do Spark na capacidade ociosa dos clusters, sem competir por recursos com workloads de serviços online.
Como funciona
Instale o componente
ack-spark-operatorem cada sub-cluster onde os jobs do Spark serão executados.Crie um
SparkApplicatione umaPropagationPolicyna instância Fleet.-
O Global Scheduler (componente de agendamento multicluster da instância Fleet) compara as solicitações de recursos do job do Spark com a capacidade restante de cada sub-cluster associado e seleciona o melhor destino.
Em sub-clusters com Kubernetes 1.28 ou posterior, a instância Fleet oferece suporte à pré-ocupação de recursos para aumentar as taxas de sucesso do agendamento.
A instância Fleet distribui o
SparkApplicationpara o sub-cluster selecionado.O ACK Spark Operator no sub-cluster inicia os Pods
drivereexecutordo Spark. A instância Fleet monitora o status de execução do job. Se odriverfalhar ao iniciar devido a recursos insuficientes, a instância Fleet recupera oSparkApplicationapós um tempo limite e o reagenda para outro sub-cluster com capacidade suficiente.
Pré-requisitos
Antes de começar, verifique se você tem:
Uma instância Fleet associada a dois ou mais clusters que executam Kubernetes 1.18 ou posterior. Para obter mais informações, consulte Gerenciar clusters associados.
A política do Resource Access Management (RAM)
AliyunAdcpFullAccessanexada ao seu usuário RAM. Para obter mais informações, consulte Conceder permissões a um usuário RAM.A ferramenta de linha de comando AMC instalada. Para obter mais informações, consulte Usar a linha de comando AMC.
Etapa 1: Instalar o ack-spark-operator nos sub-clusters
Instale o componente ack-spark-operator em cada sub-cluster onde deseja executar jobs do Spark.
Faça login no ACK console. No painel de navegação à esquerda, escolha Marketplace > Marketplace.
Na página Marketplace, clique em App Catalog, localize e clique em ack-spark-operator.
Na página do ack-spark-operator, clique em Deploy.
No painel Deploy, selecione um cluster e namespace e clique em Next.
Na etapa Parameters, configure os parâmetros e clique em OK.
A tabela a seguir descreve os principais parâmetros. Todas as configurações de parâmetros estão disponíveis na seção Parameters da página do ack-spark-operator.
|
Parâmetro |
Descrição |
Padrão |
|
|
Quantidade de réplicas do controlador. |
|
|
|
Quantidade de réplicas do webhook. |
|
|
|
Namespaces onde os jobs do Spark podem ser executados. Defina como |
|
|
|
Nome da ServiceAccount criada automaticamente em cada namespace listado em |
|
Etapa 2: Criar uma PriorityClass e distribuí-la aos sub-clusters
Atribua uma prioridade baixa aos jobs do Spark para evitar que eles compitam por recursos com workloads de serviços online.
-
Com o arquivo kubeconfig da instância Fleet, crie uma
PriorityClassde baixa prioridade com umvaluenegativo:apiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: low-priority value: -1000 globalDefault: false description: "Low priority for Spark applications" -
Crie uma
ClusterPropagationPolicyna instância Fleet para distribuir aPriorityClassaos sub-clusters de destino. Para distribuir a todos os clusters associados, remova o campoclusterAffinity.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} # The ID of your cluster. - ${cluster2-id} # The ID of your cluster. # labelSelector: # matchLabels: # key: value replicaScheduling: replicaSchedulingType: Duplicated
Etapa 3: Enviar um job do Spark na instância Fleet
(Opcional) Criar e distribuir namespaces para os sub-clusters
Se o namespace onde o SparkApplication será executado ainda não existir na instância Fleet, crie-o primeiro. Esse namespace também deve estar listado no parâmetro spark.jobNamespaces configurado na Etapa 1.
-
Crie o namespace na instância Fleet:
kubectl create ns xxx -
Crie uma
ClusterPropagationPolicypara distribuir o namespace para cada sub-cluster:apiVersion: policy.one.alibabacloud.com/v1alpha1 kind: ClusterPropagationPolicy metadata: name: ns-policy spec: resourceSelectors: - apiVersion: v1 kind: Namespace name: xxx placement: clusterAffinity: clusterNames: - ${cluster1-id} # The ID of your cluster. - ${cluster2-id} # The ID of your cluster. replicaScheduling: replicaSchedulingType: Duplicated
Criar uma PropagationPolicy para SparkApplication
Crie uma PropagationPolicy na instância Fleet. Essa política instrui o Global Scheduler a distribuir todos os recursos SparkApplication da versão de API sparkoperator.k8s.io/v1beta2 para os sub-clusters de destino usando agendamento Gang.
apiVersion: policy.one.alibabacloud.com/v1alpha1
kind: PropagationPolicy
metadata:
name: sparkapp-policy
namespace: default
spec:
preserveResourcesOnDeletion: false
propagateDeps: true # Automatically propagates dependent resources (such as the ServiceAccount referenced in the driver spec) to the target sub-clusters.
placement:
clusterAffinity:
clusterNames:
- ${cluster1-id} # The ID of your cluster.
- ${cluster2-id} # The ID of your cluster.
# labelSelector:
# matchLabels:
# key: value
replicaScheduling:
replicaSchedulingType: Divided
customSchedulingType: Gang
resourceSelectors:
- apiVersion: sparkoperator.k8s.io/v1beta2
kind: SparkApplication
Enviar um SparkApplication
Crie um SparkApplication na instância Fleet. Defina priorityClassName como a PriorityClass criada na Etapa 2 tanto para o driver quanto para o executor.
O Global Scheduler usa os valores de memory e cores nas especificações do driver e do executor como solicitações de recursos do Kubernetes. Ele compara o total de recursos solicitados com a capacidade restante de cada sub-cluster para selecionar o cluster de destino. Dimensione esses valores para refletir os recursos reais necessários ao seu job. Valores subdimensionados podem resultar em agendamento bem-sucedido, mas falha na execução. Valores superdimensionados podem impedir o agendamento se nenhum cluster tiver capacidade suficiente.
Após criar o SparkApplication, a PropagationPolicy da etapa anterior o distribui para o sub-cluster selecionado.
apiVersion: sparkoperator.k8s.io/v1beta2
kind: SparkApplication
metadata:
name: spark-pi
namespace: default # Make sure this namespace is listed in the spark.jobNamespaces parameter.
spec:
type: Scala
mode: cluster
image: registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/spark:3.5.4
imagePullPolicy: IfNotPresent
mainClass: org.apache.spark.examples.SparkPi
mainApplicationFile: local:///opt/spark/examples/jars/spark-examples_2.12-3.5.4.jar
arguments:
- "1000"
sparkVersion: 3.5.4
driver:
cores: 1
memory: 512m
priorityClassName: low-priority
serviceAccount: spark-operator-spark # Replace with the custom name you specified in Step 1.
executor:
instances: 1
cores: 1
memory: 512m
priorityClassName: low-priority
restartPolicy:
type: Never
Etapa 4: Verificar o job do Spark
Verificar o status do job e o resultado do agendamento
-
Execute o seguinte comando na instância Fleet para visualizar o status do job do Spark:
kubectl get sparkappSaída esperada:
NAME STATUS ATTEMPTS START FINISH AGE spark-pi RUNNING 1 2025-02-24T12:10:34Z <no value> 11s -
Execute o comando abaixo para confirmar em qual sub-cluster o job foi agendado:
kubectl describe sparkapp spark-piSaída esperada:
Normal ScheduleBindingSucceed 2m29s default-scheduler Binding has been scheduled successfully. Result: {c6xxxxx:0,[{driver 1} {executor 1}]} -
Use o seguinte comando para visualizar o status do job no sub-cluster associado:
kubectl amc get sparkapp -MSaída esperada:
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 -
Consulte o status dos Pods executando este comando:
kubectl amc get pod -MSaída esperada:
NAME CLUSTER READY STATUS RESTARTS AGE spark-pi-driver c6xxxxxxx 0/1 Completed 0 68s -
Visualize os detalhes completos do job do Spark no sub-cluster com o comando a seguir:
kubectl amc get sparkapp spark-pi -m ${member clusterid} -oyaml
Solução de problemas
Caso o job não atinja o status COMPLETED, utilize os comandos abaixo para diagnosticar o problema.
Job preso em PENDING ou não agendado:
Verifique os eventos no SparkApplication para identificar se o Global Scheduler relatou uma falha de agendamento:
kubectl describe sparkapp spark-pi
Procure por eventos com o motivo ScheduleBindingFailed ou similar. Causas comuns incluem recursos insuficientes em todos os sub-clusters ou uma PriorityClass ausente no cluster de destino.
Pod do Driver não está iniciando:
Verifique os eventos do Pod do driver no sub-cluster:
kubectl amc get pod -M
kubectl amc describe pod spark-pi-driver -m ${member clusterid}
Operator não está em execução no sub-cluster:
Confirme se o ack-spark-operator está em execução no sub-cluster:
kubectl amc get pod -n spark-operator -M