Integração SP-Franca
Integracao SP-Franca — Arquitetura
Objetivo
Integrar os sites Franca e Sao Paulo numa malha unificada onde:
- GPU jobs flutuam entre sites conforme disponibilidade
- Servicos de dados (Qdrant, Neo4j, PostgreSQL) sao acessiveis de qualquer cluster transparentemente
- Cada site opera autonomamente durante particoes de rede
- VMs e bare metal participam da mesma malha de rede que os pods K8s
Principio central
Cada ferramenta resolve exatamente UM problema. Nenhuma e a plataforma inteira.
Rede, federation, scheduling e roteamento de IA sao camadas independentes. Nenhuma ferramenta substitui outra — elas se complementam.
Visao geral: quem faz o que
┌────────────────────────────────────────────────────────────────────┐│ PLANO DE CONTROLE ││ ││ ArgoCD ──→ Karmada API ──→ PropagationPolicy ──→ Member Clusters ││ (o que) (para onde) (como distribuir) ││ ││ TensorZero ──→ vLLM/Whisper (qual backend usar, qual cluster) ││ (roteamento de requests GPU em tempo real) │├────────────────────────────────────────────────────────────────────┤│ PLANO DE REDE ││ ││ VyOS WireGuard ──→ tunel L3 entre sites ││ Cilium ──→ CNI dentro de cada cluster ││ Cilium Cluster Mesh ──→ service discovery cross-cluster ││ Cilium External Workloads ──→ VMs e bare metal na malha │├────────────────────────────────────────────────────────────────────┤│ PLANO DE EXECUCAO (por cluster) ││ ││ K3s ──→ container runtime ││ Kueue ──→ fila local de GPU jobs ││ KAI Scheduler ──→ GPU sharing dentro do node │├────────────────────────────────────────────────────────────────────┤│ CROSS-SITE BATCH ││ ││ MultiKueue ──→ despacha jobs para o cluster com GPU livre │└────────────────────────────────────────────────────────────────────┘Catalogo de ferramentas
Cada ferramenta responde UMA pergunta
| Ferramenta | Pergunta que responde | Escopo |
|---|---|---|
| VyOS WireGuard | ”Como os sites se conectam via IP?” | Rede L3 entre sites |
| Cilium | ”Como pods ganham IP e policies?” | CNI dentro de cada cluster |
| Cilium Cluster Mesh | ”Como um pod em SP encontra um service em Franca?” | Service discovery cross-cluster |
| Cilium External Workloads | ”Como VMs e bare metal participam da mesma malha?” | Estender Cilium para fora do K8s |
| Karmada | ”Onde esse Deployment roda? E se um site cair?” | Placement + failover de workloads |
| ArgoCD | ”O que deve estar deployed? O Git e a fonte de verdade” | GitOps, sync de manifests |
| Kueue | ”Tem GPU livre para esse job? Se nao, espere na fila” | Fila de jobs dentro do cluster |
| MultiKueue | ”Franca esta lotada, SP tem GPU livre?” | Fila de jobs cross-cluster |
| KAI Scheduler | ”Como 2 pods compartilham a mesma A5000?” | GPU sharing dentro do node |
| TensorZero | ”Qual backend atende esse request agora?” | Roteamento HTTP model-aware |
Detalhamento por camada
1. VyOS WireGuard — tunel L3 entre sites
O que e: tunel criptografado ponto-a-ponto entre os dois roteadores VyOS (Franca e SP).
Papel: criar conectividade IP entre as redes internas dos dois sites. Sem isso, os clusters nao se enxergam.
Topologia:
Franca (192.168.0.0/23) SP (192.168.2.0/23)VyOS 200.145.122.96 ←── WireGuard ──→ VyOS <IP-publico-SP> wg0: 10.0.0.1/30 wg0: 10.0.0.2/30
Rotas: Franca: 192.168.2.0/23 via 10.0.0.2 (wg0) SP: 192.168.0.0/23 via 10.0.0.1 (wg0)Por que WireGuard e nao Headscale: Headscale e mesh (N-to-N), bom para laptops e nodes dinamicos. WireGuard site-to-site e mais simples e deterministico para dois roteadores fixos. Menos pecas moveis.
Risco: a rede entre sites (UNESP/ANSP) pode ter latencia ou particoes — por isso clusters autonomos e nao cluster unico.
2. Cilium — CNI (Container Network Interface)
O que e: o “driver de rede” do Kubernetes. Substitui o Flannel padrao do K3s.
Papel dentro de cada cluster:
- Atribui IPs a pods
- Aplica NetworkPolicies (L3/L4/L7)
- Faz load balancing entre pods (kube-proxy replacement)
- Observabilidade de rede (Hubble)
Por que trocar Flannel por Cilium: Flannel e L3 puro, sem policies, sem observabilidade, e nao suporta Cluster Mesh. Cilium e pre-requisito para conectar os clusters.
Instalacao (cluster novo):
# K3s SP (novo, limpo):k3s server --flannel-backend=none --disable-network-policy --disable=servicelb
# Cilium via Helm:helm install cilium cilium/cilium \ --namespace kube-system \ --set cluster.name=sp \ --set cluster.id=2 \ --set ipam.mode=kubernetes \ --set kubeProxyReplacement=true3. Cilium Cluster Mesh — service discovery cross-cluster
O que e: extensao do Cilium que conecta dois (ou mais) clusters numa malha de servicos.
Papel: tornar um Service de um cluster visivel no outro transparentemente. Um pod em SP pode chamar qdrant.default.svc.cluster.local e o Cilium roteia para Franca se e la que o Qdrant roda.
Como funciona:
Cluster Franca (cluster.id=1) Cluster SP (cluster.id=2)┌──────────────────────┐ ┌──────────────────────┐│ clustermesh-apiserver │←── mTLS ────→│ clustermesh-apiserver ││ (expoe services) │ (via WG) │ (expoe services) │└──────────────────────┘ └──────────────────────┘Annotations em Services:
metadata: annotations: service.cilium.io/global: "true" # visivel cross-cluster service.cilium.io/affinity: "local" # prefere local, fallback remoto service.cilium.io/shared: "true" # ambos os clusters servemRoteamento por tipo de servico:
| Tipo de chamada | Quem roteia | Por que |
|---|---|---|
| GPU (vLLM, Whisper, embeddings) | TensorZero | Model-aware, A/B test, fallback cloud |
| Batch GPU (fine-tuning, OCR lote) | Kueue MultiKueue | Queue-aware, despacha para cluster com GPU livre |
| Dados (Trino, Neo4j, PostgreSQL, Qdrant) | Cilium Global Services | Service discovery transparente cross-cluster |
4. Cilium External Workloads — VMs e bare metal na malha
O que e: extensao do Cilium que permite VMs e hosts bare metal participarem da mesma malha de rede dos pods K8s, com identidade, policies e observabilidade.
Impacto na topologia:
Hoje (3 mundos separados): VyOS (rede) ←→ VMs (IPs fixos) ←→ K3s (pods, outro mundo de rede) Cada fronteira = NAT rules, firewall rules, IPs hardcoded
Com Cilium External Workloads (malha unica): Cilium mesh (tudo: pods + VMs + bare metal) └── identidade unica por workload └── policy unica (L3/L4/L7) └── observabilidade unica (Hubble) └── VyOS so faz borda internet ↔ rede internaCasos de uso concretos:
| Workload | Onde roda | Beneficio |
|---|---|---|
| debian-proxy (Traefik) | VM standalone | Acessa pods diretamente com mTLS, sem NodePort/NAT |
| vm-cpps-03 | VM | Crawlers e processos Python ganham identidade Cilium |
| Nodes Proxmox com GPU | Bare metal | LINSTOR satellite visivel como endpoint, com health check |
| DRBD replication cross-site | Bare metal | Comunicacao via malha criptografada do Cilium |
Comparacao com e sem:
| Sem Cilium (hoje) | Com Cilium External Workloads | |---|---|---| | Traefik → K3s via NodePort + IP fixo | Traefik → pods via service discovery direto | | VMs acessam cluster via kubectl/kubeconfig | VMs sao parte da malha, mesmas policies | | NetworkPolicy so dentro do K3s | NetworkPolicy se estende para VMs | | Observabilidade de rede para na borda do cluster | Hubble ve fluxos VM↔pod | | Acesso a LINSTOR via IP hardcoded | LINSTOR como endpoint Cilium |
Limitacao: replicacao DRBD high-throughput dentro do mesmo site deve usar rede L2 direta — o overhead de criptografia pode impactar. Para storage cross-site, o custo e aceitavel.
5. Karmada — orquestracao multi-cluster
O que e: control plane Kubernetes que distribui recursos para multiplos clusters. Voce fala com a API do Karmada como se fosse um cluster — ele propaga para os clusters reais.
Papel: decidir onde cada workload roda, com que configuracao, e o que fazer quando um cluster falha.
3 conceitos centrais:
a) PropagationPolicy — para onde vai
apiVersion: policy.karmada.io/v1alpha1kind: PropagationPolicymetadata: name: vllm-spreadspec: resourceSelectors: - apiVersion: apps/v1 kind: Deployment name: vllm placement: clusterAffinity: clusterNames: [franca, sp] replicaScheduling: replicaDivisionPreference: Weighted weightPreference: staticWeightList: - targetCluster: clusterNames: [franca] weight: 1 - targetCluster: clusterNames: [sp] weight: 1“vLLM roda nos dois clusters, distribuido igualmente.” Karmada olha a capacidade real (via ResourceEstimator) e ajusta.
b) OverridePolicy — ajustes por cluster
apiVersion: policy.karmada.io/v1alpha1kind: OverridePolicymetadata: name: vllm-francaspec: targetCluster: clusterNames: [franca] overriders: plaintext: - path: /spec/template/spec/nodeSelector/gpu.model operator: replace value: "a5500"“Em Franca, o vLLM usa nodeSelector para A5500.” Sem override, usaria o default do manifest.
c) Failover — o que acontece quando um cluster cai
placement: spreadConstraints: - spreadByField: cluster maxGroups: 2 minGroups: 1 clusterTolerations: - effect: NoExecute tolerationSeconds: 300 # 5min para failoverSe SP cai, apos 5 minutos o Karmada reschedula os workloads de SP para Franca (se tiver capacity).
Onde roda: no cluster Franca como “host cluster”. Instala apiserver + controller-manager + scheduler proprios. Os clusters reais se registram como members.
6. ArgoCD + Karmada — integracao
Modelo escolhido: ArgoCD → Karmada API (Opcao A)
Git repo (colabhd/devops) ↓ syncArgoCD (Franca) ↓ deploy paraKarmada API Server ↓ PropagationPolicy + OverridePolicy├── K3s Franca (member cluster)└── K3s SP (member cluster)Um ArgoCD so. Ele deploya no Karmada, que propaga para os member clusters. Se o control plane Karmada cair, os clusters continuam rodando o que ja tem deployed.
Alternativa futura (Opcao B): ArgoCD em cada cluster. Mais resiliente (se Franca cai, SP continua com ArgoCD proprio), mas mais pecas. Migrar quando a autonomia do SP se tornar critica.
7. Kueue — fila local de GPU jobs
O que e: admission controller que gerencia filas de jobs dentro de um cluster.
Papel: quando chega um job batch (fine-tuning, OCR em lote, eval), o Kueue coloca na fila e libera conforme a GPU fica disponivel. Evita overcommit.
Job "fine-tuning-llama" chega ↓Kueue ClusterQueue "gpu-batch" (quota: 2 GPUs) ↓ GPU livre? sim → admite o job, pod inicia nao → fila, espera outro job terminarSem Kueue: o job seria agendado pelo scheduler e disputaria GPU com servicos interativos (vLLM), degradando a API.
8. MultiKueue — batch cross-site
O que e: plugin do Kueue que conhece filas em multiplos clusters.
Papel: quando um job batch chega e o cluster local esta lotado, o MultiKueue despacha para o outro cluster.
Job "ocr-lote-500pdfs" chega em Franca ↓Kueue Franca: fila cheia (3 GPUs ocupadas) ↓MultiKueue consulta Kueue SP: 1 GPU livre ↓Job e despachado para SP via KarmadaSem MultiKueue: o job ficaria na fila de Franca esperando, mesmo com GPU livre em SP.
9. TensorZero — gateway de requests GPU em tempo real
O que e: API gateway OpenAI-compatible que roteia requests para backends de IA.
Papel diferente do Karmada: Karmada distribui Deployments (onde o pod roda). TensorZero roteia requests HTTP (qual backend atende essa chamada).
Pesquisador chama POST /v1/chat/completions ↓TensorZero avalia: - modelo pedido: llama-3.1-70b - backends disponiveis: vLLM-Franca (latencia 50ms), vLLM-SP (latencia 120ms) - A/B test ativo? sim → 80% Franca, 20% SP - rate limit do usuario? ok ↓Roteia para vLLM-FrancaPor que TensorZero e nao so Cilium load balancing: Cilium faz L4/L7 generico. TensorZero entende modelos de IA — sabe que llama-70b precisa de mais VRAM, sabe fazer fallback para cloud se ambos os sites estao lotados, faz A/B testing entre modelos.
Topologia alvo
┌─── Site Franca ──────────────────────────────────────────────────────┐│ ││ VyOS (200.145.122.96) ││ ├── NAT/Firewall (borda internet) ││ └── WireGuard wg0: 10.0.0.1/30 ──────────────────────┐ ││ │ ││ K3s Cluster Franca (Cilium CNI, cluster.id=1) │ ││ ├── Control Plane │ ││ ├── GPU Nodes: 3x A5500 (24GB) = 72 GB VRAM │ ││ ├── Karmada Control Plane (host cluster) │ ││ ├── ArgoCD (single instance → Karmada API) │ ││ ├── Cilium Cluster Mesh apiserver │ ││ ├── Kueue + MultiKueue │ ││ ├── TensorZero (AI gateway) │ ││ ├── vLLM, Whisper, Docling, BGE-M3 │ ││ └── Servicos de dados: Qdrant, Neo4j, PostgreSQL │ ││ │ ││ Cilium External Workloads: │ ││ ├── debian-proxy (Traefik) ← malha Cilium │ ││ ├── vm-cpps-03 ← malha Cilium │ ││ └── pve-labri-31/32/33 (LINSTOR) ← malha Cilium │ ││ │ │└──────────────────────────────────────────────────────────┼───────────┘ │ WireGuard (UNESP/ANSP) │ Cilium Cluster Mesh (mTLS) │ Karmada federation │ MultiKueue cross-site │ │┌─── Site SP ──────────────────────────────────────────────┼───────────┐│ │ ││ VyOS (<IP-publico-SP>) │ ││ ├── NAT/Firewall (borda internet) │ ││ └── WireGuard wg0: 10.0.0.2/30 ──────────────────────┘ ││ ││ K3s Cluster SP (Cilium CNI, cluster.id=2) ││ ├── Control Plane ││ ├── GPU Nodes: 3x A5000 (24GB) = 72 GB VRAM ││ ├── Karmada member cluster ││ ├── Cilium Cluster Mesh apiserver ││ ├── Kueue (local) ││ ├── vLLM, Whisper, Docling, BGE-M3 ││ └── Replicas de servicos web ││ ││ Cilium External Workloads: ││ └── pve-ippri-31/33/34 (LINSTOR + GPU) ← malha Cilium ││ │└──────────────────────────────────────────────────────────────────────┘Fases de implementacao
Cada fase funciona independente das seguintes. Ordem ditada por dependencias tecnicas.
Phase A — Cilium como CNI
Pre-requisito: nenhum (pode comecar imediatamente no cluster SP novo)
| Step | Tarefa | Detalhe |
|---|---|---|
| A.1 | Provisionar K3s SP com Cilium | --flannel-backend=none --disable-network-policy --disable=servicelb + Helm install Cilium (cluster.id=2) |
| A.2 | Migrar K3s Franca para Cilium | Opcao segura: criar K3s Franca novo com Cilium, redeployar via ArgoCD (GitOps = manifests sao fonte de verdade). Opcao rapida: migrar in-place com janela de manutencao (downtime) |
| A.3 | Onboard VMs na malha Cilium | Instalar cilium-agent em debian-proxy, vm-cpps-03. Testar: pod → VM e VM → pod sem NAT |
| A.4 | Onboard nodes Proxmox | Instalar cilium-agent em pve-labri-31/32/33 e pve-ippri-31/33/34. LINSTOR acessivel como endpoint Cilium |
Validacao: cilium connectivity test em cada cluster. Hubble mostrando fluxos pod ↔ VM.
Risco principal: migracao Flannel→Cilium no cluster Franca de producao. Mitigacao: usar a via GitOps (criar cluster novo, ArgoCD sincroniza tudo).
Artefatos no repo:
apps/cilium/├── values-franca.yaml # cluster.name=franca, cluster.id=1└── values-sp.yaml # cluster.name=sp, cluster.id=2Phase B — Conectividade cross-site
Pre-requisito: Phase A (Cilium em ambos os clusters)
| Step | Tarefa | Detalhe |
|---|---|---|
| B.1 | VyOS WireGuard site-to-site | Configurar tunel wg0 entre VyOS Franca e VyOS SP. Rotas estaticas para subnets remotas |
| B.2 | Cilium Cluster Mesh | cilium clustermesh enable em ambos. Conectar via cilium clustermesh connect |
| B.3 | Testar Global Services | Criar service de teste com service.cilium.io/global: "true" em Franca, acessar de SP |
Validacao: cilium clustermesh status mostra ambos os clusters connected. Pod em SP resolve DNS de service em Franca.
Artefatos no repo:
config/vyos/wireguard/├── franca.conf # interface wg0, peer SP└── sp.conf # interface wg0, peer FrancaPhase C — Karmada (federation)
Pre-requisito: Phase B (clusters conectados via Cluster Mesh)
| Step | Tarefa | Detalhe |
|---|---|---|
| C.1 | Instalar Karmada control plane | Helm chart karmada-io/karmada no cluster Franca (host cluster) |
| C.2 | Registrar member clusters | karmadactl join franca + karmadactl join sp |
| C.3 | Configurar ArgoCD → Karmada API | ArgoCD destination aponta para Karmada API server em vez de kubernetes.default.svc |
| C.4 | Instalar ResourceEstimator | Para Karmada ter visao de GPU capacity em cada cluster |
| C.5 | Definir PropagationPolicies | GPU services (spread), data services (affinity Franca), web services (replicas) |
| C.6 | Definir OverridePolicies | nodeSelector por cluster (a5500 vs a5000), resource limits |
| C.7 | Testar failover | Simular queda de SP, verificar rescheduling para Franca |
Validacao: karmadactl get clusters mostra ambos Ready. Deploy via ArgoCD propaga para os dois clusters. Failover funciona em <5min.
Artefatos no repo:
apps/karmada/├── values.yaml # Helm values do control plane├── propagation-policies/│ ├── gpu-services.yaml # vLLM, Whisper, Docling — spread│ ├── data-services.yaml # Qdrant, Neo4j — affinity Franca│ └── web-services.yaml # Open WebUI, Backstage — replicas├── override-policies/│ ├── franca.yaml # gpu.model=a5500│ └── sp.yaml # gpu.model=a5000Phase D — MultiKueue (batch cross-site)
Pre-requisito: Phase C (Karmada) + Kueue local em cada cluster (Phase 5 do gpu-platform.md)
| Step | Tarefa | Detalhe |
|---|---|---|
| D.1 | Kueue em cada cluster | Helm install Kueue com ClusterQueues locais (gpu-interactive, gpu-batch) |
| D.2 | MultiKueue admission controller | Configurar no Karmada para despacho cross-site |
| D.3 | ClusterQueues cross-site | Fairness: dinamico baseado em GPU livre, nao peso fixo |
| D.4 | Testar batch cross-site | Submeter job (fine-tuning Unsloth) com Franca lotada, verificar despacho para SP |
Validacao: job batch submetido em Franca e despachado para SP quando GPUs de Franca estao ocupadas.
Artefatos no repo:
apps/kueue/├── values-franca.yaml├── values-sp.yaml├── cluster-queues/│ ├── gpu-franca.yaml│ └── gpu-sp.yamlapps/karmada/multikueue/├── multikueue-config.yamlSequencia consolidada
| Step | O que | Pre-requisito | Risco |
|---|---|---|---|
| A.1 | K3s SP com Cilium | Nodes SP prontos | Baixo |
| A.2 | K3s Franca com Cilium | Janela manutencao | Alto (mitigar via GitOps) |
| A.3 | VMs na malha Cilium | A.1 ou A.2 | Baixo |
| A.4 | Nodes Proxmox na malha | A.1 ou A.2 | Baixo |
| B.1 | VyOS WireGuard site-to-site | IPs publicos | Baixo |
| B.2 | Cilium Cluster Mesh | A.1 + A.2 + B.1 | Medio |
| B.3 | Testar Global Services | B.2 | Baixo |
| C.1 | Karmada control plane | B.2 | Medio |
| C.2 | Registrar clusters | C.1 | Baixo |
| C.3 | ArgoCD → Karmada API | C.2 | Medio |
| C.4-C.7 | Policies + failover | C.3 | Baixo-Medio |
| D.1 | Kueue local | Clusters federados | Baixo |
| D.2-D.4 | MultiKueue cross-site | C.1 + D.1 | Medio |
Decisoes em aberto
| Decisao | Opcoes | Quando decidir |
|---|---|---|
| Migrar Franca in-place vs criar cluster novo | In-place (rapido, downtime) vs novo cluster (seguro, mais trabalho) | Antes de A.2 |
| Karmada host cluster vs VM dedicada | No cluster Franca (menos infra) vs VM separada (isolamento) | Antes de C.1 |
| ArgoCD Opcao A vs B | Single ArgoCD → Karmada (simples) vs ArgoCD por cluster (resiliente) | Antes de C.3 |
| IP publico do site SP | Fixo da UNESP/ANSP ou dinamico | Antes de B.1 |
| DRBD cross-site via Cilium ou rede direta | Cilium (criptografado, overhead) vs L2 direto (rapido, sem crypto) | Antes de A.4 |
Relacao com outros roadmaps
- gpu-platform.md Phase 8: este documento detalha e expande a Phase 8
- gpu-platform.md Phases 0-7: pre-requisitos (GPU no K3s, Kueue, servicos de IA)
- data-platform.md: servicos de dados (Qdrant, Neo4j, Trino) serao distribuidos via Cilium Global Services + Karmada PropagationPolicy
- iac.md: Pulumi provisiona K3s SP, Ansible configura nodes, ArgoCD sincroniza apps — mesma divisao