Skip to content

Arquitetura ​

O Ongrid é um sistema de quatro camadas. O edge roda em todo host monitorado; o manager é a nuvem. Eles se comunicam por um tunnel outbound (o control plane) mais um caminho de upload direto auth-gated separado para telemetria (o data plane).

O modelo de 4 camadas ​

text
┌──────────────────────────────────────────────────────────────────┐
│ L4  Alerta / notificação                                         │
│      regras built-in + kinds custom → canais (Slack / TG / IM)   │
├──────────────────────────────────────────────────────────────────┤
│ L3  Inteligência (agent ReAct de graph-kernel)                   │
│      coordinator → specialist sub-agents → ~30 skills            │
├──────────────────────────────────────────────────────────────────┤
│ L2  Tríade de observabilidade + caminho direto do edge           │
│      Prometheus · Loki · Tempo  +  RPC push_host_metrics         │
├──────────────────────────────────────────────────────────────────┤
│ L1  Cluster (coleta de sinal)                                    │
│      ongrid-edge + plugins em cada host                          │
└──────────────────────────────────────────────────────────────────┘
  • L1 — Cluster. De onde os sinais vêm. Um ongrid-edge por host, mais seus plugins subprocess (promtail, node_exporter, process_exporter, otelcol-contrib).
  • L2 — Tríade de observabilidade. Prometheus / Loki / Tempo armazenam os sinais. Vêm no docker-compose; a mesma UI funciona contra equivalentes externos gerenciados (Grafana Cloud, Mimir, VictoriaMetrics) se você trocar a partir de Settings. Um caminho direto do edge separado carrega push_host_metrics pelo tunnel para métricas de host de baixa cardinalidade de conjunto fechado (é o que alimenta os alertas built-in de CPU / mem / disco / load mesmo antes do Prom ser configurado).
  • L3 — Inteligência. O agent ReAct de graph-kernel: coordinator decompõe a pergunta, despacha a sub-agents specialist, chama skills, sintetiza uma resposta.
  • L4 — Alertas & notificações. Regras built-in + kinds custom avaliam contra streams L2 / L1, disparam em canais (Slack, Telegram, Larksuite, DingTalk, WeCom, webhook cru).

A aposta estratégica é L1 + caminho direto L2: um único tarball, um tunnel outbound, métricas de host fluindo sem um round-trip do Prom. É o que faz a instalação de 10 minutos ser de fato 10 minutos.

Edge → frontier → manager ​

text
   host (seu)                    cloud (sua, self-hosted)
 ┌──────────────────┐
 │ ongrid-edge      │
 │ ├─ plugins/      │           ┌─────────────────────────────┐
 │ │  promtail      │           │ frontier (broker, port 40012)│
 │ │  node_exporter │           │  · geminio multiplex         │
 │ │  process_exp.  │── one ───▶│  · auth: access/secret key   │
 │ │  otelcol       │  outbound │  · service-end → manager     │
 │ └─ runtime       │   TCP     └──────────────┬──────────────┘
 │    geminio client│   :40012                 │ service-end (40011)
 └──────────────────┘                          ▼
                                 ┌─────────────────────────────┐
                                 │ ongrid (manager)            │
                                 │  · http API (nginx 443)     │
                                 │  · bounded contexts         │
                                 │  · agent runtime            │
                                 └──────────────┬──────────────┘
                                                │
                                                ▼
                                       Prom / Loki / Tempo /
                                       MySQL / Qdrant /
                                       SearXNG / Grafana
  • Uma conexão TCP por host. ongrid-edge disca para frontier:40012 outbound. Nada inbound. Sem port-forward, sem jumpbox, sem reverse-tunnel SaaS.
  • Multiplex Geminio. Muitos streams RPC lógicos rodam em uma conexão TCP. Bidirecional: o manager pode chamar para dentro do edge (bash, host_probe_*, query_processes) e o edge pode chamar para dentro do manager (push_host_metrics, report_register).
  • Frontier é o broker. Upstream singchia/frontier, distribuído no tarball de release. ADR-007 é a justificativa (não reimplementamos o que um broker externo já faz).
  • Manager é um único binário Go. Cerca de dez bounded contexts (edges, alerts, incidents, agent, knowledge, channels, identity, audit…), todos atrás da porta da frente do nginx.

