Todos os produtos
Search
Central de documentação

Elastic Container Instance:Executar jobs do Spark no ECI

Última atualização: Jul 05, 2026

Executar jobs do Spark em uma elastic container instance (ECI) em um cluster Kubernetes aumenta a eficiência e a estabilidade com recursos como Auto Scaling, implantação automatizada e alta disponibilidade. Este tópico descreve como instalar o Spark operator em um cluster ACK Serverless e usar o ECI para executar jobs do Spark.

Contexto

O Apache Spark é um projeto open-source amplamente usado para análise de dados, comum em cargas de trabalho de big data e machine learning. A partir da versão 2.3.0, você pode executar e gerenciar recursos do Spark no Kubernetes.

O Spark operator foi projetado para o Spark no Kubernetes e permite que desenvolvedores usem Custom Resource Definitions (CRDs) para enviar jobs do Spark a um cluster Kubernetes.

  • Supera as limitações do suporte nativo do Spark ao Kubernetes.

  • Integra-se perfeitamente aos componentes do ecossistema Kubernetes, como armazenamento, monitoramento e logs.

  • Oferece suporte a recursos avançados do Kubernetes, incluindo failover, Auto Scaling e otimização de agendamento.

Antes de começar

  1. Crie um cluster ACK Serverless.

    Crie um cluster ACK Serverless no console do Container Service for Kubernetes. Para mais informações, consulte Criar um cluster ACK Serverless.

    Importante

    Se precisar baixar imagens da internet ou se o job de treinamento exigir acesso à internet, configure um NAT Gateway.

    Use o kubectl para gerenciar e acessar o cluster ACK Serverless da seguinte forma:

  2. Crie um bucket do OSS.

    Crie um bucket do Object Storage Service (OSS) para armazenar dados de teste, resultados e logs. Para obter instruções sobre como criar um bucket, consulte Criar buckets.

Instalar o Spark operator

  1. Instale o Spark operator.

    1. No console do ACK, escolha Marketplace > Marketplace no painel de navegação à esquerda.

    2. Na aba App Catalog, localize e clique em ack-spark-operator.

    3. No canto superior direito, clique em Deploy.

    4. No painel, selecione o cluster de destino e conclua a configuração.

  2. Crie um ServiceAccount, Role e RoleBinding.

    Um job do Spark requer um ServiceAccount com permissões para criar pods. Crie o ServiceAccount, o Role e o RoleBinding necessários. O YAML a seguir é um exemplo. Modifique o namespace de cada recurso conforme necessário.

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: spark
      namespace: default
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      namespace: default
      name: spark-role
    rules:
    - apiGroups: [""]
      resources: ["pods"]
      verbs: ["*"]
    - apiGroups: [""]
      resources: ["services"]
      verbs: ["*"]
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: spark-role-binding
      namespace: default
    subjects:
    - kind: ServiceAccount
      name: spark
      namespace: default
    roleRef:
      kind: Role
      name: spark-role
      apiGroup: rbac.authorization.k8s.io

Criar uma imagem de job do Spark

Compile o job do Spark em um arquivo JAR e crie uma imagem usando um Dockerfile.

Este exemplo de Dockerfile usa uma imagem base do Spark do Alibaba Cloud Container Service.

FROM registry.aliyuncs.com/acs/spark:ack-2.4.5-latest
RUN mkdir -p /opt/spark/jars
# To use OSS for reading data or writing event logs, add the following JARs to the image.
ADD https://repo1.maven.org/maven2/com/aliyun/odps/hadoop-fs-oss/3.3.8-public/hadoop-fs-oss-3.3.8-public.jar $SPARK_HOME/jars
ADD https://repo1.maven.org/maven2/com/aliyun/oss/aliyun-sdk-oss/3.8.1/aliyun-sdk-oss-3.8.1.jar $SPARK_HOME/jars
ADD https://repo1.maven.org/maven2/org/aspectj/aspectjweaver/1.9.5/aspectjweaver-1.9.5.jar $SPARK_HOME/jars
ADD https://repo1.maven.org/maven2/org/jdom/jdom/1.1.3/jdom-1.1.3.jar $SPARK_HOME/jars
COPY SparkExampleScala-assembly-0.1.jar /opt/spark/jars
Importante

Baixar imagens grandes do Spark pode ser demorado. Use o ImageCache para acelerar o download de imagens. Para mais informações, consulte Gerenciar ImageCache e Usar ImageCache para acelerar a criação de pods.

Você também pode usar a imagem base do Spark do Alibaba Cloud. O Alibaba Cloud fornece uma imagem base para o Spark 2.4.5 otimizada para cenários de Kubernetes, como agendamento e elasticidade, o que melhora significativamente a velocidade de agendamento e inicialização. Ative esse recurso definindo a variável do Helm chart enableAlibabaCloudFeatureGates: true. Para obter velocidades de inicialização ainda maiores, defina enableWebhook: false.

