Files
EvoBGP/.cursor/plans/evobgp_архитектура_0e73ef02.plan.md
T
Denozordec acc0608432
CI / changes (push) Successful in 4s
CI / openapi (push) Successful in 24s
CI / go (push) Successful in 22s
CI / bird2 (push) Successful in 13s
CI / docker-images (deploy/docker/bird2/Dockerfile, evobgp-bird2) (push) Successful in 38s
CI / docker-images (deploy/docker/evobgp-agent/Dockerfile, evobgp-agent) (push) Successful in 1m8s
CI / docker-images (deploy/docker/evobgp-web/Dockerfile, evobgp-web) (push) Successful in 49s
CI / docker-images (evobgp-all, 1, deploy/docker/gobinary/Dockerfile, evobgp-all) (push) Successful in 1m30s
CI / docker-images (evobgp-api, 1, deploy/docker/gobinary/Dockerfile, evobgp-api) (push) Successful in 1m31s
CI / docker-images (evobgp-ingest, 0, deploy/docker/gobinary/Dockerfile, evobgp-ingest) (push) Has been cancelled
CI / docker-images (evobgp-deploy, 0, deploy/docker/gobinary/Dockerfile, evobgp-deploy) (push) Has been cancelled
CI / docker-images (evobgp-node, 0, deploy/docker/gobinary/Dockerfile, evobgp-node) (push) Has been cancelled
CI / docker-images (evobgp-render, 0, deploy/docker/gobinary/Dockerfile, evobgp-render) (push) Has been cancelled
CI / docker-images (evobgp-scheduler, 0, deploy/docker/gobinary/Dockerfile, evobgp-scheduler) (push) Has been cancelled
docs: update architecture and API documentation to clarify job processing, in-memory registry usage, and future broker integration plans. Enhance OpenAPI specifications for enrollment responses and refine quickstart instructions for Docker setups.
2026-04-05 18:36:32 +07:00

75 KiB
Raw Blame History

