Saltar para o conteúdo principal
Versão 3.0.0

Integrações — JupyterLab

Integração com Spark

O chart tdp-jupyter integra-se com o Apache Spark via o mecanismo tdpSparkIntegration. Ao ativar a integração, um ConfigMap (tdp-jupyter-spark-integration) é criado com as configurações de spark-defaults.conf e um script auxiliar jupyter-spark-env.sh.

Os pods de notebooks montam esse ConfigMap em /opt/bitnami/spark/conf e executam o script no postStart, de modo que cada sessão Spark encontra o master correcto automaticamente.

Para o usuário final, a decisão principal é simples:

  • usar PySpark local para testes rápidos e desenvolvimento;
  • usar cluster Spark externo quando quiser distribuir processamento;
  • usar Iceberg a partir do notebook apenas depois de a integração Spark e o catálogo Iceberg já estarem configurados no ambiente.

Modos de operação

ModotdpSparkIntegration.enabledValor resolvido para spark.masterUso típico
PySpark localfalselocal[*]Executa Spark dentro do próprio pod do notebook (padrão para desenvolvimento)
Cluster externotruespark://<release>-spark-master-svc.<namespace>.svc.cluster.local:7077Liga a um deployment Spark já existente
dica

O parâmetro spark.master no values.yaml fica vazio por padrão. O template escolhe o valor correcto em tempo de renderização com base em tdpSparkIntegration.enabled. É possível fornecer uma URL personalizada se necessário.

Componentes envolvidos

ComponenteFunção
templates/spark-integration-configmap.yamlRenderiza as configurações Spark e o script auxiliar de ambiente
singleuser.extraEnvDefine variáveis de ambiente Spark para cada pod de notebook
singleuser.lifecycleHooks.postStartExecuta jupyter-spark-env.sh antes do JupyterLab iniciar
singleuser.networkPolicy.egressPermite que os pods de notebook alcancem o Spark master e serviços auxiliares

Variáveis de ambiente injectadas nos pods de notebook

SPARK_HOME=/opt/bitnami/spark
PYTHONPATH=/opt/bitnami/spark/python:/opt/bitnami/spark/python/lib/py4j-0.10.9.7-src.zip
SPARK_CONF_DIR=/opt/bitnami/spark/conf
PYSPARK_PYTHON=/opt/conda/envs/py312/bin/python
PYSPARK_DRIVER_PYTHON=/opt/conda/envs/py312/bin/python
SPARK_MASTER_URL=<automático> # local[*] ou spark://... conforme tdpSparkIntegration.enabled
SPARK_DRIVER_PORT=2222
SPARK_BLOCKMANAGER_PORT=7777

Volumes montados nos pods de notebook

CaminhoTipoConteúdo
/opt/bitnami/spark/confConfigMapspark-defaults.conf e scripts auxiliares
/tmp/spark-localemptyDirDados temporários e shuffle do Spark
/tmp/spark-logsemptyDirLogs do driver Spark

Como configurar

Modo 1 — PySpark local (padrão)

Não requer um cluster Spark externo. O Spark é executado dentro do pod do notebook com local[*]:

tdpSparkIntegration:
enabled: false
deploySparkCluster: false
configMap:
sparkConfig:
"spark.master": "" # resolve para local[*]

Teste num notebook:

from pyspark.sql import SparkSession

spark = SparkSession.builder.appName("Local PySpark").getOrCreate()
print(spark.sparkContext.master) # local[*]

Modo 2 — Cluster Spark externo

Liga os notebooks a um deployment Spark já existente no cluster Kubernetes:

tdpSparkIntegration:
enabled: true
deploySparkCluster: false # false = apontar para deployment existente
configMap:
sparkConfig:
"spark.kubernetes.namespace": "tdp-project" # opcional
"spark.master": "" # resolve para spark://<release>-spark-master-svc.<ns>:7077
"spark.driver.host": "" # deixe vazio para usar o serviço admin do notebook
"spark.executor.instances": "2"
"spark.executor.memory": "4g"
"spark.executor.cores": "3"

tdp-spark:
spark:
worker:
replicaCount: 2
resources:
limits:
cpu: 4
memory: 6Gi

Certifique-se de que o serviço Spark master é acessível a partir do namespace dos notebooks (ex.: tdp-spark-master-svc.tdp-project.svc.cluster.local:7077).

Considerações sobre NetworkPolicy

  • Os pods de notebook adicionam uma regra de egress que corresponde a qualquer Spark master (app.kubernetes.io/component: master, app.kubernetes.io/name: spark).
  • Se o chart Spark tiver a sua própria NetworkPolicy, permita ligações de entrada a partir do namespace dos notebooks.

