Skip to content

Arquitetura da Infraestrutura

Este documento define o que cada componente faz, por que está onde está e o que ainda não está implementado. O Roadmap usa este modelo pra ordenar as fases.

📌 Pré-requisito de leitura: Contexto institucional — missão CPPS + Lab Multiusuário IPPRI + Colaboratório de Humanidades Digitais. Toda decisão arquitetural deste documento deve ser conectável àquele contexto.

Os 3 estados

Toda afirmação sobre a infra deve cair em uma destas categorias. Misturar os três é o erro mais comum.

EstadoSignificadoExemplo
Validado em produçãoFunciona hoje, com tráfego/dados reaisLINSTOR SP SSD, Tutor/Open edX, VyOS Franca
Declarado em IaCExiste no código (Pulumi/Ansible) mas não foi aplicado/validado em produçãotraefik-sp com ha: True no config (Pulumi não cria HA real ainda)
Desejado (roadmap)Decisão arquitetural mas sem código nem validaçãoPBS cross-site, Cilium ClusterMesh, ArgoCD SP

Cada item deste documento marca explicitamente seu estado.

Visão geral

A infra CPPS opera em 2 sites institucionais (Franca e SP — Praça da Sé) interligados via UnespNet, com autonomia local em cada site e operação integrada quando a rede entre-sites está disponível. Roadmap futuro inclui:

  • Cloud privada (AWS, Azure) — bursting de capacidade sob demanda
  • HPC externo (Grid Unesp, supercomputadores) — execução de jobs batch

Princípios

  1. Autonomia por site — cada site sobrevive a partição de rede; nada essencial depende de link cross-site
  2. Modularidade entre camadas — cada camada tem interface clara; trocar componente não cascata pras demais
  3. Declarativo > imperativo — config como código (Pulumi, Ansible, ArgoCD); estado reproduzível
  4. GitOps no plano de aplicações — main do repo é a fonte da verdade; ArgoCD reconcilia
  5. Backup defensivo — perda de 1 site não significa perda de dados (replicação intra-site + backup cross-site)
  6. Frugalidade operacional — toda peça nova custa tempo de admin; só entra com caso de uso comprovado
  7. Distinguir HA de DR — replicação síncrona (LINSTOR) protege contra falha de hardware; backup (PBS) protege contra erro lógico/desastre

Estrutura

Ver diagrama interativo das camadas → Catálogo visual

Por que essas camadas?

A ordenação é bottom-up por dependência operacional: cada camada N só pode ser operada sobre a N-1 estável. GPU/HPC não é uma camada porque atravessa workloads (camada 8) — é capacidade aplicada onde existe hardware GPU.


Camada 0 — Virtualização (Proxmox)

Papel: substrato de compute. Cria VMs (full-virt) e LXCs sobre hardware físico.

Componentes: Proxmox VE 8.x/9.x · cluster por site (Franca: pve-labri-*, SP: pve-ippri-*) · Pulumi (IaC) · Ansible (config OS).

Por que aqui: isola hardware das camadas acima. Trocar hardware ou migrar VM entre nodes não muda nada da camada 1+.

Estado:

  • ✅ Validado: 2 clusters Proxmox em produção (Franca: 7 hosts, SP: 6 hosts)
  • 🚧 Em andamento: upgrade PVE 9.x dos nodes restantes
  • ❌ Desejado: cluster Proxmox cross-site rejeitado (latência incompatível com pmxcfs)

Pendências:

  • Upgrade PVE 8.4 → 9.x dos nodes restantes
  • Padronizar template LXC Debian 13
  • HA configurado via Proxmox (declarado mas não implementado em VMs como traefik-sp)

Camada 1 — Storage distribuído (LINSTOR + DRBD)

Papel: block storage replicado, intra-site. Volumes lineares acessíveis por todas as VMs/LXCs do site (live migration sem downtime).

Componentes: LINSTOR (controller + satellites) · DRBD 9 · LVM thin pools (linstor_ssd, linstor_sp aka linstor-ssd-01, linstor-nvme-01) · controller HA via VRRP (VIP 10.10.20.1 em SP).