name, overview, todos, isProject
name overview todos isProject
EvoBGP архитектура Оба профиля по умолчанию на PostgreSQL (один движок, одни миграции). reference — микросервисы + PG + брокер; microVPS — evobgp-all + контейнер PG (жёсткий тюнинг). SQLite — опция только для одного контейнера без PG. REST API проработан в §7 плана (пути /v1, jobs, бандлы нод); OpenAPI — канон при появлении схемы.
id content status
schema-db Схема БД: PostgreSQL (основной); опционально SQLite (microVPS single-container); модули, ревизии, jobs completed
id content status
bird-generator Формат bird.conf, include-фрагменты, фильтры, birdc configure completed
id content status
rest-jobs REST (refresh, apply, preview, rollback, bundle API) и async jobs completed
id content status
node-agent evobgp-agent + bird2 в Docker на мастере; evobgp-node + тот же паттерн на реплике (отдельная ВМ) completed
id content status
observability Метрики, алерты префиксов и BGP-сессий completed
id content status
docker-ms Compose profiles reference + microVPS; сервисы bird2 + evobgp-agent; сеть BGP; лимиты; логи; prune completed
id content status
go-modules Monorepo по §1 (дерево репозитория); internal/*, cmd/evobgp-all и cmd/* для reference completed
id content status
replica-bundle Подписанный бандл ревизии, API, evobgp-node completed
id content status
risk-hardening Двухфазный deploy, LKG, pin BIRD, политика миграций, обязательная подпись бандла на ноде completed
id content status
test-bird-matrix Матрица сценариев BIRD + golden-тесты birdfmt + bird -p в CI completed
id content status
ci-gitea .gitea/workflows/ci.yaml, документация для act runner completed
id content status
web-ui Web UI (Svelte + shadcn-svelte) в отдельном контейнере: списки, расписание, мониторинг completed
false

EvoBGP — архитектурный план

Control-plane на Go, анонс префиксов через BIRD, политика и история в SQL-БД, управление по REST. Репозиторий кода пока пустой — документ задаёт целевую архитектуру.


Содержание

  1. Структура репозитория (файлы и пакеты)
  2. Два эталонных профиля
  3. Логическая модель и термины
  4. Сервисы и контейнеры
  1. База данных, ETL, ER-схема
  2. Модули префиксов и FQDN
  3. REST API
  1. Генерация BIRD и ревизии
  2. Эксплуатация и масштаб пиров
  3. Реплика evobgp-node
  4. Выбор СУБД
  5. Профиль microVPS — детализация
  6. Снижение рисков (меры и процессы)
  7. Тестирование BIRD2 и матрица сценариев
  8. CI/CD (Gitea Actions)
  9. Риски и этапы внедрения
  10. Web UI (Svelte, shadcn-svelte)

1. Структура репозитория (файлы и пакеты)

Monorepo на Go: общая логика в internal/*, отдельные бинарники в cmd/*. Цель — одна кодовая база для профилей reference (несколько процессов) и microVPS (evobgp-all).

Принципы:

  • **cmd/** — только точки входа: флаги, переменные окружения, сборка зависимостей (DI), запуск; без доменной логики.
  • **internal/** — весь прикладной код; внешние модули Go не могут импортировать эти пакеты (правило компилятора).
  • Слои: domain (модели и инварианты без I/O) → repository и адаптеры к БД/внешним API → пакеты воркеров (оркестрация) → транспорт (httpapi, jobs, клиент к агенту).
  • Один код — две упаковки: микросервисы и evobgp-all используют одни и те же пакеты internal/*; отличается только набор процессов в cmd/*.
  • **docs/, **scripts/ — как сейчас в репозитории (контракт API: docs/openapi.yaml, вспомогательные скрипты).
  • **deploy/** — Dockerfiles, docker-compose с профилями reference / microVPS, при необходимости entrypoint’ы для bird2 / evobgp-agent; инфраструктура не смешивается с internal/.

Целевое дерево каталогов (ориентир; имена подпакетов можно уточнить при первой итерации кода, роли каталогов зафиксированы):

EvoBGP/
├── cmd/
│   ├── evobgp-api/          # REST + постановка jobs (reference)
│   ├── evobgp-scheduler/
│   ├── evobgp-ingest/
│   ├── evobgp-render/
│   ├── evobgp-deploy/
│   ├── evobgp-all/          # microVPS: те же пакеты, один процесс / несколько goroutine
│   ├── evobgp-agent/        # рядом с bird2: запись конфигов, birdc
│   └── evobgp-node/         # pull бандла, проверка подписи, apply
├── internal/
│   ├── config/              # загрузка конфигурации (ENV, файлы)
│   ├── platform/            # логирование, метрики, трассировка, health
│   ├── db/                  # пул, транзакции; embed миграций или вызов migrate
│   ├── repository/          # SQL по сущностям (tenant, module, peer, revision, jobs, …)
│   ├── domain/              # типы и правила без I/O (префиксы, community, ревизии)
│   ├── httpapi/             # роуты OpenAPI, middleware, валидация, маппинг в сервисы
│   ├── jobs/                # задачи: сейчас in-memory Registry в процессе API; PG job_audit / брокер — целевое расширение (см. примечание ниже §2)
│   ├── scheduler/           # триггеры по расписанию модулей
│   ├── ingest/              # CDN, DoH, нормализация, запись в БД
│   ├── render/              # материализация префиксов, ревизия, текст артефактов BIRD
│   ├── birdfmt/             # шаблоны и сборка include-фрагментов (альтернатива имени: bird/)
│   ├── deploy/              # доставка на volume, взаимодействие с evobgp-agent / бандлы
│   ├── bundle/              # упаковка и подпись бандла для evobgp-node
│   └── signing/             # ключи, проверка подписи на ноде
├── migrations/              # SQL миграции PostgreSQL (единый набор для обоих профилей)
├── deploy/
│   ├── compose/             # docker-compose с профилями
│   └── docker/              # Dockerfile на бинарь + общие слои
├── docs/
├── scripts/
├── go.mod
├── go.sum
└── README.md

Соответствие сервисам плана:

Сервис (план) Код
evobgp-api cmd/evobgp-api, internal/httpapi, internal/jobs, internal/repository
evobgp-scheduler cmd/evobgp-scheduler, internal/scheduler, internal/jobs, internal/repository
evobgp-ingest cmd/evobgp-ingest, internal/ingest, internal/repository
evobgp-render cmd/evobgp-render, internal/render, internal/birdfmt, internal/repository
evobgp-deploy cmd/evobgp-deploy, internal/deploy, internal/bundle, internal/repository
evobgp-all cmd/evobgp-all — поднимает HTTP и воркеры, импортируя те же internal/*
evobgp-agent cmd/evobgp-agent, internal/deploy (запись на volume, birdc)
evobgp-node cmd/evobgp-node, internal/bundle, internal/signing, internal/birdfmt / internal/deploy

Поток пакетов (упрощённо):

flowchart TB
  subgraph entry [cmd]
    API[evobgp-api]
    W[scheduler ingest render deploy]
  end
  subgraph internal [internal]
    HTTP[httpapi]
    J[jobs]
    R[repository]
    DBpkg[db]
    REN[render]
    BF[birdfmt]
    DEP[deploy]
  end
  PG[(PostgreSQL)]
  AG[evobgp-agent]
  API --> HTTP
  HTTP --> J
  HTTP --> R
  W --> J
  W --> R
  R --> DBpkg
  DBpkg --> PG
  REN --> BF
  REN --> R
  DEP --> R
  DEP --> AG

2. Два эталонных профиля развёртывания

Один и тот же код в дереве internal/ (все подпакеты), две упаковки в Docker Compose.

Критерий reference (эталон) microVPS
Назначение Production control-plane без жёсткого лимита RAM; горизонтальное масштабирование воркеров Один хост: маленькая VPS / вложенная ВМ
CPU 2+ vCPU (рекомендуется) 1 vCPU
RAM 4+ ГиБ (ориентир) ~1 ГиБ
Диск под Docker + данные по объёму проекта 7–10 ГиБ (бюджет; не весь диск ОС)
ОС Linux (в т.ч. Ubuntu 22.04/24.04) Ubuntu 24.04 LTS (референс)
Контейнеры Go 5 образов: api, scheduler, ingest, render, deploy 1 образ: evobgp-all
БД PostgreSQL (отдельный сервис или managed) PostgreSQL в контейнере (жёсткий тюнинг под 1 ГиБ)
Очередь NATS JetStream или Redis Streams (на выбор) Нет брокера — job_audit в PostgreSQL + SKIP LOCKED / малый пул коннектов
Reverse proxy Traefik / Nginx (опционально) Нет — прямой порт API
Object storage MinIO / S3 опционально для артефактов Только локальный volume или небольшие BLOB в БД
BIRD BIRD 2 в Docker (privileged / нужные capabilities) + контейнер **evobgp-agent** с общим volume То же: bird2 + evobgp-agent + postgres + evobgp-all
Контейнеры (итого) 5×Go + postgres + брокер + bird2 + evobgp-agent (+ опц. proxy) 4: evobgp-all + postgres + bird2 + evobgp-agent (+ опц. нода вне VPS)
flowchart LR
  subgraph ref [reference]
    R1[5x Go]
    R2[(PostgreSQL)]
    R3[(Broker)]
    R4[bird2]
    R5[evobgp-agent]
    R1 --> R2
    R1 --> R3
    R1 --> R5
    R5 --> R4
  end
  subgraph micro [microVPS]
    M1[evobgp-all]
    M2[(PostgreSQL)]
    M3[bird2]
    M4[evobgp-agent]
    M1 --> M2
    M1 --> M4
    M4 --> M3
  end

Правило: логика домена одинакова; один движок БД — PostgreSQL (одинаковые миграции и SQL). Отличаются число процессов Go, наличие брокера и настройки PG.

Примечание (текущий код vs целевая очередь): исполнение async jobs идёт через in-memory jobs.Registry в процессе evobgp-api / evobgp-all; таблица job_audit в миграциях заложена под будущую персистенцию и идемпотентность между процессами. В reference Compose отдельный evobgp-scheduler не читает эту очередь, а вызывает POST .../modules/{id}/refresh по HTTP. NATS в compose — для будущей интеграции; см. docs/architecture.md.

Опция microVPS_sqlite: один контейнер evobgp-all без PG — только если критичен абсолютный минимум контейнеров; иначе не рекомендуется как основной путь.


3. Логическая модель (общая для обоих профилей)

  • BGP-сервер (ваш) — процесс BIRD, который анонсирует префиксы и держит сессии.
  • Клиенты — внешние роутеры (BGP-пиры), подключающиеся к вам и получающие маршруты. Это не контейнеры EvoBGP.
  • Мастер — control-plane + BIRD 2 в контейнере и контейнер **evobgp-agent** (общий volume: сгенерированные bird.d, сокет/канал для birdc).
  • EvoBGP-нода (опционально) — отдельная площадка: только pull подписанного бандла с мастера + BIRD 2 в Docker (тот же паттерн agent + bird2); своей полной БД и ingest нет.

Быстрый путь данных: БД → ingest (CDN / DoH / AS; IP_RANGES только читаются при render из БД) → render (префиксы + community + ревизия) → deploy → файлы BIRD → birdc configure → клиентские сессии.


4. Сервисы (сравнение профилей)

Сервис Назначение reference microVPS
evobgp-api REST, CRUD, задачи, /jobs отдельный контейнер goroutine в evobgp-all
evobgp-scheduler Интервалы модулей/CDN → события отдельный контейнер goroutine в evobgp-all
evobgp-ingest CDN, DoH, материализация в БД отдельный контейнер goroutine в evobgp-all
evobgp-render Итоговые префиксы, ревизия, текст BIRD отдельный контейнер goroutine в evobgp-all
evobgp-deploy Доставка на мастерский BIRD, публикация бандла отдельный контейнер goroutine в evobgp-all
evobgp-agent Контейнер рядом с bird2: запись конфигов, birdc configure то же (общий volume с bird2) то же
evobgp-node Реплика: pull бандла, локальный BIRD отдельный хост не на microVPS

Инфраструктура reference: PostgreSQL, NATS или Redis, опционально Traefik, MinIO, bird2 + evobgp-agent в Docker.

Зависимости (профиль reference)

flowchart TB
  subgraph cp [Control plane]
    API[evobgp-api]
    SCH[scheduler]
    ING[ingest]
    REN[render]
    DEP[deploy]
  end
  DB[(PostgreSQL)]
  MQ[(Broker)]
  API --> DB
  API --> MQ
  SCH --> DB
  SCH --> MQ
  ING --> DB
  ING --> MQ
  REN --> DB
  REN --> MQ
  DEP --> DB
  DEP --> MQ
  DEP --> AG[evobgp-agent]
  AG --> BIRD2[bird2]

4.1. Топология Docker Compose

Целевая упаковка: все компоненты мастера в Compose, включая BIRD 2 (bird2). Пара bird2 + evobgp-agent делает общий именованный volume (или bind-mount) для каталога конфигурации и точки управления birdc (см. образ/entrypoint в репозитории).

Сеть для BGP: на практике для входящих TCP 179 часто нужны network_mode: host (Linux), macvlan/ipvlan или публикация портов / отдельный L3-интерфейс — выбор фиксируется в профиле Compose и документации оператора; контейнер bird2 получает privileged и набор capabilities (NET_ADMIN, и при необходимости NET_RAW), плюс sysctls под forwarding, если не на host-сети.

flowchart TB
  subgraph refDocker [profile_reference]
    subgraph goRef [Сервисы Go]
      API1[evobgp-api]
      SCH1[scheduler]
      ING1[ingest]
      REN1[render]
      DEP1[deploy]
    end
    PG1[(postgres)]
    BR1[broker]
    subgraph bgpRef [Стек BGP Docker]
      AG1[evobgp-agent]
      B21[bird2]
    end
    VOL1[vol_bird_config]
    API1 --> PG1
    API1 --> BR1
    SCH1 --> PG1
    SCH1 --> BR1
    ING1 --> PG1
    ING1 --> BR1
    REN1 --> PG1
    REN1 --> BR1
    DEP1 --> PG1
    DEP1 --> BR1
    DEP1 --> AG1
    AG1 --> VOL1
    B21 --> VOL1
    AG1 -->|birdc| B21
  end
  subgraph microDocker [profile_microVPS]
    ALL[evobgp-all]
    PG2[(postgres)]
    subgraph bgpMicro [Стек BGP Docker]
      AG2[evobgp-agent]
      B22[bird2]
    end
    VOL2[vol_bird_config]
    ALL --> PG2
    ALL --> AG2
    AG2 --> VOL2
    B22 --> VOL2
    AG2 -->|birdc| B22
  end

На реплике (evobgp-node) — тот же паттерн bird2 + evobgp-agent в Docker на отдельном хосте; pull бандла и birdc configure без полной БД (см. §10).


5. База данных, ETL, ER-схема

5.1. Группы сущностей

Область Назначение
module Тип AS_PREFIXES / CDN_CIDRS / DOMAINS / IP_RANGES, расписание, DoH, приоритет
module_cdn_source URL + source_kind (формат тела списка); примеры наброска: text_cidr_lines, json_prefix_list, custom; ETag; свой refresh_interval опционально
doh_profile URL DoH, таймауты, секреты по ссылке
module_domain_entry / module_as_entry / module_ip_range_entry FQDN; или ASN/префикс; или только CIDR/диапазон + community_id (IP_RANGES)
bgp_community Справочник community для BIRD
bgp_peer Клиентский пир; speaker_id NULL = все спикеры в бандле
bgp_speaker master / replica, last_applied_revision_id
config_revision / revision_materialized_prefix История, diff, откат
job_audit Асинхронные задачи; в reference дополняет брокер

5.2. ETL

flowchart LR
  subgraph ex [Extract]
    CDN[CDN fetch]
    DOH[DoH]
    AS[AS из БД]
    IPR[IP ranges из БД]
  end
  subgraph tr [Transform]
    NORM[Нормализация CIDR]
    DEDUP[Дедуп]
    COMM[Community]
  end
  subgraph ld [Load]
    DB[(SQL БД)]
    REV[revision]
    ART[артефакты BIRD]
  end
  CDN --> NORM
  DOH --> NORM
  AS --> NORM
  IPR --> NORM
  NORM --> DEDUP --> COMM
  COMM --> DB
  COMM --> REV
  REV --> ART

5.3. ER (упрощённо)

erDiagram
  tenant ||--o{ module : owns
  tenant ||--o{ bgp_community : owns
  tenant ||--o{ bgp_peer : owns
  tenant ||--o{ bgp_speaker : owns
  doh_profile ||--o{ module : uses
  module ||--o{ module_cdn_source : contains
  module ||--o{ module_domain_entry : contains
  module ||--o{ module_as_entry : contains
  module ||--o{ module_ip_range_entry : contains
  bgp_community ||--o{ module_domain_entry : tags
  bgp_community ||--o{ module_as_entry : tags
  bgp_community ||--o{ module_ip_range_entry : tags
  bgp_community ||--o{ module_cdn_source : tags
  bgp_speaker ||--o{ bgp_peer : scope
  module ||--o{ config_revision : produces
  config_revision ||--o{ revision_materialized_prefix : snapshot
  module ||--o{ job_audit : tasks

5.4. Пояснения к таблицам

Таблица Назначение Ключевые поля Кто использует
tenant Multi-tenant id, name, slug API, все сервисы
module Блок политики type, enabled, priority, doh_profile_id, refresh_interval_sec, cron_expr, default_community_id API, scheduler, ingest, render
doh_profile DoH url, таймауты, ссылка на секрет DOMAINS, ingest
module_cdn_source Строка CDN source_kind (набросок: text_cidr_lines, json_prefix_list, custom), url, etag, refresh_interval_sec, community_id ingest, render
module_domain_entry FQDN fqdn, community_id, метаданные резолва ingest, render
module_as_entry AS/префикс asn, prefix, community_id API, render
module_ip_range_entry Статический CIDR prefix (CIDR), community_id; без ASN и без внешнего URL — модуль типа IP_RANGES API, render
bgp_community Справочник kind, значения, уникальность в tenant API, render
bgp_peer Клиентский пир neighbor, ASN, политики, bgp_speaker_id (NULL = все спикеры) API, render, бандл
bgp_speaker Экземпляр BIRD role master/replica, endpoint, last_applied_revision_id deploy, нода
config_revision История hash, артефакт, parent_revision_id render, deploy, rollback
revision_materialized_prefix Снимок префиксов revision_id, prefix, community_id, source preview, diff, откат
job_audit Задачи kind, status, idempotency_key API, воркеры

Дополнительно: **global_settings** (KV); **module_cdn_fetch_log** (опционально, TTL).

В reference очередь: брокер + job_audit; в microVPS — только БД и идемпотентность в job_audit.


6. Модули префиксов (AS / CDN / домены)

Продуктовая трактовка

В терминах продукта модуль — это один из четырёх видов источника префиксов: AS (AS_PREFIXES), CDN (CDN_CIDRS), DOMAINS (DOMAINS), IP-диапазоны (IP_RANGES). Наполнение задаётся либо записями в таблице (ASN или префикс + community_id; FQDN + community_id для доменов; CIDR + community_id для IP_RANGES без ASN и без внешнего URL), либо для CDN — источником по URL с полем source_kind, определяющим формат скачанного списка и парсер. Строка сущности **module** в БД — это экземпляр модуля выбранного типа (расписание, приоритет, DoH для доменов и т.д.); **module_id в API** — идентификатор экземпляра, а не «имя типа». При минимальном развёртывании (один bird2, мало пиров) допустим один экземпляр на каждый нужный тип или узкий набор экземпляров — это не противоречит модели.

Тип Ввод Поведение
AS ASN / префиксы Таблица + опционально внешний PrefixProvider
CDN URL или список Fetch, ETag, интервал модуля или строки
Домены FQDN В BIRD попадают только IP-префиксы после DoH-резолва
IP-диапазоны CIDR (IPv4/IPv6) + community Только таблица module_ip_range_entry; без IRR/ASN-семантики и без fetch

FQDN: воркер резолвит через DoH-профиль модуля → /32 / /128 (или политика) → материализация в БД → генерация static include для BIRD.


7. REST API

Статус: черновик для согласования и реализации; каноничная машиночитаемая форма — docs/openapi.yaml (по мере заполнения). Ниже — единая проработка путей и семантики (консолидация с docs/evobgp-api-sketches.md). Базовый префикс: **/v1**. Термины: §3, §5, §6.