operatorImageName: registry.aliyuncs.com/acs/spark-operator
operatorImageVersion: ack-2.4.5-latest
operatorVersion: v2.4.5-v1beta2
imagePullPolicy: IfNotPresent
rbac:
  create: true
serviceAccounts:
  spark:
    create: true
    name: spark
  sparkoperator:
    create: true
    name: ack-spark-operator
sparkJobNamespace: "default"
enableWebhook: false
enableMetrics: true
enableAlibabaCloudFeatureGates: false

Criar e enviar um job do Spark

Crie um arquivo de configuração YAML para o job do Spark e implante-o.

  1. Crie um arquivo spark-pi.yaml.

    Veja abaixo um manifesto de job típico. Para mais informações, consulte a documentação do spark-on-k8s-operator.

    apiVersion: "sparkoperator.k8s.io/v1beta2"
    kind: SparkApplication
    metadata:
      name: spark-pi
      namespace: default
    spec:
      type: Scala
      mode: cluster
      image: "registry.aliyuncs.com/acs/spark:ack-2.4.5-latest"
      imagePullPolicy: Always
      mainClass: org.apache.spark.examples.SparkPi
      mainApplicationFile: "local:///opt/spark/examples/jars/spark-examples_2.11-2.4.5.jar"
      sparkVersion: "2.4.5"
      restartPolicy:
        type: Never
      driver:
        cores: 2
        coreLimit: "2"
        memory: "3g"
        memoryOverhead: "1g"
        labels:
          version: 2.4.5
        serviceAccount: spark
        annotations:
          k8s.aliyun.com/eci-kube-proxy-enabled: 'true'
          k8s.aliyun.com/eci-auto-imc: "true"
        tolerations:
        - key: "virtual-kubelet.io/provider"
          operator: "Exists"
      executor:
        cores: 2
        instances: 1
        memory: "3g"
        memoryOverhead: "1g"
        labels:
          version: 2.4.5
        annotations:
          k8s.aliyun.com/eci-kube-proxy-enabled: 'true'
          k8s.aliyun.com/eci-auto-imc: "true"
        tolerations:
        - key: "virtual-kubelet.io/provider"
          operator: "Exists"
  2. Implante o job do Spark.

    kubectl apply -f spark-pi.yaml

Configurar a coleta de logs

Para coletar logs de saída padrão do driver e do executor do Spark, injete variáveis de ambiente no campo envVars para ativar a coleta automática de logs. Para mais informações, consulte Personalizar a coleta de logs para uma elastic container instance.

envVars:
   aliyun_logs_test-stdout_project: test-k8s-spark
   aliyun_logs_test-stdout_machinegroup: k8s-group-app-spark
   aliyun_logs_test-stdout: stdout

Após a configuração, os logs coletados do executor do Spark ficam disponíveis na aba Raw Log no console do Log Service. Cada entrada de log inclui campos estruturados como __source__, __tag__:__hostname__, __tag__:__path__ e __tag__:eci_id, além do conteúdo dos logs de execução da aplicação Spark. Isso inclui informações sobre o processo de encerramento, como a limpeza de diretórios pelo ShutdownHookManager, a parada do BlockManager e a liberação do MemoryStore.

Configurar o history server

O history server permite auditar jobs do Spark. Adicione o campo sparkConf ao CRD SparkApplication para gravar logs de eventos no OSS. O history server lê esses dados do OSS para exibir o histórico de jobs. Veja abaixo um exemplo de configuração:

sparkConf:
   "spark.eventLog.enabled": "true"
   "spark.eventLog.dir": "oss://bigdatastore/spark-events"
   "spark.hadoop.fs.oss.impl": "org.apache.hadoop.fs.aliyun.oss.AliyunOSSFileSystem"
   # The endpoint of the OSS bucket, for example, oss-cn-beijing.aliyuncs.com
   "spark.hadoop.fs.oss.endpoint": "oss-cn-beijing.aliyuncs.com"
   "spark.hadoop.fs.oss.accessKeySecret": ""
   "spark.hadoop.fs.oss.accessKeyId": ""
        

O Alibaba Cloud também fornece um Helm chart para o spark-history-server. Pesquise por ack-spark-history-server e instale-o na página Marketplace > Marketplace no console do ACK. Durante a instalação, configure as informações do OSS na seção Parameters. Confira o exemplo a seguir:

oss:
  enableOSS: true
  # Please input your accessKeyId
  alibabaCloudAccessKeyId: ""
  # Please input your accessKeySecret
  alibabaCloudAccessKeySecret: ""
  # oss bucket endpoint such as oss-cn-beijing.aliyuncs.com
  alibabaCloudOSSEndpoint: "oss-cn-beijing.aliyuncs.com"
  # oss file path such as oss://bucket-name/path
  eventsDir: "oss://bigdatastore/spark-events"

