7 min de leitura

Como otimizar seu cluster do Spark com trabalhos interativos do Spark

Spark on Kubernetes

Neste artigo, você aprenderá:

  • Como diminuir o tempo de execução do trabalho do Spark
  • O que é um trabalho interativo em Ilum
  • Como executar um trabalho interativo do Spark
  • Diferenças entre executar um trabalho do Spark usando a API do Ilum e a API do Spark

Tipos de trabalho Ilum

Existem três tipos de trabalhos que você pode executar no Ilum: trabalho único , trabalho interativo e Código interativo . Neste artigo, vamos nos concentrar no trabalho interativo tipo. No entanto, é importante conhecer as diferenças entre os três tipos de trabalhos, então vamos dar uma rápida visão geral de cada um.

Com Trabalhos individuais , você pode enviar programas semelhantes a códigos. Eles permitem que você envie um aplicativo Spark para o cluster, com código pré-compilado, sem interação durante o tempo de execução. Nesse modo, você deve enviar um jar compilado para o Ilum, que é usado para iniciar um único trabalho. Você pode enviá-lo diretamente ou usar credenciais da AWS para obtê-lo de um bucket do S3. Um exemplo típico de uso de um único trabalho seria algum tipo de tarefa de preparação de dados.

A Ilum também fornece um interativo Modo de código , que permite enviar comandos em tempo de execução. Isso é útil para tarefas em que você precisa interagir com os dados, como análise exploratória de dados.

Trabalho interativo

Os trabalhos interativos têm sessões de longa duração, nas quais você pode enviar dados da instância do trabalho para serem executados imediatamente. O recurso matador desse modo é que você não precisa esperar que o contexto do Spark seja inicializado. Se os usuários estivessem apontando para a mesma ID de trabalho, eles interagiriam com o mesmo contexto do Spark. O Ilum encapsula a lógica do aplicativo Spark em um trabalho Spark de longa duração que é capaz de lidar com solicitações de cálculo imediatamente, sem a necessidade de aguardar a inicialização do contexto do Spark.

Iniciando um trabalho interativo

Vamos dar uma olhada em como a sessão interativa de Ilum pode ser iniciada. A primeira coisa que temos que fazer é configurar o Ilum. Você pode fazer isso facilmente com o minikube. Um tutorial com a instalação do Ilum está disponível neste link . Na próxima etapa, temos que criar um arquivo jar que contenha uma implementação da interface de trabalho do Ilum. Para usar a API de trabalho do Ilum, temos que adicioná-la ao projeto com alguns gerenciadores de dependência, como Maven ou Gradle. Neste exemplo, usaremos algum código Scala com um Gradle para calcular o PI.

O exemplo completo está disponível em nosso GitHub .

Se preferir não compilá-lo sozinho, você pode encontrar o arquivo jar compilado aqui .

O primeiro passo é criar uma pasta para o nosso projeto e alterar o diretório para ela.

$ mkdir exemplo de trabalho interativo
$ cd exemplo de trabalho interativo 

Se você não tiver a versão mais recente do Gradle instalada em seu computador, verifique como fazer isso aqui . Em seguida, execute o seguinte comando em um terminal de dentro do diretório do projeto:

$ gradle init 

Escolha um aplicativo Scala com Groovy como DSL. A saída deve ficar assim:

Iniciar um Daemon do Gradle (as compilações subsequentes serão mais rápidas)

Selecione o tipo de projeto a ser gerado:
  1: básico
  2: Aplicação
  3: biblioteca
  4: Plug-in do Gradle
Insira a seleção (padrão: básico) [1..4] 2

Selecione o idioma de implementação:
  1: C++
  2: Groovy
  3: Java
  4: Kotlin
  5: Escalão
  6: Rápido
Insira a seleção (padrão: Java) [1..6] 5

Dividir a funcionalidade em vários subprojetos?:
  1: não - apenas um projeto de aplicativo
  2: Sim - Projetos de aplicativos e bibliotecas
Insira a seleção (padrão: não - apenas um projeto de aplicativo) [1..2] 1

Selecione a DSL do script de compilação:
  1: Groovy
  2: Kotlin
Insira a seleção (padrão: Groovy) [1..2] 1

Gerar compilação usando novas APIs e comportamento (alguns recursos podem mudar na próxima versão secundária)? (Padrão: não) [Sim, não] Não                           
Nome do projeto (padrão: interactive-job-example): 
Pacote de origem (padrão: interactive.job.example): 

> Tarefa: init
Obtenha mais ajuda com seu projeto: https://docs.gradle.org/7.5.1/samples/sample_building_scala_applications_multi_project.html

CONSTRUÇÃO BEM-SUCEDIDA em 30s
2 tarefas acionáveis: 2 executadas 

Agora temos que adicionar o repositório Ilum e as dependências necessárias ao seu build.gradle arquivo. Neste tutorial, usaremos o Scala 2.12.

dependências {
    implementação 'org.scala-lang:scala-library:2.12.16'
    implementação 'cloud.ilum:ilum-job-api:5.0.1'
    compileOnly 'org.apache.spark:spark-sql_2.12:3.1.2'
} 