7.1. Общие соглашения

Тема Решение (набросок)
Аутентификация Заголовок Authorization: Bearer <api_key> или mTLS на edge; ключи привязаны к tenant и роли.
Multi-tenant Все сущности в скоупе tenant: либо из ключа, либо явный префикс X-Tenant-Id (только для супер-ролей).
Идентификаторы UUID v7 или ULID в URL; в JSON — строки.
Время ISO 8601 UTC (2026-04-03T12:00:00Z).
Ошибки Тело application/problem+json (RFC 9457): type, title, status, detail, instance, опционально errors[] по полям.
Идемпотентность Для мутаций, создающих задачи или побочные эффекты: заголовок Idempotency-Key (опционально обязателен для POST apply/refresh).
Пагинация ?cursor=<opaque>&limit=50 (cursor-based); ответ: items, next_cursor, has_more.
Асинхронные операции 202 Accepted, заголовок Location: /v1/jobs/{job_id}; тело { "job_id", "status": "queued" }.
Версионирование Несовместимые изменения — новый префикс /v2.

7.2. Системные и служебные

Метод Путь Назначение
GET /v1/health Liveness (процесс жив).
GET /v1/ready Readiness (БД, брокер при reference, и т.д.).
GET /v1/version Версия сборки API и control-plane (git_sha, build_time).