Modo 3 — Cluster Spark integrado (opcional)

Define tdpSparkIntegration.deploySparkCluster: true para instalar o subchart tdp-spark juntamente com o JupyterHub:

tdpSparkIntegration:
enabled: true
deploySparkCluster: true

Ajuste os valores de stack/charts/tdp/tdp-spark conforme necessário.

Uso de Iceberg a partir do Jupyter

O suporte a Iceberg no Jupyter não é uma integração separada do chart tdp-jupyter. Na prática, ele acontece via Spark:

  • o notebook liga-se ao Spark;
  • o Spark precisa conhecer o catálogo Iceberg;
  • o catálogo Iceberg precisa de acesso ao Hive Metastore e ao storage S3/MinIO.

Por isso:

nota

Não trate Iceberg como obrigatório para o Jupyter. Ele é apenas um cenário adicional para notebooks que precisem consultar ou manter tabelas Iceberg via Spark.


Instalar ou atualizar o JupyterHub

Terminal input
helm upgrade --install <release> \
oci://registry.tecnisys.com.br/tdp/charts/tdp-jupyter \
-n <namespace> \
-f values.yaml
Após atualizações

Sempre que modificar ConfigMaps ou variáveis de ambiente, reinicie os pods de usuário (Stop Server → Start Server no JupyterHub) para que as novas configurações entrem em vigor.


Checklist de verificação

  1. Pods em execução

    Terminal input
    kubectl get pods -n <namespace> | grep jupyter
  2. ConfigMap Spark criado

    Terminal input
    kubectl get configmap tdp-jupyter-spark-integration -n <namespace> -o yaml
  3. Conectividade de rede (a partir de um pod de notebook)

    Terminal input
    kubectl exec -n <namespace> <pod> -- \
    curl -sv tdp-spark-master-svc.<namespace>.svc.cluster.local:7077

Testar a integração

Notebook de teste incluído no chart

O chart inclui um notebook de teste (tdp-jupyter-spark-test ConfigMap). Para o extrair:

Terminal input
kubectl get configmap tdp-jupyter-spark-test -n <namespace> \
-o jsonpath='{.data.spark-integration-test\.ipynb}' \
> spark-integration-test.ipynb

Faça upload do notebook pelo JupyterLab e execute cada célula.

Smoke test manual

Execute o seguinte código num notebook para validar a integração:

import os
from pyspark.sql import SparkSession

print("SPARK_HOME:", os.environ.get("SPARK_HOME"))
print("SPARK_MASTER_URL:", os.environ.get("SPARK_MASTER_URL"))

spark = SparkSession.builder.appName("TDP-Jupyter Smoke Test").getOrCreate()
print("Versão Spark:", spark.version)
print("Master activo:", spark.sparkContext.master)

spark.range(5).show()
spark.stop()

Resolução de problemas

SintomaCausa provávelAcção sugerida
JAVA_GATEWAY_EXITED ou erros Py4JSPARK_HOME/PYTHONPATH mal configuradosVerifique se singleuser.extraEnv usa os caminhos /opt/bitnami/spark
IllegalStateException: Cannot call methods on a stopped SparkContextSpark master inacessível ou NetworkPolicy a bloquear egress/ingressConfirme tdpSparkIntegration.enabled, verifique o serviço Spark, ajuste as NetworkPolicies
Pod do notebook falha no arranque (ImportError para zmq)PYTHONPATH poluído com site-packages PySparkNão adicione /opt/conda/envs/py312/lib/python3.12/site-packages ao PYTHONPATH
Driver Spark não consegue ligar/comunicarSPARK_DRIVER_HOST não resolúvelDeixe em branco para usar o serviço admin do notebook ou forneça uma entrada DNS acessível

Comandos de diagnóstico

Terminal input
# Logs do pod do notebook
kubectl logs -n <namespace> <notebook-pod>

# Variáveis de ambiente Spark dentro do pod
kubectl exec -n <namespace> <notebook-pod> -- env | grep SPARK

# Listar arquivos montados
kubectl exec -n <namespace> <notebook-pod> -- ls -R /opt/bitnami/spark/conf

# Verificar endpoints do serviço Spark master
kubectl get svc -n <namespace> | grep spark-master

Personalização avançada

  • Adicione propriedades Spark extra em tdpSparkIntegration.configMap.sparkConfig.
  • Defina perfis de tamanho de notebook via singleuser.profileList e ajuste variáveis de ambiente Spark por perfil.
  • Quando usar múltiplos clusters Spark, sobreponha spark.master por perfil ou via ambiente de usuário.

Limpeza

Terminal input
helm uninstall <release> -n <namespace>
kubectl delete configmap tdp-jupyter-spark-integration -n <namespace>