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 ficheiros e exploram dados directamente no browser.
No TDP Kubernetes, o JupyterLab é servido pelo JupyterHub, responsável pela autenticação e pelo ciclo de vida dos ambientes de cada utilizador no cluster.
Consulte JupyterLab — Conceitos para uma visão completa da ferramenta, a sua arquitectura e funcionamento.
Estrutura de valores (Helm)
O chart tdp-jupyter organiza a sua configuração em quatro blocos principais:
| Bloco | Finalidade |
|---|---|
tdp-jupyter: | Configuração do JupyterHub: Hub, Proxy, pods single-user, autenticação, armazenamento e segurança |
tdpSparkIntegration: | Integração com Spark: modo local ou cluster externo, ConfigMap e subchart opcional |
TDP-Settings: | Configurações TDP: base de dados externa e controlo 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 |
| Base de dados de metadados | SQLite por omissã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 pela autenticação e gestão dos ambientes |
| Proxy | Proxy reverso que encaminha cada utilizador para o seu ambiente |
| Single-user pods | Um pod Kubernetes por utilizador autenticado |
| PVCs | Armazenamento persistente para os notebooks, quando configurado |
Modelo single-user
Cada vez que um utilizador inicia sessão, o Hub cria um pod dedicado no Kubernetes. Quando o utilizador para o servidor, o pod é terminado, mas o armazenamento pode persistir se estiver associado a um PVC.
O dimensionamento do cluster deve considerar o pico esperado de utilizadores 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 utilizador 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
- Resoluçã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 ficheiro -f, são usados os valores padrão do chart. Em ambientes de produção, versione um ficheiro de valores com recursos, armazenamento e tipo de Service alinhados à política do cluster.
OpenShift
O chart detecta automaticamente o ambiente OpenShift através 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 ficheiro overlay values-openshift.yaml:
openshift:
enabled: true
tdp-jupyter:
scheduling:
userScheduler:
containerSecurityContext:
runAsNonRoot: true
Quando o modo OpenShift está activo, 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-instalação que nulifica
runAsUser/runAsGroupno Hub e forçarunAsNonRoot: true
Parâmetros principais
| Parâmetro | Descrição | Valor por omissão |
|---|---|---|
tdp-jupyter.enabled | Activar 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 | Utilizador por omissão | admin |
tdp-jupyter.hub.config.DummyAuthenticator.password | Palavra-passe por omissã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 utilizador | 5Gi |
tdp-jupyter.singleuser.storage.dynamic.storageClass | StorageClass do PVC | 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 | Activar base de dados externa | false |
TDP-Settings.externalDatabase.recreate | Recriar base de dados na actualização | false |
TDP-Settings.gateway.ingress.enabled | Activar Ingress | false |
TDP-Settings.gateway.gatewayApi.enabled | Activar Gateway API | false |
tdpSparkIntegration.enabled | Activar integração com Spark | false |
tdpSparkIntegration.deploySparkCluster | Instalar subchart tdp-spark | false |
openshift.enabled | Forçar modo OpenShift | false |
Base de dados externa (PostgreSQL)
Por omissã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 deve ser gerida 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
Armazenamento
Cada utilizador autenticado pode receber um volume persistente para o directó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 aceder a um endpoint de armazenamento S3 interno —, utilize singleuser.extraPodConfig.hostAliases:
tdp-jupyter:
singleuser:
extraPodConfig:
hostAliases:
- ip: "<CONTROLLER_IP>"
hostnames:
- "<COMPONENT_HOSTNAME>"
Este parâmetro adiciona entradas ao ficheiro /etc/hosts de cada pod de notebook, permitindo que o Spark e as bibliotecas Python resolvam o hostname para o IP indicado.
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 resolução de problemas ficam em Integrações — JupyterLab.
Exposição do serviço
A forma de expor o Proxy define como os utilizadores chegam à interface.
NodePort (por omissão)
tdp-jupyter:
proxy:
service:
type: NodePort
nodePorts:
http: 30080
https: 30443
kubectl get nodes -o wide
# Aceda via http://<NODE_IP>:30080
Port-forward
kubectl -n <NAMESPACE> port-forward service/<RELEASE_NAME>-proxy 8080:80
# Aceda 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 aceder à 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 directa pelo Service, tdp-jupyter.proxy.service.type pode ser ajustado para LoadBalancer no ficheiro de valores. Esta é 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.
Resolução de problemas
# Estado dos pods
kubectl -n <NAMESPACE> get pods -l app.kubernetes.io/instance=<RELEASE_NAME>
# Registos do Hub
kubectl -n <NAMESPACE> logs -l app.kubernetes.io/component=hub
# Registos do Proxy
kubectl -n <NAMESPACE> logs -l app.kubernetes.io/component=proxy
# Eventos do pod
kubectl -n <NAMESPACE> describe pod <POD_NAME>
# PVCs
kubectl -n <NAMESPACE> get pvc -l app.kubernetes.io/instance=<RELEASE_NAME>
# Base de dados externa (se configurada)
kubectl -n <NAMESPACE> exec -it <POD_NAME> -- \
psql "postgresql://<DATABASE_USER>@<POSTGRESQL_SERVICE>.<NAMESPACE>.svc.cluster.local:5432/<DATABASE_NAME>"
| Sintoma | Causa provável | Acção sugerida |
|---|---|---|
Pods em Pending | StorageClass inexistente ou sem capacidade | Verifique o provisionador de PV e as quotas |
| Falha de conexão Spark | NetworkPolicy ou serviço Spark inacessível | Verifique tdpSparkIntegration.enabled e conectividade |
| Falha de conexão com base de dados externa | PostgreSQL inacessível ou credenciais incorrectas | Verifique URL, Secret e acessibilidade do PostgreSQL |
| Pods OOMKilled | Limites de CPU/memória demasiado 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 utilizadores não são removidos automaticamente. Para os remover:
kubectl delete pvc -l app.kubernetes.io/instance=<RELEASE_NAME> -n <NAMESPACE>
Esta operação é destrutiva e elimina os dados de notebook de todos os utilizadores.