7.3. Модули префиксов (module)

Связь с продуктом. В продуктовой формулировке ASN / CDN / DOMAINS / IP-диапазоны — это четыре вида модулей. Поле **type** в POST /v1/modules выбирает вид: AS_PREFIXES, CDN_CIDRS, DOMAINS или **IP_RANGES. Дочерние ресурсы: **as-entries, **cdn-sources**, **domain-entries**; **ip-range-entries** — статические CIDR + community_id (без ASN и без URL). **module_id** в пути — идентификатор конкретного экземпляра модуля, а не имя типа (согласовано с §6).

Метод Путь Описание
GET /v1/modules Список модулей tenant (фильтры: ?type=, ?enabled=).
POST /v1/modules Создать модуль.
GET /v1/modules/{module_id} Детали модуля.
PATCH /v1/modules/{module_id} Частичное обновление (расписание, DoH, приоритет, enabled).
DELETE /v1/modules/{module_id} Мягкое удаление или enabled=false — зафиксировать в реализации.

CDN-источники модуля

Метод Путь Описание
GET /v1/modules/{module_id}/cdn-sources Список строк CDN.
POST /v1/modules/{module_id}/cdn-sources Добавить источник (URL + source_kind + опционально community_id).
PATCH /v1/modules/{module_id}/cdn-sources/{source_id} URL, source_kind, community_id, свой refresh_interval_sec.
DELETE /v1/modules/{module_id}/cdn-sources/{source_id} Удалить.

