Files
cloud-ip-validator/docs/DIAGRAMS.md
T
ayurishchevandClaude Sonnet 5 2246369b64 Add control/data plane diagrams for microservices deployment to docs
Standalone HTML page (docs/CONTROL_DATA_PLANE.html) showing the
docker-compose deployment topology (hosts, COMPOSE_PROFILES) and the
egress/inbound check traffic, refined through several presentation
review passes. Linked from README.md's docs table and docs/DIAGRAMS.md
alongside the existing Mermaid diagrams.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NeVbMVEiE7XQAkBd7HQgj6
2026-09-13 21:38:51 +03:00

236 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Диаграммы потоков данных
Три диаграммы, поясняющие устройство системы на уровне потоков данных —
дополнение к [API.md](API.md) (протокол) и [USAGE.md](USAGE.md) (работа
оператора). Диаграммы — в формате Mermaid, рендерятся нативно на
GitHub/GitLab и в большинстве современных Markdown-просмотрщиков.
Презентационная версия этих же двух разрезов (control plane и data plane)
под микросервисный (docker-compose) деплой, с топологией по хостам и
профилям `COMPOSE_PROFILES` — [CONTROL_DATA_PLANE.html](CONTROL_DATA_PLANE.html)
(самодостаточный HTML-файл, открыть в браузере).
## Как читать диаграммы
Единое условное обозначение стрелок для всех диаграмм:
| Обозначение | Значение |
|---|---|
| `-->` тонкая сплошная | Управляющий вызов / API-запрос |
| `-.->` пунктирная | Ответ, уведомление, асинхронный результат |
| `==>` жирная сплошная | Реальный сетевой трафик проверки (data-plane) — именно то, что валидируется, а не служебный вызов |
## Содержание
- [1. Control plane сервиса](#1-control-plane-сервиса)
- [2. Поток данных: от валидатора к целевому серверу (egress-проверка)](#2-поток-данных-от-валидатора-к-целевому-серверу-egress-проверка)
- [3. Поток данных телеметрии](#3-поток-данных-телеметрии)
---
## 1. Control plane сервиса
Кто кем управляет и через какой канал: конфигурация оператора, HTTP API
control-api, фоновый оркестратор, база данных, вызовы к OpenStack и опрос
со стороны validator-agent/prober.
```mermaid
flowchart TB
subgraph OP["Оператор"]
CFG["control-api.yaml<br/>(bootstrap пустой БД:<br/>validators, sites, targets,<br/>check_types, ip_addresses)"]
ENV["control-api.env<br/>(OS_AUTH_URL, OS_TOKEN, ...)"]
ADMIN["curl /api/v1/admin/*<br/>(status/ips/validators,<br/>ips submit/cancel,<br/>config CRUD)"]
end
subgraph CAPI["control-api (управляющая машина, 1 экземпляр)"]
HTTP["HTTP API<br/>/api/v1/agents/*<br/>/api/v1/probers/*<br/>/api/v1/admin/*<br/>/healthz"]
ORCH["Оркестратор: Tick раз в<br/>poll_interval_seconds<br/>claim → associate FIP →<br/>ожидание self-check →<br/>checking → aggregate → release<br/>+ lease sweep + heartbeat sweep"]
DB[("SQLite<br/>validators / ip_queue / sites /<br/>target_groups / check_types /<br/>checks / events")]
OSCLIENT["OpenStack-клиент<br/>(mode: mock | real)"]
end
OS["OpenStack Neutron<br/>Floating IP API"]
VA["validator-agent ×N<br/>(на каждой ВМ-валидаторе)"]
PR["prober ×3<br/>(на каждой внешней площадке)"]
CFG -->|"читается только один раз,<br/>на пустых таблицах (bootstrap)"| DB
ENV -->|"переменные окружения процесса"| OSCLIENT
ADMIN --> HTTP
HTTP -->|"config/queue CRUD:<br/>источник истины после<br/>первого изменения"| DB
HTTP --> ORCH
ORCH <--> DB
ORCH --> OSCLIENT
OSCLIENT -->|"associate / disassociate<br/>floating ip"| OS
VA <-->|"register, heartbeat,<br/>GET assignment,<br/>POST self-check/events/<br/>results/complete"| HTTP
PR <-->|"register,<br/>GET assignments,<br/>POST results"| HTTP
```
**Пояснение.** `control-api` — единственный компонент с состоянием и
единственная точка принятия решений (какой IP кому назначить, когда
считать проверку завершённой). `control-api.yaml` используется только как
одноразовый bootstrap для четырёх секций (`validators`, `sites`,
`targets`, `check_types`) — читается лишь пока соответствующая таблица в
БД пуста; `ip_addresses` — отдельный, всегда аддитивный путь постановки в
очередь при каждом старте. После bootstrap все изменения этих сущностей,
включая состав очереди и принудительные повтор/остановку проверки, идут
через `/api/v1/admin/*` — «на лету», без `systemctl restart control-api`
(см. [API.md](API.md#управление-очередью-и-конфигурацией)). Оркестратор
работает по таймеру независимо от HTTP-запросов — назначение IP
валидаторам и агрегация результатов не привязаны к конкретному входящему
запросу, читая актуальную конфигурацию из БД на каждом проходе, а не
единожды при старте. `validator-agent` и `prober` — активная сторона: они
сами инициируют все HTTP-запросы к control-api (pull-модель), сам
control-api к ним не обращается.
---
## 2. Поток данных: от валидатора к целевому серверу (egress-проверка)
Как валидатор проверяет, что через назначенный ему публичный адрес
реально работает исходящий доступ в интернет.
```mermaid
flowchart LR
subgraph VM["ВМ-валидатор (сервисный проект OpenStack)"]
AGENT["validator-agent"]
end
FIP(["Floating IP<br/>203.0.113.10<br/>(адрес под проверкой,<br/>привязан оркестратором заранее)"])
IPECHO["Внешний IP-echo сервис<br/>(api.ipify.org и т.п.,<br/>вне облака)"]
CAPI["control-api"]
subgraph TARGETS["Целевые серверы (targets из конфига)"]
T1["hub.docker.com"]
T2["github.com"]
T3["packages.ubuntu.com"]
end
AGENT ==>|"1 self-check: исходящий трафик<br/>ВМ идёт через FIP (SNAT облака)"| FIP
FIP ==>|"1 GET"| IPECHO
IPECHO -.->|"2 наблюдаемый исходящий IP"| AGENT
AGENT -->|"3 POST self-check {success}"| CAPI
AGENT ==>|"4 проверки: тоже через FIP"| FIP
FIP ==>|"4 HTTPS GET"| T1
FIP ==>|"4 HTTPS GET"| T2
FIP ==>|"4 ICMP echo"| T3
```
**Пояснение.** Шаги 1–2 — самопроверка (self-check): агент сам (без
участия control-api) обращается к внешнему IP-echo сервису и сравнивает
адрес, с которого пришёл его собственный запрос, с адресом, который ему
назначен. Ресурс для сравнения обязан быть вне облака: OpenStack
применяет SNAT через Floating IP только к трафику, уходящему через
внешнюю сеть — обращение к чему-либо внутри проекта (включая сам
control-api, если он в той же внутренней сети) показало бы приватный
адрес валидатора независимо от корректности привязки FIP. Итог
самопроверки агент затем сообщает control-api отдельным вызовом (шаг 3) —
это уже управляющий, а не проверяемый трафик. Только после успешного
self-check агент переходит к шагу 4 и выполняет проверки из
`check_config` (HTTPS/ICMP/опционально SSH) против целей из конфига —
тем же путём, через тот же FIP. Каждый результат отправляется обратно в
control-api сразу после выполнения (см. диаграмму телеметрии ниже) — сам
этот data-plane трафик (шаги 1 и 4) в control-api не проходит и им не
наблюдается напрямую, control-api видит только заявленный агентом
результат.
### Дополнительно: обратное направление (пробер к валидатору)
Тот же Floating IP одновременно проверяется и «снаружи» — с трёх внешних
площадок, независимо от исходящих проверок агента:
```mermaid
flowchart LR
subgraph SITES["3 внешние площадки"]
P1["prober site-1"]
P2["prober site-2"]
P3["prober site-3"]
end
FIP(["тот же Floating IP<br/>203.0.113.10"])
VM["ВМ-валидатор<br/>(слушает 22/80/443/8080)"]
P1 ==>|"TCP connect + ICMP echo"| FIP
P2 ==>|"TCP connect + ICMP echo"| FIP
P3 ==>|"TCP connect + ICMP echo"| FIP
FIP -.-> VM
```
Именно сочетание двух направлений (egress от валидатора и inbound от трёх
площадок) и даёт полную картину: адрес может нормально работать «наружу»,
но быть заблокирован для конкретных внешних сетей — это увидит только
inbound-проверка, и наоборот.
---
## 3. Поток данных телеметрии
Как результаты проверок и события аудита от validator-agent и трёх
проберов попадают в базу данных control-api, агрегируются в итоговый
результат и становятся видны оператору.
```mermaid
flowchart TB
subgraph SOURCES["Источники телеметрии"]
VA["validator-agent<br/>(egress-проверки + self-check)"]
P1["prober site-1"]
P2["prober site-2"]
P3["prober site-3"]
end
subgraph API["HTTP API control-api"]
EP1["POST /agents/{id}/events"]
EP2["POST /agents/{id}/self-check"]
EP3["POST /agents/{id}/results"]
EP4["POST /probers/{site_id}/results"]
end
subgraph DB["SQLite (control-api)"]
EVENTS[("events<br/>журнал аудита")]
CHECKS[("checks<br/>результаты проверок,<br/>source=egress|inbound-site-N")]
IPQ[("ip_queue<br/>state, *_complete,<br/>overall_result")]
end
AGG["Агрегация (оркестратор):<br/>по достижении всех *_complete<br/>или по таймауту checking_window_seconds"]
ADMIN["Оператор:<br/>GET /api/v1/admin/status<br/>GET /api/v1/admin/ips<br/>GET /api/v1/admin/ips/{ip}"]
VA -->|"config_received,<br/>self_check_result, ..."| EP1 --> EVENTS
VA -->|"success, detected_egress_ip"| EP2 --> EVENTS
EP2 -.->|"успех → egress_complete"| IPQ
VA -->|"check_type, target,<br/>success, latency_ms"| EP3 --> CHECKS
P1 & P2 & P3 -->|"check_type, success,<br/>latency_ms, complete"| EP4 --> CHECKS
EP4 -.->|"complete=true → siteN_complete"| IPQ
CHECKS --> AGG
IPQ --> AGG
AGG -->|"overall_result:<br/>pass / partial / fail"| IPQ
EVENTS --> ADMIN
CHECKS --> ADMIN
IPQ --> ADMIN
```
**Пояснение.** Телеметрия стекается в БД из четырёх независимых потоков
(один от агента-валидатора, три — по одному с каждой площадки),
записываясь в две таблицы: `events` — сырой журнал аудита (что и когда
произошло), `checks` — результат каждой отдельной проверки с указанием
источника (`source`: `egress` для валидатора, `inbound-site-1/2/3` для
площадок). Отдельно, по мере поступления данных, выставляются флаги
завершения (`egress_complete`, `site1/2/3_complete`) в `ip_queue`. Как
только все ожидаемые флаги выставлены — либо истекло время ожидания
(`checking_window_seconds`) — фоновая агрегация суммирует все строки
`checks` по текущей попытке и записывает итог (`pass`/`partial`/`fail`)
обратно в `ip_queue`. Оператор в любой момент читает уже накопленные
данные через административные `GET`-методы, не дожидаясь завершения
проверки — подробнее о значениях полей см.
[USAGE.md](USAGE.md#значения-полей-ip).
> На диаграмме показан пример с тремя площадками — это лишь иллюстрация,
> не ограничение. Площадки опциональны и их число не ограничено: сколько
> их ожидать, определяется списком `sites` в конфиге control-api (пустой
> список — ни одного потока `inbound-site-N`, агрегация ждёт только
> `egress_complete`; N площадок — N параллельных потоков телеметрии). См.
> [USAGE.md](USAGE.md#управление-площадками-проберами).