Após a instalação, localize o endpoint externo do ack-spark-history-server na página Services e acesse-o para visualizar os jobs arquivados. Na página do Spark History Server, visualize a lista de aplicações Spark concluídas. A lista contém colunas como App id, App name, Started, Completed, Duration, Spark user, Last updated e Event log. Baixe o log de eventos correspondente clicando no botão Download.

Verificar o resultado do job

  1. Verifique o status dos pods.

    kubectl get pods

    Saída esperada:

    NAME                            READY      STATUS     RESTARTS   AGE
    spark-pi-1547981232122-driver   1/1       Running    0          12s
    spark-pi-1547981232122-exec-1   1/1       Running    0          3s
  2. Visualize a Spark UI em tempo real.

    kubectl port-forward spark-pi-1547981232122-driver 4040:4040
  3. Verifique o status do SparkApplication.

    kubectl describe sparkapplication spark-pi

    Saída esperada:

    Name:         spark-pi
    Namespace:    default
    Labels:       <none>
    Annotations:  kubectl.kubernetes.io/last-applied-configuration:
                    {"apiVersion":"sparkoperator.k8s.io/v1alpha1","kind":"SparkApplication","metadata":{"annotations":{},"name":"spark-pi","namespace":"default"...}}
    API Version:  sparkoperator.k8s.io/v1alpha1
    Kind:         SparkApplication
    Metadata:
      Creation Timestamp:  2019-01-20T10:47:08Z
      Generation:          1
      Resource Version:    4923532
      Self Link:           /apis/sparkoperator.k8s.io/v1alpha1/namespaces/default/sparkapplications/spark-pi
      UID:                 bbe7445c-1ca0-11e9-9ad4-062fd7c19a7b
    Spec:
      Deps:
      Driver:
        Core Limit:  200m
        Cores:       0.1
        Labels:
          Version:        2.4.0
        Memory:           512m
        Service Account:  spark
        Volume Mounts:
          Mount Path:  /tmp
          Name:        test-volume
      Executor:
        Cores:      1
        Instances:  1
        Labels:
          Version:  2.4.0
        Memory:     512m
        Volume Mounts:
          Mount Path:         /tmp
          Name:               test-volume
      Image:                  gcr.io/spark-operator/spark:v2.4.0
      Image Pull Policy:      Always
      Main Application File:  local:///opt/spark/examples/jars/spark-examples_2.11-2.4.0.jar
      Main Class:             org.apache.spark.examples.SparkPi
      Mode:                   cluster
      Restart Policy:
        Type:  Never
      Type:    Scala
      Volumes:
        Host Path:
          Path:  /tmp
          Type:  Directory
        Name:    test-volume
    Status:
      Application State:
        Error Message:
        State:          COMPLETED
      Driver Info:
        Pod Name:             spark-pi-driver
        Web UI Port:          31182
        Web UI Service Name:  spark-pi-ui-svc
      Execution Attempts:     1
      Executor State:
        Spark - Pi - 1547981232122 - Exec - 1:  COMPLETED
      Last Submission Attempt Time:             2019-01-20T10:47:14Z
      Spark Application Id:                     spark-application-1547981285779
      Submission Attempts:                      1
      Termination Time:                         2019-01-20T10:48:56Z
    Events:
      Type    Reason                     Age                 From            Message
      ----    ------                     ----                ----            -------
      Normal  SparkApplicationAdded      55m                 spark-operator  SparkApplication spark-pi was added, Enqueuing it for submission
      Normal  SparkApplicationSubmitted  55m                 spark-operator  SparkApplication spark-pi was submitted successfully
      Normal  SparkDriverPending         55m (x2 over 55m)   spark-operator  Driver spark-pi-driver is pending
      Normal  SparkExecutorPending       54m (x3 over 54m)   spark-operator  Executor spark-pi-1547981232122-exec-1 is pending
      Normal  SparkExecutorRunning       53m (x4 over 54m)   spark-operator  Executor spark-pi-1547981232122-exec-1 is running
      Normal  SparkDriverRunning         53m (x12 over 55m)  spark-operator  Driver spark-pi-driver is running
      Normal  SparkExecutorCompleted     53m (x2 over 53m)   spark-operator  Executor spark-pi-1547981232122-exec-1 completed
  4. Verifique os logs para obter o resultado.

    NAME                                      READY     STATUS      RESTARTS   AGE
    spark-pi-1547981232122-driver   0/1       Completed   0          1m

    Quando o status do SparkApplication ou do pod driver for COMPLETED, verifique os logs para conferir o resultado.

    kubectl logs spark-pi-1547981232122-driver
    Pi is roughly 3.152155760778804