Estado:

  • ✅ Validado: LINSTOR SP SSD em pve-ippri-11/12/31, controller HA
  • ✅ Validado: LINSTOR Franca em labri-31/32/33 (controller_primary em labri-32)
  • 🚧 Declarado/parcial: LINSTOR SP NVMe (pool nvme-pool em pve-ippri-31/33/34) — pve-ippri-34 tem linstor_interface: "" (precisa correção antes de usar)
  • ❌ Desejado: cross-site replication strategy (DRBD remoto vs PBS-to-PBS)

Pendências críticas:

  • Corrigir linstor_interface vazio em pve-ippri-34 antes de qualquer outro tuning
  • place_count: 3 no SP SSD (hoje 2 — perda de 1 node = degradação) — só após correção do pve-ippri-34
  • DRBD auto-evict tuning conforme decisão recente
  • Quorum policy revisada
  • Witness/tie-breaker em terceiro site (cloud VM ou outro campus) pra eliminar split-brain de minoria

Camada 2 — Backup e recuperação (PBS)

Papel: backup VM-level com retenção longa, restore granular (bloco/arquivo). Complementa LINSTOR (que protege contra falha de hardware mas não contra deleção/corrupção lógica).

Estratégia 3-camadas:

  1. Snapshots LINSTOR — retorno rápido (minutos), retenção curta (horas/dias)
  2. PBS local — retenção média (semanas/meses), restore granular VM-level e por arquivo
  3. PBS remoto cross-site — disaster recovery, retenção longa, sync via WireGuard

Estado:

  • ❌ Desejado: PBS Franca, PBS SP, sync cross-site (nenhum implementado hoje)
  • ⚠️ Backup é prioridade MVP, não defer

Decisões pendentes:

  • Onde rodar PBS (VM dedicada por site)
  • Cadência (incremental? horário? diário?)
  • Política de retenção (4 semanas? 6 meses?)
  • Encryption-at-rest + key management

Camada 3 — Rede e roteamento (VyOS + UnespNet)

Papel: roteamento entre VLANs, NAT, firewall, link upstream institucional, VPN cross-site.

Componentes: VyOS (1 router por site) · UnespNet (link upstream institucional, com possibilidade de IP público fixo) · WireGuard SP↔Franca via UnespNet.