Data plane vs control plane ​

Edges têm dois caminhos de egress distintos para a nuvem, por design:

text
 ┌──────── ongrid-edge ────────┐
 │                              │
 │  ┌──────── runtime ────────┐ │     ── control plane ──▶ frontier:40012
 │  │ geminio client (RPC)    │ │       (TLS-por-padrão se cert fornecido)
 │  └─────────────────────────┘ │       multiplex, bidirecional, low rate
 │                              │
 │  ┌──────── plugins ────────┐ │     ── data plane ──▶ nginx :443
 │  │ promtail   → Loki push  │ │       https POST por batch
 │  │ otelcol    → OTLP push  │ │       auth_request → manager edgeauth
 │  │ exporters  → /metrics   │ │       high rate, payloads grandes
 │  └─────────────────────────┘ │
 │                              │
 └──────────────────────────────┘

Por que o split? ADR-014. Logs + traces são de alto volume, batch grande, naturalmente HTTP. Multiplexá-los no tunnel mata o throughput sob carga. Push direto sobre nginx auth_request mantém a postura de segurança (só edges enrolled podem fazer push) mantendo o data plane rápido.

O que ainda anda pelo tunnel?

  • Métricas — atualmente ainda RPC push_host_metrics por geminio. remote_write direto de edge a Prometheus está no roadmap quando tamanhos de cluster justificarem. Até lá o volume de métrica é tolerável.
  • Todos os RPCs — query_processes, bash, query_logs_tail, host_probe_*, expand_topology, leituras de arquivo, WebShell.

Mapa de containers (docker-compose) ​

O que sudo ./install.sh sobe no host manager:

ContainerImagemPortas no hostPapel
ongridongrid:<version>9100 (metrics)O manager. Binário Go; API HTTP em :8080 proxiada pelo nginx.
ongrid-nginxongrid-web:<version>443, 80Terminador TLS + SPA + reverse proxy. Serve /api/*, /grafana/*, /install.sh, /edge/*.
ongrid-mysqlmysql:8.03306Todo estado operacional (edges, alerts, users, audit log, configs de canal).
ongrid-frontiersingchia/frontier:1.2.540012Broker geminio. Edges discam 40012; manager disca 40011 pela rede do compose.
ongrid-prometheusprom/prometheus:v2.54.0(nenhuma)TSDB. Recebe remote_write do manager, queries da skill query_promql.
ongrid-lokigrafana/loki:3.4.0(nenhuma)Backend de logs. Push em /loki/api/v1/push via auth-gate do nginx.
ongrid-tempografana/tempo:2.5.0(nenhuma)Backend de traces. Push OTLP em /v1/traces via auth-gate do nginx.
ongrid-grafanagrafana/grafana-oss:11.1.43000Dashboards. Embarcados como iframes sob /grafana/ no SPA.
ongrid-qdrantqdrant/qdrant(nenhuma)Vector store para a base de conhecimento.
ongrid-searxngsearxng/searxng(nenhuma)Meta-search self-hosted para a skill web_search.

Todos os serviços com estado fazem bind-mount em paths do host sob /var/lib/ongrid/, não em volumes nomeados do docker — operadores podem fazer backup e inspecionar arquivos sem ginástica de docker. Override do data root com ONGRID_DATA_DIR e o log root com ONGRID_LOG_DIR.

Manager — bounded contexts ​

O binário do manager é um único processo Go. Internamente é dividido em bounded contexts (cada um detém seu próprio schema de DB, suas próprias rotas HTTP, seus próprios background workers). Aproximadamente:

text
┌─────────┐   ┌─────────┐   ┌─────────────┐   ┌──────────────┐
│ identity│   │ edge    │   │ alert       │   │ incident     │
│ ┌─────┐ │   │ ┌─────┐ │   │ ┌─────────┐ │   │ ┌──────────┐ │
│ │users│ │   │ │edges│ │   │ │rules    │ │   │ │incidents │ │
│ │roles│ │   │ │tnls │ │   │ │events   │ │   │ │timeline  │ │
│ │JWT  │ │   │ │keys │ │   │ │evaluator│ │   │ │investig. │ │
│ └─────┘ │   │ └─────┘ │   │ └─────────┘ │   │ └──────────┘ │
└─────────┘   └─────────┘   └─────────────┘   └──────────────┘

┌─────────┐   ┌──────────┐   ┌─────────┐   ┌──────────┐   ┌─────────┐
│ agent   │   │ knowledge│   │ channels│   │ audit    │   │ skills  │
│ kernel  │   │ vault+   │   │ slack/  │   │ events / │   │ registry│
│ + sub-  │   │ embed+   │   │ telegram│   │ chains   │   │ marketp.│
│ agents  │   │ search   │   │ /lark/dt│   │          │   │         │
└─────────┘   └──────────┘   └─────────┘   └──────────┘   └─────────┘

Tráfego inter-BC é por chamadas de função Go (camada biz) — não há RPC dentro do binário. O arch lint (make arch-lint) impõe a direção de dependência (cmd → service → biz → data, sem ciclos).

Edge — plugin runtime ​

ongrid-edge é um binário Go que supervisiona uma pequena frota de subprocessos. Cada subprocesso é um collector off-the-shelf reskinado como um "plugin":

text
ongrid-edge (PID 1)
 ├─ geminio runtime  ← control plane para frontier
 ├─ plugin: logs
 │   └─ subprocess promtail
 │       config: /etc/ongrid-edge/promtail.yaml
 │       data plane: https://<manager>/loki/api/v1/push
 ├─ plugin: traces
 │   └─ subprocess otelcol-contrib
 │       config: /etc/ongrid-edge/otelcol.yaml
 │       data plane: https://<manager>/v1/traces
 ├─ plugin: hostmetrics
 │   └─ subprocess node_exporter
 │       /metrics raspado pelo Prometheus dentro do manager
 └─ plugin: procmetrics
     └─ subprocess process_exporter

ADR-015 é a justificativa: cada collector é best-of-breed em seu próprio ecossistema; reinventá-los como libs Go é desesperançoso. Então o edge detém o contrato de runtime (entrega de config, healthcheck, captura de log, upgrade) e shell out para o trabalho de dado real.

Upgrades — stage-then-swap ​

ADR-024 governa upgrades de bundle inteiro. O fluxo:

  1. Operador joga edge-bundle-<arch>-<ver>.tar.gz + .sha256 em /opt/ongrid/edge/ no manager (o install.sh e o upgrade.sh do tarball de release fazem isso).
  2. Operador dispara "upgrade all edges" da UI. O manager envia MethodFetchPackage pelo tunnel.
  3. Edge baixa o bundle, verifica o sha256, faz stage dos arquivos em /var/lib/ongrid-edge/.upgrade/incoming/.
  4. Edge escreve um marker, sai limpo. systemd reinicia.
  5. Em restart, apply-pending-upgrade.sh roda como root (via ExecStartPre com +) — verifica o sha de cada arquivo, faz backup de <dest> em <dest>.previous, faz mv atômico do arquivo novo para o lugar.
  6. Se o agent novo não escreve um healthy_marker antes do próximo restart, apply-pending-upgrade.sh rolla back cada .previous automaticamente.

É por isso que um upgrade de edge é só "restart a unit" — sem rewire frágil in-process.

Onde as coisas vivem em disco ​

No manager:

PathO que
/opt/ongrid/Compose file, configs, certs, .env, artefatos de edge.
/opt/ongrid/.envSecrets + tunables (mode 0600).
/opt/ongrid/certs/tls.crt, tls.key para nginx. Substitua para prod.
/opt/ongrid/edge/Bundles de upgrade de edge + binários soltos por arch.
/var/lib/ongrid/Root de bind-mount para containers com estado.
/var/log/ongrid/Arquivos de log do manager e nginx.

No edge:

PathO que
/usr/local/bin/ongrid-edgeO binário do agent.
/usr/local/lib/ongrid-edge/Binários de plugin + apply-pending-upgrade.sh.
/etc/ongrid-edge/ongrid-edge.env (access/secret keys), configs de plugin.
/var/lib/ongrid-edge/.upgrade/Incoming de upgrade staged + markers.
/var/log/ongrid-edge/Captura de stdout/stderr de plugin. Journal detém logs do agent.
/etc/systemd/system/ongrid-edge.serviceUnit do Systemd.

Onde ler mais ​