Skip to content

아키텍처

Ongrid 는 4-레이어 시스템입니다. edge 는 모니터링되는 모든 호스트에서 실행되고, manager 는 클라우드입니다. 둘은 한 개의 아웃바운드 터널 (컨트롤 플레인) 과 텔레메트리용의 별도 인증 게이트 직접 업로드 경로 (데이터 플레인) 를 통해 통신합니다.

4-레이어 모델

text
┌──────────────────────────────────────────────────────────────────┐
│ L4  Alert / notification                                         │
│      built-in rules + custom kinds → channels (Slack / TG / IM)  │
├──────────────────────────────────────────────────────────────────┤
│ L3  Intelligence (graph-kernel ReAct agent)                      │
│      coordinator → specialist sub-agents → ~30 skills            │
├──────────────────────────────────────────────────────────────────┤
│ L2  Observability triad + edge direct path                       │
│      Prometheus · Loki · Tempo  +  push_host_metrics RPC         │
├──────────────────────────────────────────────────────────────────┤
│ L1  Cluster (signal collection)                                  │
│      ongrid-edge + plugins on every host                         │
└──────────────────────────────────────────────────────────────────┘
  • L1 — Cluster. 신호가 발생하는 곳. 호스트당 하나의 ongrid-edge 와 그 서브 프로세스 플러그인 (promtail, node_exporter, process_exporter, otelcol-contrib).
  • L2 — Observability triad. Prometheus / Loki / Tempo 가 신호를 저장합니다. docker-compose 에 포함되어 있고, 설정에서 외부 매니지드 대응물 (Grafana Cloud, Mimir, VictoriaMetrics) 로 교체해도 같은 UI 가 동작합니다. 별도의 edge 직접 경로 는 저-카디널리티 폐쇄형 호스트 메트릭을 터널 위 push_host_metrics 로 운반합니다 (Prom 이 구성되기 전에도 내장 CPU / mem / disk / load 알림을 구동하는 것이 이것입니다).
  • L3 — Intelligence. 그래프 커널 기반 ReAct 에이전트. coordinator 가 질문을 분해하고, specialist 서브 에이전트로 디스패치하고, 기능을 호출하고, 답을 합성합니다.
  • L4 — 알림 & 통지. 내장 규칙 + 커스텀 kind 가 L2 / L1 스트림에 대해 평가하여 채널 (Slack, Telegram, Larksuite, DingTalk, WeCom, 원시 webhook) 로 발화합니다.

전략적 베팅은 L1 + L2 edge 직접 경로 입니다. 단일 tarball, 단일 아웃바운드 터널, Prom 왕복 없이 흐르는 호스트 메트릭. 그래서 10 분 설치가 정말로 10 분이 됩니다.

Edge → frontier → manager

text
   host (yours)                  cloud (yours, self-hosted)
 ┌──────────────────┐
 │ ongrid-edge      │
 │ ├─ plugins/      │           ┌─────────────────────────────┐
 │ │  promtail      │           │ frontier (broker, port 40012)│
 │ │  node_exporter │           │  · multiplexed geminio       │
 │ │  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
  • 호스트당 한 개의 TCP 연결. ongrid-edgefrontier:40012 로 아웃바운드 다이얼. 인바운드 없음. 포트 포워딩 없음, 점프 호스트 없음, 리버스 터널 SaaS 없음.
  • Geminio multiplex. 많은 논리 RPC 스트림이 하나의 TCP 연결에 탑니다. 양방향: 매니저가 edge 를 호출 (bash, host_probe_*, query_processes) 할 수 있고 edge 도 매니저를 호출 (push_host_metrics, report_register) 할 수 있습니다.
  • Frontier 는 브로커. 업스트림은 singchia/frontier, 릴리스 tarball 에 포함. ADR-007 이 근거 (외부 브로커가 이미 하는 것을 재 구현하지 않습니다).
  • Manager 는 Go 바이너리 하나. 약 10 개의 bounded context (edges, alerts, incidents, agent, knowledge, channels, identity, audit…) 가 모두 nginx 정문 뒤에 있습니다.

