아키텍처
Ongrid 는 4-레이어 시스템입니다. edge 는 모니터링되는 모든 호스트에서 실행되고, manager 는 클라우드입니다. 둘은 한 개의 아웃바운드 터널 (컨트롤 플레인) 과 텔레메트리용의 별도 인증 게이트 직접 업로드 경로 (데이터 플레인) 를 통해 통신합니다.
4-레이어 모델
┌──────────────────────────────────────────────────────────────────┐
│ 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
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-edge가frontier: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 경로를 갖습니다.
┌──────── 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_metricsRPC. edge 에서 Prometheus 로의 직접remote_write는 클러스터 크기가 정당화하면 로드맵에 있습니다. 그때까지는 메트릭 볼륨이 견딜 수 있습니다. - 모든 RPC —
query_processes,bash,query_logs_tail,host_probe_*,expand_topology, 파일 읽기, WebShell.
컨테이너 맵 (docker-compose)
sudo ./install.sh 가 매니저 호스트에서 띄우는 것:
| Container | Image | Host ports | Role |
|---|---|---|---|
ongrid | ongrid:<version> | 9100 (metrics) | 매니저. Go 바이너리; nginx 가 프록시하는 :8080 의 HTTP API. |
ongrid-nginx | ongrid-web:<version> | 443, 80 | TLS 종단점 + SPA + 리버스 프록시. /api/*, /grafana/*, /install.sh, /edge/* 제공. |
ongrid-mysql | mysql:8.0 | 3306 | 모든 운영 상태 (edges, alerts, users, audit log, channel configs). |
ongrid-frontier | singchia/frontier:1.2.5 | 40012 | Geminio 브로커. edge 는 40012 로 다이얼, 매니저는 compose 네트워크 위에서 40011 로 다이얼. |
ongrid-prometheus | prom/prometheus:v2.54.0 | (없음) | TSDB. 매니저로부터 remote_write 수신, query_promql 기능에서 쿼리. |
ongrid-loki | grafana/loki:3.4.0 | (없음) | 로그 백엔드. nginx 인증 게이트를 통해 /loki/api/v1/push 로 push. |
ongrid-tempo | grafana/tempo:2.5.0 | (없음) | 트레이스 백엔드. nginx 인증 게이트를 통해 /v1/traces 로 OTLP push. |
ongrid-grafana | grafana/grafana-oss:11.1.4 | 3000 | 대시보드. SPA 의 /grafana/ 아래 iframe 으로 임베드. |
ongrid-qdrant | qdrant/qdrant | (없음) | 지식 베이스용 벡터 저장소. |
ongrid-searxng | searxng/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 라우트, 자체 백그라운드 워커 소유). 대략:
┌─────────┐ ┌─────────┐ ┌─────────────┐ ┌──────────────┐
│ 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 바이너리입니다. 각 서브 프로세스는 "플러그인" 으로 옷을 갈아입은 기성 컬렉터입니다.
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 subprocessADR-015 가 근거입니다. 모든 컬렉터는 각자의 생태계에서 best-of-breed 이고, 이것들을 Go 라이브러리로 재구현하는 것은 가망 없습니다. 그래서 edge 는 런타임 계약 (config 전달, healthcheck, 로그 캡처, 업그레이드) 만 소유하고 실제 데이터 작업은 셸 아웃합니다.
업그레이드 — stage-then-swap
ADR-024 가 전체 번들 업그레이드를 관할합니다. 흐름:
- 운영자가 매니저의
/opt/ongrid/edge/에edge-bundle-<arch>-<ver>.tar.gz+.sha256을 놓습니다 (릴리스 tarball 의install.sh와upgrade.sh가 둘 다 이를 수행). - 운영자가 UI 에서 "upgrade all edges" 를 트리거. 매니저가 터널 위
MethodFetchPackage를 전송. - Edge 가 번들을 다운로드, sha256 검증,
/var/lib/ongrid-edge/.upgrade/incoming/에 파일 스테이지. - Edge 가 마커를 쓰고 깨끗하게 종료. systemd 가 재시작.
- 재시작 시
apply-pending-upgrade.sh가 root 로 실행되며 (+가 붙은 ExecStartPre 를 통해) — 모든 파일의 sha 를 검증,<dest>를<dest>.previous로 백업, 새 파일을 원자적으로mv로 배치. - 다음 재시작 전에 새 에이전트가
healthy_marker를 쓰지 못하면apply-pending-upgrade.sh가 각.previous를 자동 롤백.
이 때문에 edge 업그레이드가 "unit 재시작" 으로 충분합니다 — 깨지기 쉬운 in-process 재배선이 없습니다.
디스크 상의 위치
manager 에서:
| Path | What |
|---|---|
/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 에서:
| Path | What |
|---|---|
/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.service | Systemd unit. |
더 읽을 곳
- Concepts — 명사 용어집.
- Server install — docker-compose 경로.
- Edge install — curl-pipe + 검증.
- Upgrade —
apply-pending-upgrade.sh, 번들 불변량, 롤백. - Telemetry data plane (Reference) — 정확한 엔드포인트, 인증, 한도.