Записи AS / домены

Метод Путь Описание
GET /v1/modules/{module_id}/as-entries Список ASN/префиксов.
POST /v1/modules/{module_id}/as-entries Добавить.
PATCH /v1/modules/{module_id}/as-entries/{entry_id} Обновить.
DELETE /v1/modules/{module_id}/as-entries/{entry_id} Удалить.
GET /v1/modules/{module_id}/domain-entries FQDN + community.
POST /v1/modules/{module_id}/domain-entries Добавить.
PATCH /v1/modules/{module_id}/domain-entries/{entry_id} Обновить.
DELETE /v1/modules/{module_id}/domain-entries/{entry_id} Удалить.

Записи IP-диапазонов (только для type: IP_RANGES)

Метод Путь Описание
GET /v1/modules/{module_id}/ip-range-entries Список CIDR + community_id.
POST /v1/modules/{module_id}/ip-range-entries Добавить (prefix, community_id).
PATCH /v1/modules/{module_id}/ip-range-entries/{entry_id} Обновить.
DELETE /v1/modules/{module_id}/ip-range-entries/{entry_id} Удалить.

Refresh (ingest)

Метод Путь Описание
POST /v1/modules/{module_id}/refresh Запуск ingest для модуля (CDN / DoH / AS по типу). Для **IP_RANGES** обычно не требуется (данные только в БД); возможен **204** / no-op или **400**, если тип не поддерживает refresh — зафиксировать в реализации.

Пример тела создания модуля (набросок)

{
  "type": "CDN_CIDRS",
  "name": "edge-v4",
  "enabled": true,
  "priority": 10,
  "doh_profile_id": null,
  "refresh_interval_sec": 3600,
  "cron_expr": null,
  "default_community_id": "550e8400-e29b-41d4-a716-446655440000"
}

Пример модуля **IP_RANGES**: type: "IP_RANGES", doh_profile_id: null, далее строки через ip-range-entries с полями prefix (например 203.0.113.0/24) и community_id.

7.4. DoH-профили (doh_profile)

Метод Путь Описание
GET /v1/doh-profiles Список.
POST /v1/doh-profiles Создать (URL, таймауты; секрет — ссылка на vault id или отдельный POST .../secret).
GET /v1/doh-profiles/{id} Детали (без раскрытия секрета).
PATCH /v1/doh-profiles/{id} Обновить.
DELETE /v1/doh-profiles/{id} Удалить, если не используется модулями.

7.5. BGP community (bgp_community)

Метод Путь Описание
GET /v1/communities Список справочника.
POST /v1/communities Создать.
GET /v1/communities/{id} Детали.
PATCH /v1/communities/{id} Обновить.
DELETE /v1/communities/{id} Удалить при отсутствии ссылок.

7.6. Пиры (bgp_peer)

Метод Путь Описание
GET /v1/peers Список (?speaker_id=, пагинация).
POST /v1/peers Создать пира.
GET /v1/peers/{id} Детали.
PATCH /v1/peers/{id} Политики, neighbor, ASN, привязка к bgp_speaker_id или null = все спикеры.
DELETE /v1/peers/{id} Удалить / отключить.

7.7. Спикеры BIRD (bgp_speaker)

Метод Путь Описание
GET /v1/speakers Список (master / replica, endpoint).
POST /v1/speakers Зарегистрировать спикер (реплика, canary).
GET /v1/speakers/{id} Детали + last_applied_revision_id.
PATCH /v1/speakers/{id} Метаданные, endpoint.