데이터 플레인 vs. 컨트롤 플레인

Edge 는 설계상 클라우드로 가는 두 개의 별개 egress 경로를 갖습니다.

text
 ┌──────── ongrid-edge ────────┐
 │                              │
 │  ┌──────── runtime ────────┐ │     ── control plane ──▶ frontier:40012
 │  │ geminio client (RPC)    │ │       (TLS-by-default if cert provided)
 │  └─────────────────────────┘ │       multiplex, bidirectional, low rate
 │                              │
 │  ┌──────── plugins ────────┐ │     ── data plane ──▶ nginx :443
 │  │ promtail   → Loki push  │ │       https POST per batch
 │  │ otelcol    → OTLP push  │ │       auth_request → manager edgeauth
 │  │ exporters  → /metrics   │ │       high rate, large payloads
 │  └─────────────────────────┘ │
 │                              │
 └──────────────────────────────┘

왜 분리하는가? ADR-014. 로그 + 트레이스는 고용량, 대용량 배치, 본질적 HTTP 입니다. 이것들을 터널에 멀티플렉싱하면 부하 하에서 처리량이 죽습니다. nginx auth_request 를 통한 직접 push 는 보안 자세 (등록된 edge 만 push 가능) 를 유지하면서도 데이터 플레인을 빠르게 유지합니다.

터널을 타는 것은 무엇이 남았나?

  • 메트릭 — 현재까지는 여전히 geminio 위의 push_host_metrics RPC. edge 에서 Prometheus 로의 직접 remote_write 는 클러스터 크기가 정당화하면 로드맵에 있습니다. 그때까지는 메트릭 볼륨이 견딜 수 있습니다.
  • 모든 RPC — query_processes, bash, query_logs_tail, host_probe_*, expand_topology, 파일 읽기, WebShell.

컨테이너 맵 (docker-compose)

sudo ./install.sh 가 매니저 호스트에서 띄우는 것:

