Executar jobs do Spark no ECI em um cluster Kubernetes oferece dimensionamento automático, implantação automatizada e alta disponibilidade, o que aumenta a eficiência e a estabilidade. Instale o Spark Operator em um cluster ACK Serverless para executar e gerenciar jobs do Spark no ECI.
Contexto
O Apache Spark é um projeto open-source amplamente utilizado em análise de dados para cargas de trabalho de big data e machine learning. A partir da versão 2.3.0, é possível executar e gerenciar recursos do Spark no Kubernetes.
O Spark Operator, desenvolvido para o Spark no Kubernetes, permite enviar jobs do Spark para um cluster Kubernetes definindo-os como Custom Resource Definitions (CRDs). O Spark Operator oferece as seguintes vantagens:
Supera as limitações do suporte nativo do Spark ao Kubernetes.
Permite integração rápida com componentes do ecossistema Kubernetes, como armazenamento, monitoramento e logs.
Oferece suporte a recursos avançados do Kubernetes, como recuperação de falhas, dimensionamento automático e otimização de agendamento.
Pré-requisitos
-
Crie um cluster ACK Serverless.
Crie um cluster ACK Serverless no Container Service for Kubernetes console. Para mais informações, consulte Create an ACK Serverless cluster.
ImportanteSe for necessário 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 das seguintes formas:
Para gerenciar o cluster do computador local, instale e configure o cliente kubectl. Para mais informações, consulte Obtain the kubeconfig file of a cluster and use kubectl to connect to the cluster.
Também é possível usar o kubectl no Cloud Shell para gerenciar o cluster. Para mais informações, consulte Use kubectl to manage a Kubernetes cluster in Cloud Shell.
-
Crie um bucket do OSS.
Crie um bucket do OSS para armazenar dados de teste, resultados e logs. Para mais informações, consulte Create a bucket.
Instalar o Spark Operator
-
Instale o Spark Operator.
No painel de navegação à esquerda do ACK console, escolha Marketplace > Marketplace.
Na aba App Catalog, localize e clique em ack-spark-operator.
No canto superior direito, clique em Deploy.
No painel exibido, selecione o cluster desejado e conclua a configuração conforme solicitado.
-
Crie um ServiceAccount, Role e RoleBinding.
Um job do Spark requer um ServiceAccount com permissões para criar pods. Crie um ServiceAccount, Role e RoleBinding usando o manifesto YAML a seguir. Modifique o namespace 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 pacote JAR do job do Spark e empacote-o em uma imagem usando um Dockerfile.
O Dockerfile a seguir tem como base a imagem do Spark fornecida pelo Alibaba Cloud Container Service:
FROM registry.aliyuncs.com/acs/spark:ack-2.4.5-latest
RUN mkdir -p /opt/spark/jars
# If you need to use OSS (for example, to read data from or write events to OSS), add the following JAR packages 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 uma imagem grande do Spark pode ser demorado. Use o ImageCache para acelerar o download de imagens. Para mais informações, consulte Manage ImageCache e Use ImageCache to accelerate pod creation.
A Alibaba Cloud fornece uma imagem base para o Spark 2.4.5 otimizada para agendamento e elasticidade no Kubernetes, o que melhora significativamente as velocidades de agendamento e inicialização. Ative essa otimização definindo a variável enableAlibabaCloudFeatureGates: true no Helm chart. Para uma inicialização ainda mais rápida, 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 manifesto de job
Crie um arquivo de configuração YAML para o job do Spark e implante-o.
-
Crie um arquivo spark-pi.yaml.
Veja abaixo um exemplo de manifesto de job. Para mais informações, consulte 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 um job de computação 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 correspondente. Para mais informações, consulte Customize log collection for ECI.
envVars:
aliyun_logs_test-stdout_project: test-k8s-spark
aliyun_logs_test-stdout_machinegroup: k8s-group-app-spark
aliyun_logs_test-stdout: stdout
Defina essas variáveis de ambiente para o driver e o executor ao enviar o job. Após a configuração, visualize os logs coletados na aba Raw Logs do Project correspondente no console do Log Service. As entradas de log contêm campos como __source__, __tag__:__hostname__, __tag__:__path__, __tag__:__user_defined_id__ e __tag__:eci_id, além do conteúdo do log no campo content.
Configurar o history server
O history server rastreia e audita jobs do Spark. Adicione o campo SparkConf ao CRD SparkApplication para gravar eventos no OSS. O history server lê esses eventos para exibir informações sobre os jobs. 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"
# oss bucket endpoint such as 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": ""
A Alibaba Cloud também fornece um Helm chart spark-history-server. Pesquise por ack-spark-history-server na página Marketplace > Marketplace do console do ACK e instale-o. Durante a instalação, configure as informações relacionadas ao OSS na seção Parameters. Exemplo:
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 em Services, na página de detalhes do cluster. Acesse esse endpoint para visualizar jobs arquivados. A página do Spark History Server lista aplicações Spark concluídas com colunas como App ID, App Name, Started, Completed, Duration, Spark User, Last Updated e Event Log. Para baixar um log de eventos, clique em Download na linha correspondente.
Visualizar o resultado do job
-
Verifique o status de execução 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 interface do 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 -
Visualize os logs para verificar o resultado.
NAME READY STATUS RESTARTS AGE spark-pi-1547981232122-driver 0/1 Completed 0 1mQuando o status do SparkApplication for
COMPLETEDou o status do pod driver do Spark forCompleted, visualize os logs para conferir o resultado.kubectl logs spark-pi-1547981232122-driver Pi is roughly 3.152155760778804