7.8. Ревизии конфигурации (config_revision)

Метод Путь Описание
GET /v1/revisions История ревизий (?module_id=, ?limit=).
GET /v1/revisions/{revision_id} Метаданные: хэш, родитель, время, артефакты.
GET /v1/revisions/{revision_id}/prefixes Материализованный снимок префиксов (пагинация).
GET /v1/revisions/{revision_id}/preview Превью фрагментов BIRD (read-only, без apply).
POST /v1/revisions/{revision_id}/rollback Создать новую ревизию с содержимым отката; часто **202**.

Сравнение ревизий (набросок)

Метод Путь Описание
GET /v1/revisions/{a}/diff/{b} Diff префиксов / метаданных (формат зафиксировать: JSON patch или табличный).

7.9. Применение конфигурации (deploy, BIRD)

Метод Путь Описание
POST /v1/apply Применить текущую целевую ревизию на всех спикерах (или по политике по умолчанию). **202**.
POST /v1/speakers/{id}/apply Применить на одном спикере (canary). **202**.
POST /v1/bird/reload Опционально: явный мягкий reload политики (если отделён от apply); иначе часть apply.

Тело POST /v1/apply (набросок, опционально)

{
  "revision_id": "01JQXYZ...",
  "strategy": "all_speakers",
  "dry_run": false
}

Связь с безопасным применением: §13 (двухфазный deploy, LKG).

7.10. Задачи (job_audit)

Метод Путь Описание
GET /v1/jobs Список задач (?status=, ?kind=, cursor).
GET /v1/jobs/{job_id} Статус, прогресс, ошибка, связанные сущности.
POST /v1/jobs/{job_id}/cancel Запрос отмены (best-effort).

Пример ответа GET /v1/jobs/{id}

{
  "job_id": "01JQXYZ...",
  "kind": "module_refresh",
  "status": "running",
  "idempotency_key": "client-abc-123",
  "created_at": "2026-04-03T10:00:00Z",
  "started_at": "2026-04-03T10:00:01Z",
  "finished_at": null,
  "error": null,
  "meta": { "module_id": "01JQM..." }
}

7.11. Реплики evobgp-node: бандлы

Вызываются нодой с отдельным ключом / mTLS (роль node). См. также §10.

Метод Путь Описание
GET /v1/speakers/{speaker_id}/revisions/latest Указатель на последнюю опубликованную ревизию для ноды.
GET /v1/speakers/{speaker_id}/bundle/{revision_id} Скачивание подписанного бандла (архив + manifest.json + подпись).
POST /v1/nodes/enroll Регистрация ноды (обмен ключами, привязка к speaker_id) — детали протокола отдельно.

Заголовки для бандла: Content-Type: application/octet-stream или multipart; целостность по manifest (SHA-256) и подписи (например Ed25519) — обязательно на ноде в production (§13).

7.12. Глобальные настройки (опционально)

Метод Путь Описание
GET /v1/settings KV вроде global_settings (лимиты CDN, feature flags).
PATCH /v1/settings Частичное обновление (только роль operator).

7.13. Матрица прав (роли)

Ресурс viewer editor operator node
GET модули, ревизии, peers да да да нет*
PATCH модули, peers нет да да нет
apply, rollback нет нет да нет
bundle / enroll нет нет нет да

Нода не ходит в общий CRUD; только §7.11.

7.14. Следующие итерации API

  • Полная OpenAPI 3.1 в docs/openapi.yaml по этому разделу.
  • Webhooks: POST на URL клиента по завершении job (опционально).
  • SSE/WebSocket для стрима статуса долгих jobs.
  • Rate limits по ключу и по tenant в ответах (RateLimit-* заголовки).

7.15. Связь API с разделами плана

Тема плана Подраздел §7
REST, jobs, идемпотентность 7.1, 7.10
refresh, apply, rollback, preview, IP_RANGES 7.3, 7.8, 7.9
peers, speakers, communities, DoH 7.4–7.7
bundle API, нода 7.11
Контрактные тесты HTTP §14 + openapi.yaml

Черновик в репозитории docs/evobgp-api-sketches.md держать синхронным с §7 при согласовании изменений (или пометить файл указателем на план как единый источник).