ContainerImageHost portsRole
ongridongrid:<version>9100 (metrics)매니저. Go 바이너리; nginx 가 프록시하는 :8080 의 HTTP API.
ongrid-nginxongrid-web:<version>443, 80TLS 종단점 + SPA + 리버스 프록시. /api/*, /grafana/*, /install.sh, /edge/* 제공.
ongrid-mysqlmysql:8.03306모든 운영 상태 (edges, alerts, users, audit log, channel configs).
ongrid-frontiersingchia/frontier:1.2.540012Geminio 브로커. edge 는 40012 로 다이얼, 매니저는 compose 네트워크 위에서 40011 로 다이얼.
ongrid-prometheusprom/prometheus:v2.54.0(없음)TSDB. 매니저로부터 remote_write 수신, query_promql 기능에서 쿼리.
ongrid-lokigrafana/loki:3.4.0(없음)로그 백엔드. nginx 인증 게이트를 통해 /loki/api/v1/push 로 push.
ongrid-tempografana/tempo:2.5.0(없음)트레이스 백엔드. nginx 인증 게이트를 통해 /v1/traces 로 OTLP push.
ongrid-grafanagrafana/grafana-oss:11.1.43000대시보드. SPA 의 /grafana/ 아래 iframe 으로 임베드.
ongrid-qdrantqdrant/qdrant(없음)지식 베이스용 벡터 저장소.
ongrid-searxngsearxng/searxng(없음)web_search 기능용 셀프 호스트 메타 검색.

모든 상태 저장 서비스는 docker named volume 이 아니라 /var/lib/ongrid/ 아래 호스트 경로로 bind-mount 됩니다 — 운영자가 docker 곡예 없이 파일을 백업하고 점검할 수 있습니다. 데이터 루트는 ONGRID_DATA_DIR 로, 로그 루트는 ONGRID_LOG_DIR 로 오버라이드 가능.

Manager — bounded contexts

매니저 바이너리는 단일 Go 프로세스입니다. 내부적으로는 bounded context 들로 분할됩니다 (각 BC 는 자체 DB 스키마, 자체 HTTP 라우트, 자체 백그라운드 워커 소유). 대략:

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│   │          │   │         │
└─────────┘   └──────────┘   └─────────┘   └──────────┘   └─────────┘

BC 간 트래픽은 Go 함수 호출 (biz 레이어) 입니다 — 바이너리 내부에 RPC 가 없습니다. 아키텍처 lint (make arch-lint) 가 의존 방향 (cmd → service → biz → data, 사이클 금지) 을 강제합니다.

Edge — 플러그인 런타임

ongrid-edge 는 작은 서브 프로세스 군을 감독하는 한 개의 Go 바이너리입니다. 각 서브 프로세스는 "플러그인" 으로 옷을 갈아입은 기성 컬렉터입니다.

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

ADR-015 가 근거입니다. 모든 컬렉터는 각자의 생태계에서 best-of-breed 이고, 이것들을 Go 라이브러리로 재구현하는 것은 가망 없습니다. 그래서 edge 는 런타임 계약 (config 전달, healthcheck, 로그 캡처, 업그레이드) 만 소유하고 실제 데이터 작업은 셸 아웃합니다.

업그레이드 — stage-then-swap

ADR-024 가 전체 번들 업그레이드를 관할합니다. 흐름:

  1. 운영자가 매니저의 /opt/ongrid/edge/edge-bundle-<arch>-<ver>.tar.gz + .sha256 을 놓습니다 (릴리스 tarball 의 install.shupgrade.sh 가 둘 다 이를 수행).
  2. 운영자가 UI 에서 "upgrade all edges" 를 트리거. 매니저가 터널 위 MethodFetchPackage 를 전송.
  3. Edge 가 번들을 다운로드, sha256 검증, /var/lib/ongrid-edge/.upgrade/incoming/ 에 파일 스테이지.
  4. Edge 가 마커를 쓰고 깨끗하게 종료. systemd 가 재시작.
  5. 재시작 시 apply-pending-upgrade.shroot 로 실행되며 (+ 가 붙은 ExecStartPre 를 통해) — 모든 파일의 sha 를 검증, <dest><dest>.previous 로 백업, 새 파일을 원자적으로 mv 로 배치.
  6. 다음 재시작 전에 새 에이전트가 healthy_marker 를 쓰지 못하면 apply-pending-upgrade.sh 가 각 .previous 를 자동 롤백.

이 때문에 edge 업그레이드가 "unit 재시작" 으로 충분합니다 — 깨지기 쉬운 in-process 재배선이 없습니다.

디스크 상의 위치

manager 에서:

PathWhat
/opt/ongrid/Compose 파일, 설정, 인증서, .env, edge 아티팩트.
/opt/ongrid/.env시크릿 + 튜너블 (mode 0600).
/opt/ongrid/certs/nginx 용 tls.crt, tls.key. prod 에서는 교체.
/opt/ongrid/edge/Edge 업그레이드 번들 + arch 별 loose 바이너리.
/var/lib/ongrid/상태 저장 컨테이너용 bind-mount 루트.
/var/log/ongrid/매니저와 nginx 로그 파일.

edge 에서:

PathWhat
/usr/local/bin/ongrid-edge에이전트 바이너리.
/usr/local/lib/ongrid-edge/플러그인 바이너리 + apply-pending-upgrade.sh.
/etc/ongrid-edge/ongrid-edge.env (access/secret key), 플러그인 설정.
/var/lib/ongrid-edge/.upgrade/스테이징된 업그레이드 incoming + 마커.
/var/log/ongrid-edge/플러그인 stdout/stderr 캡처. 에이전트 로그는 journal 소유.
/etc/systemd/system/ongrid-edge.serviceSystemd unit.

더 읽을 곳

  • Concepts — 명사 용어집.
  • Server install — docker-compose 경로.
  • Edge install — curl-pipe + 검증.
  • Upgradeapply-pending-upgrade.sh, 번들 불변량, 롤백.
  • Telemetry data plane (Reference) — 정확한 엔드포인트, 인증, 한도.