Configuração do JupyterLab
O que é o JupyterLab?
O JupyterLab é a interface interativa de notebooks do TDP Kubernetes. É o ambiente onde analistas e engenheiros de dados escrevem e executam código, organizam arquivos e exploram dados diretamente no browser.
No TDP Kubernetes, o JupyterLab é servido pelo JupyterHub, responsável pela autenticação e pelo ciclo de vida dos ambientes de cada usuário no cluster.
Consulte JupyterLab — Conceitos para uma visão completa da ferramenta, sua arquitetura e funcionamento.
Estrutura de valores (Helm)
O chart tdp-jupyter organiza sua configuração em quatro blocos principais:
| Bloco | Finalidade |
|---|---|
tdp-jupyter: | Configuração do JupyterHub: Hub, Proxy, pods single-user, autenticação, storage e segurança |
tdpSparkIntegration: | Integração com Spark: modo local ou cluster externo, ConfigMap e subchart opcional |
TDP-Settings: | Configurações TDP: banco de dados externo e controle de exposição (Ingress/Gateway API) |
openshift: | Forçar modo OpenShift quando a detecção automática não é possível |
Use helm show values oci://registry.tecnisys.com.br/tdp/charts/tdp-jupyter > values-padrao.yaml para consultar todos os parâmetros disponíveis.
Visão geral
| Propriedade | Valor |
|---|---|
| Chart | tdp-jupyter |
| Versão do JupyterHub | 5.3.0 |
| Versão do chart | 3.0.1 |
| Interface de uso | JupyterLab servido pelo JupyterHub |
| Modelo de execução | Um pod single-user por usuário autenticado |
| Banco de metadados | SQLite por padrão, com opção de PostgreSQL externo |
| Exposição HTTP | Proxy do JupyterHub via Service, Ingress ou Gateway API |
Componentes principais
| Componente | Descrição |
|---|---|
| Hub | Serviço central do JupyterHub, responsável por autenticação e gestão dos ambientes |
| Proxy | Proxy reverso que encaminha cada usuário para o seu ambiente |
| Single-user pods | Um pod Kubernetes por usuário autenticado |
| PVCs | Armazenamento persistente para os notebooks, quando configurado |
Modelo single-user
Cada vez que um usuário faz login, o Hub cria um pod dedicado para ele no Kubernetes. Quando o usuário para o servidor, o pod é encerrado, mas o storage pode persistir se estiver associado a PVC.
Isso significa que o dimensionamento do cluster deve considerar o pico esperado de usuários simultâneos.
Kernel padrão (Python 3.12)
Ao iniciar, o pod single-user executa um postStart hook que torna o kernel py312 (Python 3.12, com as bibliotecas Spark/Delta/Iceberg pré-instaladas) o kernel padrão exibido como "Python 3" no notebook — o kernel python3 original é substituído pela cópia do py312. A configuração KernelSpecManager.allowed_kernelspecs restringe a lista de kernels disponíveis ao usuário a esse kernel.
Pré-requisitos
- Kubernetes 1.32+, Red Hat OpenShift 4.19+ ou Rancher Manager 2.10.x+
- Helm 3.2.0+
- Provisionador de PV disponível no cluster
- Cluster Spark disponível via
tdp-sparkou instalação compatível, quando for usar a integração Spark
Páginas relacionadas
- Instalação
- Parâmetros principais
- Detalhes de configuração
- Acesso & Segurança
- Solução de problemas
- Desinstalação
Instalação (OCI)
Kubernetes
helm upgrade --install <RELEASE_NAME> \
oci://registry.tecnisys.com.br/tdp/charts/tdp-jupyter \
-n <NAMESPACE> --create-namespace --timeout 10m
Sem um arquivo -f, utilizam-se os valores padrão do chart. Em ambientes reais, versione um arquivo de valores com recursos, storage e tipo de Service alinhados à política do cluster.
OpenShift
O chart detecta automaticamente o ambiente OpenShift por meio da API de descoberta do Kubernetes. Se a detecção automática não for possível (redes restritas, pipelines CI), force o modo OpenShift explicitamente:
helm upgrade --install <RELEASE_NAME> \
oci://registry.tecnisys.com.br/tdp/charts/tdp-jupyter \
-n <NAMESPACE> --create-namespace --timeout 10m \
--set openshift.enabled=true \
--set tdp-jupyter.scheduling.userScheduler.containerSecurityContext.runAsNonRoot=true
Ou use um arquivo overlay values-openshift.yaml:
openshift:
enabled: true
tdp-jupyter:
scheduling:
userScheduler:
containerSecurityContext:
runAsNonRoot: true
Quando o modo OpenShift está ativo, o chart aplica automaticamente:
- Volumes de overlay para
/etc/passwde/etc/groupnos pods single-user - Init container
openshift-passwd-bootstrappara mapear UID/GID - Hook pós-install que nulifica
runAsUser/runAsGroupno Hub e forçarunAsNonRoot: true
Parâmetros principais
| Parâmetro | Descrição | Padrão |
|---|---|---|
tdp-jupyter.enabled | Habilitar JupyterHub | true |
tdp-jupyter.hub.resources.requests.cpu | CPU mínima do Hub | 500m |
tdp-jupyter.hub.resources.requests.memory | Memória mínima do Hub | 1Gi |
tdp-jupyter.hub.resources.limits.cpu | CPU máxima do Hub | 1000m |
tdp-jupyter.hub.resources.limits.memory | Memória máxima do Hub | 2Gi |
tdp-jupyter.hub.config.JupyterHub.authenticator_class | Classe de autenticação | dummy |
tdp-jupyter.hub.config.DummyAuthenticator.username | Usuário padrão (autenticação básica) | admin |
tdp-jupyter.hub.config.DummyAuthenticator.password | Senha padrão (alterar em produção) | tdp-password |
tdp-jupyter.singleuser.cpu.limit | CPU máxima por notebook | 4 |
tdp-jupyter.singleuser.cpu.guarantee | CPU garantida por notebook | 2 |
tdp-jupyter.singleuser.memory.limit | Memória máxima por notebook | 8G |
tdp-jupyter.singleuser.memory.guarantee | Memória garantida por notebook | 4G |
tdp-jupyter.singleuser.storage.capacity | Tamanho do PVC por usuário | 5Gi |
tdp-jupyter.singleuser.storage.dynamic.storageClass | StorageClass do PVC de usuário | null (padrão do cluster) |
tdp-jupyter.proxy.service.type | Tipo de Service do Proxy | NodePort |
tdp-jupyter.proxy.service.nodePorts.http | Porta HTTP NodePort | 30080 |
tdp-jupyter.proxy.service.nodePorts.https | Porta HTTPS NodePort | 30443 |
TDP-Settings.externalDatabase.enabled | Habilitar banco de dados externo | false |
TDP-Settings.externalDatabase.recreate | Recriar banco ao atualizar | false |
TDP-Settings.gateway.ingress.enabled | Habilitar Ingress | false |
TDP-Settings.gateway.gatewayApi.enabled | Habilitar Gateway API | false |
tdpSparkIntegration.enabled | Habilitar integração com Spark | false |
tdpSparkIntegration.deploySparkCluster | Instalar subchart tdp-spark junto | false |
openshift.enabled | Forçar modo OpenShift | false |
Banco externo (PostgreSQL)
Por padrão, o Hub usa SQLite com armazenamento em PVC. Para ambientes de produção com múltiplas réplicas ou quando a persistência do Hub precisa ser gerenciada fora do ciclo de vida do release Helm, use PostgreSQL externo.
TDP-Settings:
externalDatabase:
enabled: true
recreate: false
externalSecret:
releaseName: "<POSTGRESQL_RELEASE>"
tdp-jupyter:
hub:
db:
type: postgres
url: "postgresql://<DATABASE_USER>@<POSTGRESQL_SERVICE>.<NAMESPACE>.svc.cluster.local:5432/<DATABASE_NAME>"
password: null
upgrade: false
extraEnv:
PGPASSWORD:
valueFrom:
secretKeyRef:
name: "<SECRET_NAME>"
key: password
Storage
Cada usuário autenticado pode receber um volume persistente para o diretório de trabalho. A StorageClass define onde e como o disco é provisionado.
singleuser:
storage:
dynamic:
storageClass: <STORAGE_CLASS>
capacity: 5Gi
Escolha a storageClass compatível com o provisionador disponível no cluster e defina a capacity de acordo com o uso esperado de dados locais nos notebooks.
Host aliases
Quando os pods de notebook precisam resolver hostnames que não estão no DNS do cluster — por exemplo, para acessar um endpoint de armazenamento S3 interno —, use singleuser.extraPodConfig.hostAliases:
tdp-jupyter:
singleuser:
extraPodConfig:
hostAliases:
- ip: "<CONTROLLER_IP>"
hostnames:
- "<COMPONENT_HOSTNAME>"
Esse parâmetro adiciona entradas ao arquivo /etc/hosts de cada pod de notebook, permitindo que o Spark e as bibliotecas Python resolvam o hostname para o IP informado.
Integração com Spark
O JupyterLab pode funcionar sem integração com Spark (modo local[*]) ou ligar-se a um cluster Spark externo. Os detalhes completos, modos de operação e troubleshooting ficam em Integrações — JupyterLab.
Exposição do serviço
A forma de expor o Proxy define como os usuários chegam à interface.
NodePort (padrão)
tdp-jupyter:
proxy:
service:
type: NodePort
nodePorts:
http: 30080
https: 30443
kubectl get nodes -o wide
# Acesse via http://<NODE_IP>:30080
Port-forward
kubectl -n <NAMESPACE> port-forward service/<RELEASE_NAME>-proxy 8080:80
# Acesse via http://localhost:8080
LoadBalancer
tdp-jupyter:
proxy:
service:
type: LoadBalancer
kubectl get svc <RELEASE_NAME>-proxy -n <NAMESPACE>
Use o IP externo fornecido pelo provisionador de LoadBalancer para acessar a interface.
ClusterIP
tdp-jupyter:
proxy:
service:
type: ClusterIP
Restringe o acesso ao interior do cluster (apenas interno).
Exposição externa
Para exposição externa estável por Ingress ou Gateway API, consulte a página de exposição externa.
Se o ambiente exigir exposição direta pelo Service, tdp-jupyter.proxy.service.type pode ser ajustado para LoadBalancer no arquivo de valores. Essa é uma decisão de Service Kubernetes, não um modo de exposição HTTP/HTTPS equivalente aos modelos Ingress/Gateway API.
Autenticação
A configuração detalhada de autenticação, LDAP e boas práticas de acesso fica em Segurança — JupyterLab.
Solução de problemas
# Status dos pods
kubectl -n <NAMESPACE> get pods -l app.kubernetes.io/instance=<RELEASE_NAME>
# Logs do Hub
kubectl -n <NAMESPACE> logs -l app.kubernetes.io/component=hub
# Logs do Proxy
kubectl -n <NAMESPACE> logs -l app.kubernetes.io/component=proxy
# Eventos de pod
kubectl -n <NAMESPACE> describe pod <POD_NAME>
# PVCs
kubectl -n <NAMESPACE> get pvc -l app.kubernetes.io/instance=<RELEASE_NAME>
# Banco externo (se configurado)
kubectl -n <NAMESPACE> exec -it <POD_NAME> -- \
psql "postgresql://<DATABASE_USER>@<POSTGRESQL_SERVICE>.<NAMESPACE>.svc.cluster.local:5432/<DATABASE_NAME>"
| Sintoma | Causa provável | Ação sugerida |
|---|---|---|
Pods em Pending | StorageClass inexistente ou sem capacidade | Verifique provisionador de PV e cotas |
| Falha de conexão Spark | NetworkPolicy ou serviço Spark inacessível | Verifique tdpSparkIntegration.enabled e conectividade |
| Falha de conexão com banco externo | PostgreSQL inacessível ou credenciais incorretas | Verifique URL, Secret e acessibilidade do PostgreSQL |
| Pods OOMKilled | Limites de CPU/memória muito baixos | Ajuste hub.resources e singleuser.cpu/singleuser.memory |
Desinstalação
helm uninstall <RELEASE_NAME> -n <NAMESPACE>
kubectl delete configmap <RELEASE_NAME>-spark-integration -n <NAMESPACE>
Os PVCs dos usuários não são removidos automaticamente. Para removê-los:
kubectl delete pvc -l app.kubernetes.io/instance=<RELEASE_NAME> -n <NAMESPACE>
Essa operação é destrutiva e apaga os dados de notebook de todos os usuários.