8. Генерация BIRD и ревизии

  • Фрагменты bird.d/*.conf, include, фильтры, peers.conf, community из справочника.
  • Ревизия: хэш набора префиксов, артефакты, откат = новая ревизия со старым содержимым.

9. Эксплуатация и масштаб

  • До ~20+ клиентских пиров — строки bgp_peer, не отдельные хосты EvoBGP.
  • Rate-limit CDN, per-module cooldown.
  • Canary: несколько bgp_speaker или подмножество пиров по фильтру.
  • Метрики: размер префикс-сета, ошибки DoH/CDN, birdc show protocols.
  • Секреты BGP — Vault / K8s secrets, не plaintext в БД.
  • Last-known-good конфиг на volume / bind-mount, общий для bird2 и evobgp-agent (или снимок на хосте при bind-mount).

10. Реплика evobgp-node

  1. Render на мастере упаковывает бандл (как для мастерского BIRD) + manifest (SHA-256) + подпись (например Ed25519).
  2. evobgp-node: fetch → проверка → распаковка → birdc configure.
  3. Общие фильтры/префиксы идентичны; local.conf на ноде (router id, source) — вне бандла.
  4. Риски: дубли анонсов, отставание ревизий, компрометация без подписи.

11. Выбор СУБД

Решение по умолчанию: PostgreSQL в обоих профилях — один тип миграций, один SQL-диалект в коде (pgx / database/sql), проще сопровождение и перенос с microVPS на reference без смены БД.

Движок Роль в плане
PostgreSQL Основной для reference и microVPS (различаются только ресурсы и postgresql.conf).
SQLite Опция microVPS_sqlite: один контейнер без PG — только при жёстком лимите «ровно один контейнер приложения+БД в одном процессе».
MySQL / MariaDB Опционально по требованию заказчика/хостинга; тот же слой DAO через второй драйвер — вне дефолтного пути.
rqlite HA без отдельного DBA Postgres; +контейнеры; на 1 ГиБ тесно.

Почему PG «не много» и всё же два контейнера на microVPS

При узкой конфигурации (shared_buffers 64–128 МиБ, max_connections 15–30, один пул коннектов в evobgp-all, без сотен долгоживущих backend’ов) суммарный вклад PG сопоставим с практичным использованием SQLite в том же объёме RAM, зато:

  • нет отличий DDL/типов между профилями;
  • нормальные advisory locks / SKIP LOCKED для очереди job_audit;
  • проще подключить внешний managed Postgres при росте.

На microVPS отдельные контейнеры **postgres** и стек bird2 + evobgp-agent — осознанная плата за единообразие с reference (минимум: evobgp-all + postgres + bird2 + evobgp-agent).

PostgreSQL: память и CPU (ориентиры)

Сценарий соединения RAM на backend
Чистый idle ~1.5 МиБ
После простых запросов ~10–11 МиБ
После тяжёлых / temp ~14.5 МиБ

Плюс shared_buffers, relation cache при огромной схеме, autovacuum. reference: при многих процессах Go — PgBouncer (transaction pooling). microVPS: пулер часто не нужен, если суммарно ≤10 реальных коннектов к PG. Таймауты: idle_in_transaction_session_timeout, statement_timeout, параметры tcp_keepalives_*; мониторинг pg_stat_activity.

rqlite

Raft, HTTP/gorqlite; для HA control-plane; не замена дефолтного PG в плане без отдельного решения.


12. Профиль microVPS — детализация

Железо: 1 vCPU · ~1024 МиБ RAM · 7–10 ГиБ SSD под Docker + данные + логи · Ubuntu 24.04. Рекомендуется swap 512 МиБ–1 ГиБ, если его нет.

Контейнеры

Вариант Состав
A (целевой) evobgp-all + postgres + bird2 + evobgp-agent (общий volume конфигов BIRD; см. §4.1)
B (опция) Без отдельного PG — профиль microVPS_sqlite + тот же стек bird2 + evobgp-agent
C (legacy) BIRD только на хосте ОС — не целевой путь, только для отладки или жёстких ограничений Docker

Бюджет диска 7–10 ГиБ

Статья Ориентир
Образ evobgp-all ~50–150 МиБ
Образ PostgreSQL ~80–200 МиБ (слои образа)
Данные PG ~200 МиБ – 2 ГиБ (политика ревизий)
Конфиги / бандлы ~10–200 МиБ
Логи Docker max-size / max-file в compose
Prune docker system prune по расписанию
Резерв ОС/пики ≥1–2 ГиБ

CPU и RAM

  • Worker pool ingest/render: 1–2; без агрессивного параллелизма на одном ядре.
  • deploy.resources: лимиты на evobgp-all, postgres, bird2, evobgp-agent (на PG ориентир 256m–384m, на пару bird2+agent заложить 128m–256m — уточнить по docker stats).
  • Ориентир суммарно: ~400–750 МиБ простой, ~550–900 МиБ пик (PG + Go + bird2 + система) — на 1 ГиБ обычно нужны swap и жёсткий тюнинг PG/bird2.

Tuning PostgreSQL (microVPS)

Пример направлений (не копировать слепо — проверить по мониторингу):

  • shared_buffers = 64–128 МиБ; max_connections = 20–40; work_mem умеренно низкий.
  • Отключить или минимизировать parallel_workers на 1 vCPU.
  • effective_cache_size подсказка планировщику без выделения RAM.

Tuning PostgreSQL (reference)

Обычные практики под размер ВМ; PgBouncer при многих сервисах Go; резерв под autovacuum и пики ingest.


13. Снижение рисков (меры и процессы)

Дополняет §9 и §10 конкретными обязательными практиками.

Конфигурация BIRD: безопасное применение

  • Двухфазный deploy: (1) запись новой ревизии во временный каталог на общем volume и проверка **bird -c <path> -p** (парсинг без запуска демона; см. bird(8)); (2) только при нулевом коде выхода — атомарная подмена активных файлов (rename) и **birdc configure**. Опционально перед фазой (2) — preview/diff в control-plane (REST).
  • Last-known-good (LKG): хранить на volume предыдущую применённую ревизию; при неуспехе configure или ненулевом exit автоматически восстановить файлы LKG, зафиксировать событие в логах/метриках и не оставлять BIRD в полусобранном состоянии.
  • Canary в production: перед полным apply — отдельный bgp_speaker или подмножество bgp_peer (см. §9); полный выкат только после проверки сессий/префиксов на канареечном спикере.

Данные, очередь, microVPS

  • Миграции: в основной ветке — только вперёд; откат схемы — явные down-миграции (если приняты в процессе) или восстановление БД из бэкапа; политика фиксируется в операторской документации.
  • Jobs: обязательные **idempotency_key** и уникальность в job_audit там, где это предотвращает двойной apply/reload.
  • microVPS: пороги мониторинга на рост таблиц ревизий/артефактов, retention старых ревизий, лимиты ротации логов Docker (см. §12) — с алертами при приближении к лимиту диска и OOM.

Безопасность

  • evobgp-node: в production обязательна проверка подписи бандла (отдельно от TLS транспорта); ключ подписи не смешивать с другими ролями.
  • Секреты BGP (пароли, ключи) — только secret store / Docker secrets; не логировать полные конфиги с секретами.

Поставка и совместимость

  • В Dockerfile / Compose зафиксировать версию образа BIRD 2 (тег minor или digest), совпадающую с образом, в котором выполняется **bird -p** в CI (§15).
  • Статический каркас (router id, локальные интерфейсы, операторские правки) — в файлах вне автогенерируемых фрагментов; сгенерированное — только в согласованных путях bird.d/ (см. §8, §10).

Порядок внедрения (уточнение)

Перед полным набором микросервисов целесообразен параллельный этап: контракт OpenAPI + каркас internal/birdfmt + golden-тесты + проверка bird -p в CI (§14, §15), затем миграции PG и один вертикальный сценарий (например IP_RANGES).


14. Тестирование BIRD2 и матрица сценариев

Цель — покрыть поверхность генератора EvoBGP, а не весь язык BIRD. Комбинации фиксируются матрицей и каталогом сценариев в репозитории (internal/birdfmt/testdata/scenarios/).

Матрица покрытия (ориентир)

Измерение Варианты для покрытия
Роль спикера master (полный набор фрагментов); реплика / бандл для evobgp-node (manifest + подмножество includes + локальный local.conf)
Типы модулей (выход render) AS_PREFIXES, CDN_CIDRS, DOMAINS (материализованные префиксы), IP_RANGES — минимум по одному сценарию; комбинация 2+ типов в одной ревизии
Пиры при поддержке каркасом — только static; 1× IPv4, 1× IPv6, несколько пиров, смешанный v4/v6
Community каждый поддерживаемый kind в справочнике + вариант без community (default)
Фильтры экспорт «разрешить анонс»; при генерации — отрицательные кейсы (reject)
Граничные данные пустой префикс-лист; один префикс; большой список (нагрузка на размер файла)
Шаблоны include каждый именуемый фрагмент из internal/birdfmt участвует хотя бы в одном интеграционном сценарии

По мере расширения генератора матрица дополняется; регрессия — новыми строками в таблице тестов и при необходимости новыми подкаталогами сценариев.

Виды тестов

  1. Unit / snapshot (Go): пакет internal/birdfmt — вход из фикстур, выход сравнивается с *.golden или txtar.
  2. Синтаксис BIRD в CI: для каждого сценария с bird.conf выполняется **bird -c … -p** в контейнере с той же major/minor версией BIRD 2, что в production (§13).
  3. Позже: контрактные тесты HTTP по docs/openapi.yaml и сценариям из §7 после реализации internal/httpapi.

15. CI/CD (Gitea Actions)

  • Workflows: каталог **.gitea/workflows/** в корне репозитория; синтаксис совместим с GitHub Actions (документация Gitea Actions).
  • Нужен зарегистрированный act runner с меткой ubuntu-latest (или согласованной с инсталляцией) и при job с Docker — доступ Docker на runner.
  • Рекомендуемый pipeline: lint OpenAPI (npx @redocly/cli lint docs/openapi.yaml), **go vet / go test / go build ./...**, проверка всех testdata/scenarios/*/bird.conf через bird -p (см. workflow в репозитории).

