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
-
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.
ImportanteSe 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:
Para gerenciar o cluster do computador local, instale e configure o cliente kubectl. Para mais informações, consulte Obter o arquivo kubeconfig de um cluster e usar o kubectl para conectar-se ao cluster.
Você também pode usar o kubectl no Cloud Shell para gerenciar o cluster. Para mais informações, consulte Usar o kubectl para gerenciar um cluster Kubernetes no Cloud Shell.
-
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
-
Instale o Spark operator.
No console do ACK, escolha Marketplace > Marketplace no painel de navegação à esquerda.
Na aba App Catalog, localize e clique em ack-spark-operator.
No canto superior direito, clique em Deploy.
No painel, selecione o cluster de destino e conclua a configuração.
-
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
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.
-
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" -
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
-
Verifique o status dos pods.
kubectl get podsSaí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 -
Visualize a Spark UI em tempo real.
kubectl port-forward spark-pi-1547981232122-driver 4040:4040 -
Verifique o status do SparkApplication.
kubectl describe sparkapplication spark-piSaí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 -
Verifique os logs para obter o resultado.
NAME READY STATUS RESTARTS AGE spark-pi-1547981232122-driver 0/1 Completed 0 1mQuando 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