Agora podemos criar uma classe Scala que estende o Job de Ilum e que calcula PI:

pacote interativo.job.example

importar nuvem.ilum.job.Job
import org.apache.spark.sql.SparkSession
importar scala.math.random

class InteractiveJobExample extends Job {

override def run(sparkSession: SparkSession, config: Map[String, Any]): Option[String] = {

val slices = config.getOrElse("slices", "2").toString.toInt
    val n = math.min(100000L * fatias, Int.MaxValue).toInt
    val count = sparkSession.sparkContext.parallelize(1 até n, fatias).map { i =>
      val x = aleatório * 2 - 1
      val y = aleatório * 2 - 1
      se (x * x + y * y <= 1) 1 else 0
    }.reduce(_ + _)
    Some(s"Pi é aproximadamente ${4.0 * count / (n - 1)}")
  }
} 

Se o Gradle gerou algumas classes principais ou de teste, basta removê-las do projeto e fazer uma compilação.

$ compilação do gradle 

O arquivo jar gerado deve estar em ' ./exemplo-de-trabalho-interativo/app/build/libs/app.jar ', podemos então voltar para Ilum. Depois que todos os pods estiverem em execução, faça um encaminhamento de porta para ilum-ui:

SVC/ILUM-UI de encaminhamento de porta kubectl 9777:9777 

Abra a interface do usuário do Ilum em seu navegador e crie um novo grupo:

ilum ui spark monitoring

Coloque o nome de um grupo, escolha ou crie um cluster, carregue seu arquivo jar e aplique as alterações:

ilum add group

O Ilum criará um pod de driver do Spark e você poderá controlar o número de pods de executores do Spark dimensionando-os. Depois que o contêiner do Spark estiver pronto, vamos executar os trabalhos:

ilum execute job

Agora temos que colocar o nome canônico da nossa classe Scala

interactive.job.example.InteractiveJobExample 

e defina o parâmetro slices no formato JSON:

{
  "config": {
    "fatias": "10"
  }
} 

Você deve ver o resultado logo após o início do trabalho

Você pode alterar parâmetros e executar novamente um trabalho e seus cálculos ocorrerão no local.

Comparação interativa e de trabalho único

No Ilum, você também pode executar um único trabalho. A diferença mais importante em comparação com o modo interativo é que você não precisa implementar a API de trabalho. Podemos usar o jar SparkPi de exemplos do Spark:

ilum add job

Executar um trabalho como esse também é rápido, mas os trabalhos interativos são 20 vezes mais rápido (4s vs 200ms) . Se você quiser iniciar um trabalho semelhante com outros parâmetros, terá que preparar um novo trabalho e fazer o upload do jar novamente.

Comparação entre Ilum e Apache Spark simples


Configurei o Apache Spark localmente com um bitnami/faísca imagem do docker. Se você também quiser executar o Spark em sua máquina, poderá usar docker-compose:

$ curl -LO https://raw.githubusercontent.com/bitnami/containers/main/bitnami/spark/docker-compose.yml
$ docker-compose para cima 

Depois que o Spark estiver em execução, você poderá acessar localhost:8080 e ver a interface do usuário do administrador. Precisamos obter o URL do Spark no navegador:

spark admin

Em seguida, temos que abrir o contêiner do Spark no modo interativo usando

$ docker exec -it <containerid> -- bash 
spark container

E agora, dentro do contêiner, podemos enviar o trabalho do sparkPi. Neste caso, usará o SparkiPi do jar de exemplos e, como parâmetro mestre, colocará a URL do navegador:

$ ./bin/spark-submit --class org.apache.spark.examples.SparkPi\
  --mestre spark://78c84485d233:7077 \
  /opt/bitnami/spark/exemplos/jars/spark-examples_2.12-3.3.0.jar\
  10 

Resumo

Como você pode ver no exemplo acima, você pode evitar a configuração e a instalação complicadas do cliente Spark usando o Ilum. Ilum assume o trabalho e fornece uma interface simples e conveniente. Além disso, permite superar as limitações do Apache Spark, que podem levar muito tempo para inicializar. Se você tiver que fazer muitas execuções de trabalho com lógica semelhante, mas parâmetros diferentes e gostaria de ter cálculos feitos imediatamente, você definitivamente deve usar o modo de trabalho interativo.

Ilum ferret

Semelhanças com Apache Livy

O Ilum é uma ferramenta nativa da nuvem para gerenciar implantações do Apache Spark no Kubernetes. É semelhante ao Apache Livy em termos de funcionalidade - ele pode controlar uma sessão do Spark por meio da API REST e criar uma interação em tempo real com um cluster do Spark. No entanto, o Ilum foi projetado especificamente para ambientes modernos e nativos da nuvem.

Usamos o Apache Livy no passado, mas chegamos ao ponto em que o Livy simplesmente não era adequado para ambientes modernos. Tito Lívio está obsoleto em comparação com Ilum. Em 2018, começamos a mover todos os nossos ambientes para o Kubernetes e tivemos que encontrar uma maneira de implantar, monitorar e manter o Apache Spark no Kubernetes. Esta foi a ocasião perfeita para construir Ilum.