16. Риски и этапы внедрения

Риски

  • Домены и устаревшие IP; DoH down; IRR/RIR vs локальные фильтры; community-ошибки; дубли при master+node; microVPS: переполнение диска логами/ревизиями, OOM без swap.

Этапы

  1. Monorepo Go, миграции PostgreSQL (основной путь), опционально SQLite для microVPS_sqlite, Compose reference и microVPS.
  2. Один тип модуля end-to-end; render + BIRD.
  3. Расписания CDN/модуля; deploy + agent.
  4. Ревизии, rollback, bundle API.
  5. evobgp-node на отдельной ВМ; observability.
  6. Hardening, документация операторская.
  7. Web UI в отдельном контейнере (§17): полный UX по спискам, расписанию и мониторингу.

17. Web UI (Svelte, shadcn-svelte)

Цель — единая операторская поверхность поверх уже описанного REST (§7) и observability (§4, этапы в §16), без дублирования бизнес-логики на фронтенде: UI только вызывает API и визуализирует состояние.

Стек и упаковка

  • Svelte (актуальная ветка проекта, SvelteKit при необходимости SSR/роутинга) и shadcn-svelte — доступные компоненты (формы, таблицы, диалоги, навигация), единый визуальный язык.
  • Отдельный сервис в Docker Compose (профиль reference): образ со статической сборкой или Node-сервером за reverse-proxy; не вшивать UI в evobgp-api. Контейнер получает только VITE_* / публичный base URL API и при необходимости URL метрик/health-прокси (см. ниже).
  • Сборка и публикация артефакта UI — отдельный job в CI (§15) по мере появления кода в репозитории (например web/ или ui/).

Покрытие user experience

  1. Списки и сущности — модули префиксов, ревизии, пиры, community, DoH-профили, спикеры: просмотр, фильтрация, создание/редактирование там, где это отражено в OpenAPI; связь с jobs и аудитом (§7.10).
  2. Расписание — триггеры и окна обновления модулей/ETL, ручной refresh, очередь задач и статусы без «чёрного ящика» (§7, scheduler в §1).
  3. Мониторинг системы — дашборд health API, агентов и нод; интеграция с метриками/алертами (Prometheus/Grafana или встроенные виджеты по публичным эндпоинтам); наглядное состояние BGP-сессий и последних deploy/revision там, где данные доступны через API или безопасный read-only прокси.

Безопасность и эксплуатация

  • Аутентификация и роли — по §7.13; UI не хранит секреты вне согласованного потока (cookie/session или OIDC — на этапе проектирования конкретной инсталляции).
  • Для microVPS полноценный отдельный контейнер UI опционален (можно тот же образ с profiles или отключённый сервис), чтобы не раздувать single-node; приоритет — reference как эталон операторской панели.

Соответствие старым именам: full ≈ reference, target_vps ≈ microVPS.