Estado:

  • ✅ Validado: VyOS Franca em produção
  • ✅ Validado: VyOS SP renumerado pra 192.168.10.0/23 (PR #8)
  • ✅ Validado: backup VyOS 3-camadas
  • ❌ Desejado: renumeração Franca (range a definir)
  • ❌ Desejado: WireGuard SP↔Franca configurado
  • ❌ Desejado: IP público fixo via UnespNet (uso a decidir)
  • ❌ Desejado: VRRP HA pra VyOS (single-node hoje)

Resiliência de conectividade (evolução):

  1. Hoje: 1 link UnespNet por site
  2. Próximo: IP público fixo + WireGuard cross-site
  3. Futuro: link secundário (4G/5G ou ISP comercial) com failover via VyOS
  4. Fallback admin: Cloudflare Tunnel ou similar pra acesso quando link primário cai

Camada 4 — Ingress / exposição (Traefik + DNS)

Papel: entrada HTTP(S) externa para serviços, terminação TLS, roteamento por hostname.

Componentes: Traefik (1 por site) · Cloudflare DNS · cert-manager (Let’s Encrypt DNS-01).

Estado:

  • ✅ Validado: Traefik SP em 192.168.10.6 (IP único pós-renumeração)
  • 🚧 Validado parcial: Traefik Franca em produção (status de consolidação?)
  • ⚠️ Declarado: traefik-sp tem ha: True no Pulumi config, mas o Pulumi não cria recurso HA Proxmox real — apenas VM normal com on_boot=True
  • ❌ Desejado: cert-manager + Issuers + rotação de token Cloudflare
  • ❌ Desejado: failover entre sites (DNS round-robin? Cloudflare LB?)

Camada 5 — K8s rede e segurança (Cilium)

Papel: CNI (rede pod-a-pod), service mesh (mTLS opcional), policies (NetworkPolicy++), observabilidade (Hubble).

Componentes: K3s (1 cluster por site) · Cilium 1.16+ · Hubble · NetworkPolicy default-deny.

Decisão CPPS (ADR-002): Cilium roda em VMs por padrão (caminho documentado upstream). LXC privileged é exceção apenas pra hosts Tier 3 (sem iGPU, NVIDIA disputada entre display + workload — pve-ippri-31/33). Ver Tiers de hardware pra mapeamento completo.

Estado:

  • 🚧 Validado parcial: K3s Franca em produção com flannel/default
  • ❌ Desejado: K3s SP greenfield com Cilium + Hubble (cluster K3s SP “principal”, em VMs)
  • ❌ Desejado: migração Franca pra Cilium em janela
  • ✅ Decisão: cluster GPU separado fica fora do escopo do Cilium (ADR-009)

Camada 6 — GitOps (ArgoCD)

Papel: declara estado desejado dos apps em git; ArgoCD reconcilia continuamente.

Componentes: 2 ArgoCDs independentes (1 por cluster) · repo colabhd/devops como source of truth.

Por que 2 ArgoCDs (não 1 central): se ArgoCD Franca cai ou link SP↔Franca quebra, SP continua reconciliando. Autonomia por site. Ver ADR-001.

Repo structure desejada:

apps/
├── franca/ ← ArgoCD Franca observa
├── sp/ ← ArgoCD SP observa
└── multi/ ← ApplicationSet propaga (camada 7)

Estado:

  • ✅ Validado: ArgoCD Franca em produção
  • ❌ Desejado: ArgoCD SP (não depende de Cilium — pode subir antes/em paralelo)
  • ❌ Desejado: refactor apps/ em franca//sp//multi/

Camada 7 — Multi-cluster patterns

Papel: padrões pra propagar workloads em múltiplos clusters (ApplicationSet, MultiKueue) e, opcionalmente, federação de control plane (Karmada).

Componentes:

  • Cilium ClusterMesh — service discovery cross-cluster L7 (anotação service.cilium.io/global: "true")
  • ArgoCD ApplicationSet — deploy do mesmo manifest em N clusters (mais simples, declarativo)
  • Kueue / MultiKueue — fila de jobs batch cross-cluster (GPU)
  • Karmada — control plane federado (deferido)

Decisão: começar com Cilium ClusterMesh + ApplicationSet. Cobre 80% dos casos sem operar Karmada. Ver ADR-004.

Estado:

  • ❌ Desejado: ClusterMesh + ApplicationSet (depende de Cilium nos 2 sites)
  • ❌ Desejado: Kueue pra batch GPU
  • 🚫 Deferido: Karmada (critério: 5+ clusters ou scheduling dinâmico real)

Camada 8 — Workloads

Aplicações, jobs e plataformas que rodam em cima da pilha.

8a — Aplicações (VMs e K3s)

ItemEstadoNotas
Tutor / Open edX✅ ValidadoEm produção (Franca), Kustomize via ArgoCD
OpenObserve🚧 Setup feitoValidar integração com OTel + Hubble
OnlyOffice🚧 Em andamentoWorkstations Ryzen
Apps de pesquisa diversos🚧 ParcialEm ramp-up

8b — GPU + HPC (capability sobre workloads)

GPU é capacidade, não camada — atravessa o que precisa de aceleração.

ItemEstadoNotas
gpu-sp-01 (LXC + K3s standalone + A5000)✅ ValidadoMantido em LXC como cluster K3s separado (ADR-005 revisado, ADR-009). Gerenciado via ArgoCD multi-cluster
Cluster K3s GPU Franca (hardware A5500 em labri-31/32/33)❌ Hardware presente, cluster não provisionadoMesma arquitetura quando demandar: K3s standalone em LXC, sem Cilium
HAMi ou NVIDIA Device Plugin time-slicing❌ DesejadoAvaliar Device Plugin oficial primeiro
TensorZero (model proxy)❌ DesejadoApós HAMi
vLLM / SGLang serving❌ Desejado
Volcano ou Kueue (batch)❌ Desejado
Conector Grid Unesp (SLURM API)🔮 Futuro

8c — Datalake / projetos de dados

ItemEstadoNotas
SeaweedFS + Hudi❌ DesejadoPlano em Plataforma de Dados
Trino / Spark❌ Desejado
Airflow / Dagster❌ Desejado
GraphRAG sobre corpus❌ Desejado
CAQDAS apps🚧 Parcial

Capacidades transversais

Atravessam todas as camadas. Subespecificar essas capacidades é a falha mais comum em arquiteturas de plataforma — vão pra “fase futura” e nunca chegam.

◆ Secrets management

Papel: gerenciar credenciais (tokens API, senhas DB, chaves SSH, certificados privados) sem expor em git.

Decisão pendente — opções:

  • SOPS + age: criptografia simétrica, secrets ficam em git criptografados, descriptografados em runtime
  • External Secrets Operator (ESO) + Vault: secrets ficam fora de git, K8s consome via Operator
  • Sealed Secrets: secrets criptografados em git, sealed-secrets-controller descriptografa no cluster

Recomendação MVP: SOPS + age (mais simples, sem novo serviço). ESO + Vault na fase de IDP (Backstage).

Estado: ❌ Não implementado. Prioridade MVP (não defer).

◆ Certificados (TLS)

Papel: rotação automática de certificados, terminação TLS em todas exposições.

Componentes: cert-manager (no K8s) · Let’s Encrypt via DNS-01 challenge · Cloudflare API token · ClusterIssuer / Issuer.

Estado:

  • 🚧 DNS-01 mencionado mas sem cert-manager configurado formalmente
  • ❌ Inventário de domínios e wildcards
  • ❌ Rotação de token Cloudflare

Pendências MVP:

  • cert-manager instalado nos 2 clusters
  • ClusterIssuer com DNS-01 Cloudflare
  • Token Cloudflare via secrets management
  • Inventário em /operacoes/dominios.md

◆ Identity & Access (IAM/RBAC)

Papel: SSO único pra todos os serviços, RBAC granular, audit trail.

Componentes:

  • Authentik (IdP self-hosted) — SSO OIDC/SAML/OAuth2
  • Authentik LDAP Outpost — SSH/sudo via SSSD nos servidores
  • K8s RBAC — bindings por grupo Authentik
  • Proxmox roles — sync com Authentik via PAM realm

Estado: ❌ Não implementado. Prioridade Fase 2-3.

Pendências:

  • Authentik instalado (1 instância central com replica DR?)
  • LDAP Outpost validado
  • Bindings RBAC K8s + Proxmox
  • MFA habilitado pra admins

◆ Observabilidade

Papel: logs, métricas, traces, alertas — fonte única pra diagnóstico.

Componentes:

  • OpenObserve — backend unificado (logs/metrics/traces)
  • OpenTelemetry Collector — agente em todos os nós (Proxmox + K3s)
  • Hubble (Cilium) — observabilidade L7 do K8s
  • Proxmox exporter — métricas de hardware, VMs, LINSTOR
  • Blackbox probes — synthetic checks de endpoints externos
  • Alertmanager — routing de alertas (Slack, email, webhook)

Estado:

  • 🚧 OpenObserve setup feito (validar uso real)
  • ❌ OTel collector em Proxmox/K3s
  • ❌ Hubble integrado
  • ❌ Métricas LINSTOR/DRBD/PBS
  • ❌ Blackbox probes
  • ❌ Alert routing + SLOs definidos

Pendências MVP:

  • OTel collector universal via Ansible
  • Métricas LINSTOR/PBS antes de declarar produção
  • Pelo menos 5 alertas básicos: node down, LINSTOR degraded, DRBD desync, ArgoCD out-of-sync, cert expirando

◆ CI/CD de IaC

Papel: validar mudanças em Pulumi, Ansible e ArgoCD antes de aplicar em produção.

Componentes:

  • Pulumi preview automático em PR (GitHub Actions)
  • Ansible —check + lint em PR
  • ArgoCD diff antes de sync
  • Política de aprovação (1+ revisor pra mudanças em main)
  • Rollback documentado por componente

Estado: ❌ Não implementado formalmente. Prioridade MVP.

Pendências:

  • Workflow GitHub Actions com pulumi preview em PR
  • ansible-lint e ansible-playbook --check
  • Branch protection em main
  • Runbook de rollback por componente

◆ Supply chain (registry e imagens)

Papel: controlar imagens de container que rodam no cluster — integridade, vulnerabilidades, base images padronizadas.

Componentes propostos:

  • Harbor ou registry mirror (cache de docker.io/quay.io/etc)
  • Trivy scan em CI
  • cosign assinatura de imagens internas
  • Política de base images (ex: só Debian slim, ou Distroless)

Estado: ❌ Não implementado.

Decisão pendente: registry self-hosted (Harbor) vs SaaS (GHCR/Quay) vs nada (puxar direto do upstream).

Recomendação MVP: registry mirror simples (Harbor ou registry:2 + cache) pra economizar bandwidth UnespNet e proteger contra rate-limits do Docker Hub. Trivy em CI. cosign na fase de IDP.


Decisões arquiteturais (resumo)

TópicoDecisãoAlternativa rejeitadaMotivoADR
Cluster Proxmox cross-siteNãoSim, 1 cluster únicoLatência UnespNet incompatível com pmxcfs
Storage replicadoLINSTOR + DRBDCephFootprint menor, performance melhor em poucos nodesADR-003
ArgoCD topology2 instâncias independentes1 ArgoCD centralAutonomia por site na partição de redeADR-001
CNICilium em VM (padrão); LXC privileged só Tier 3Calico, flannel sem Cilium, LinkerdCilium em VM é caminho documentado/suportado; LXC só onde hardware Tier 3 obrigaADR-002, Tiers
Multi-clusterClusterMesh + ApplicationSetKarmada (default)Karmada só com escala/scheduling realADR-004
GPU placementDiferenciado por site: SP em LXC (Tier 3 obriga); Franca em VM com Cilium (Tier 2A permite)Padronização forçada (ambos LXC ou ambos VM)Hardware atual difere entre sites — assimetria respeita hardware realADR-005, ADR-009, Tiers
Backup primárioPBS por site + cross-site syncObject storage diretoRestore granular VM-level + bloco-level
GitOps repoMonorepo colabhd/devopsMulti-repoCoesão entre infra (Pulumi/Ansible) e apps (ArgoCD)
IaC ProxmoxPulumi (Python)Terraform/OpenTofuStack já em Python; type-safety; menos verbosidade
SecretsSOPS + age (MVP) → ESO + Vault (futuro)Sealed SecretsMais simples; sem novo serviço críticoADR-006
Multi-site federação humanaWireGuard direto via VyOS (MVP) → Headscale futuroTailscale managedSelf-hosted, sem dependência SaaS
Acesso seguro humanoSSH keys + Authentik LDAP (MVP) → Octelium/Teleport futuroOctelium agoraMaturidade vs valor pro time pequeno
Defesa de bordaVyOS rules + Cloudflare proxy + fail2ban (MVP) → CrowdSec futuroCrowdSec agoraComponente novo sem caso de uso comprovado
Failover DNSCloudflare Tunnel (gratuito)DNS round-robin, Cloudflare LB pago, External DNS OperatorFailover automático com plano free; sem novo serviço self-hostedADR-008

Expansão futura (fora do MVP)

A modularidade entre camadas permite expandir sem refazer o baseline:

  • Cloud privada (AWS/Azure): novo cluster K8s na cloud, integrado via Cilium ClusterMesh + VPN
  • HPC externo (Grid Unesp, supercomputadores): integração via API/SLURM na camada 8b; jobs batch via Kueue
  • IDP (Backstage + Crossplane): quando demanda real de self-service de pesquisadores aparecer; antes disso, ArgoCD + Helm bastam
  • Observabilidade SIEM (Wazuh) ou IDS/IPS (Suricata): se compliance ou ataque sofisticado exigir
  • Mais sites institucionais Unesp: cada site novo replica o stack 0-7

Próximos passos

Implementação ordenada — ver Roadmap.