diagrams and binaries

This commit is contained in:
ayurishchev committed 2026-08-21 08:11:58 +03:00
1 parent 7e44db87b2
commit f81285b151
7 files changed
+293 -15

No files matched your search

+207
View File
@@ -0,0 +1,207 @@
# Диаграммы потоков данных
Три диаграммы, поясняющие устройство системы на уровне потоков данных —
дополнение к [API.md](API.md) (протокол) и [USAGE.md](USAGE.md) (работа
оператора). Диаграммы — в формате Mermaid, рендерятся нативно на
GitHub/GitLab и в большинстве современных Markdown-просмотрщиков.
## Как читать диаграммы
Единое условное обозначение стрелок для всех диаграмм:
| Обозначение | Значение |
|---|---|
| `-->` тонкая сплошная | Управляющий вызов / 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/>(validators, sites, targets,<br/>ip_addresses, check_types)"]
ENV["control-api.env<br/>(OS_AUTH_URL, OS_TOKEN, ...)"]
ADMIN["curl /api/v1/admin/*"]
end
subgraph CAPI["control-api (управляющая машина, 1 экземпляр)"]
HTTP["HTTP API<br/>/api/v1/agents/*<br/>/api/v1/probers/*<br/>/api/v1/admin/*<br/>/healthz · /whatsmyip"]
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<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/>(инициализация validators, ip_queue)"| CAPI
ENV -->|"переменные окружения процесса"| OSCLIENT
ADMIN --> HTTP
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 кому назначить, когда
считать проверку завершённой). Конфигурация читается один раз при
старте процесса (горячей перезагрузки нет — изменения требуют
`systemctl restart control-api`, см. [SETUP.md](SETUP.md)). Оркестратор
работает по таймеру независимо от HTTP-запросов — назначение IP
валидаторам и агрегация результатов не привязаны к конкретному входящему
запросу, а выполняются фоновым циклом `Tick`. `validator-agent` и
`prober` — активная сторона: они сами инициируют все HTTP-запросы к
control-api (pull-модель), сам control-api к ним не обращается.
---
## 2. Поток данных: от валидатора к целевому серверу (egress-проверка)
Как валидатор проверяет, что через назначенный ему публичный адрес
реально работает исходящий доступ в интернет.
```mermaid
flowchart LR
subgraph VM["ВМ-валидатор (сервисный проект OpenStack)"]
AGENT["validator-agent"]
end
CAPI["control-api"]
FIP(["Floating IP<br/>203.0.113.10<br/>(адрес под проверкой,<br/>привязан оркестратором заранее)"])
subgraph TARGETS["Целевые серверы (targets из конфига)"]
T1["hub.docker.com"]
T2["github.com"]
T3["packages.ubuntu.com"]
end
AGENT -->|"1 GET /api/v1/whatsmyip<br/>(self-check)"| CAPI
CAPI -.->|"2 наблюдаемый исходящий IP"| AGENT
AGENT ==>|"3 весь исходящий трафик ВМ<br/>идёт через FIP (SNAT облака)"| FIP
FIP ==>|"4 HTTPS GET"| T1
FIP ==>|"4 HTTPS GET"| T2
FIP ==>|"4 ICMP echo"| T3
```
**Пояснение.** Шаги 1–2 — самопроверка (self-check): агент обращается к
`control-api` и сравнивает адрес, с которого пришёл его собственный
запрос, с адресом, который ему назначен. Поскольку весь исходящий трафик
ВМ реально идёт через привязанный Floating IP (шаг 3, SNAT на стороне
облака), совпадение подтверждает, что назначение применилось корректно —
только после этого агент переходит к шагу 4 и выполняет проверки из
`check_config` (HTTPS/ICMP/опционально SSH) против целей из конфига.
Каждый результат отправляется обратно в control-api сразу после
выполнения (см. диаграмму телеметрии ниже) — сам этот data-plane трафик
(шаги 3–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).
+78 -12
View File
@@ -1,16 +1,21 @@
# Подготовка стенда и первичная инициализация
Документ описывает, как собрать компоненты, подготовить конфигурацию и
запустить стенд с нуля — от чистой машины до работающего control-api,
валидаторов и проберов. Если нужно просто быстро посмотреть систему в
работе без реального OpenStack — сразу переходите к разделу
Документ описывает, как подготовить конфигурацию и запустить стенд с нуля
— от чистой машины до работающего control-api, валидаторов и проберов.
Бинарники брать не обязательно из исходников: в репозитории уже лежат
готовые сборки для Linux x86_64 (`bin/`) — это самый быстрый путь к
развёртыванию, см. [«Получение бинарников»](#получение-бинарников). Если
нужно просто быстро посмотреть систему в работе без реального OpenStack —
сразу переходите к разделу
[«Быстрая проверка без OpenStack»](#быстрая-проверка-без-openstack-offline-режим).
## Содержание
- [Компоненты и роли машин](#компоненты-и-роли-машин)
- [Требования](#требования)
- [Сборка бинарников](#сборка-бинарников)
- [Получение бинарников](#получение-бинарников)
- [Вариант A: готовые бинарники из репозитория (рекомендуется)](#вариант-a-готовые-бинарники-из-репозитория-рекомендуется)
- [Вариант B: сборка из исходников](#вариант-b-сборка-из-исходников)
- [Быстрая проверка без OpenStack (offline-режим)](#быстрая-проверка-без-openstack-offline-режим)
- [Подготовка конфигурации для реального стенда](#подготовка-конфигурации-для-реального-стенда)
- [Развёртывание control-api](#развёртывание-control-api)
@@ -33,9 +38,12 @@ control-api (см. [API.md](API.md)).
## Требования
- **Go 1.22+** для сборки (проверено на Go 1.26). Собранные бинарники —
статические, дополнительных зависимостей на целевых машинах не требуют
(используется чистый Go-драйвер SQLite, без cgo).
- Целевые серверы (control-api, валидаторы, площадки) — **Linux
x86_64 (amd64)**. Для этой платформы в репозитории уже лежат готовые
бинарники (см. ниже) — устанавливать Go на целевые машины не требуется.
- **Go 1.22+** нужен только если вы пересобираете бинарники из
исходников (проверено на Go 1.26) — например, для другой платформы
(arm64, другая ОС) или после изменения кода.
- Для `control-api` в боевом режиме (`openstack.mode: real`) — учётная
запись OpenStack с правами на чтение/изменение floating IP (Neutron)
в сервисном проекте, и заранее выделенные (allocated) floating IP —
@@ -46,15 +54,65 @@ control-api (см. [API.md](API.md)).
- `curl`, `sqlite3` (опционально, для ручной инспекции БД) на машине с
control-api пригодятся для диагностики.
## Сборка бинарников
## Получение бинарников
### Вариант A: готовые бинарники из репозитория (рекомендуется)
В директории `bin/` репозитория уже лежат три готовых бинарника —
собирать их на целевых серверах не нужно, разворачивание сразу
начинается с копирования и запуска (раздел
[«Развёртывание control-api»](#развёртывание-control-api) и далее).
```
bin/
├── control-api # ~11 МБ
├── validator-agent # ~7 МБ
├── prober # ~7 МБ
└── SHA256SUMS
```
Характеристики сборки:
- Платформа: `GOOS=linux GOARCH=amd64`.
- `CGO_ENABLED=0` — статическая линковка, без cgo (используется чистый
Go-драйвер SQLite `modernc.org/sqlite`). Дополнительные `.so`-библиотеки
и конкретная версия glibc на целевом сервере **не требуются**.
- Собрано флагами `-trimpath -ldflags="-s -w"` (без путей сборки и
отладочной информации — компактнее и без утечки информации о машине
сборки).
Убедиться в отсутствии динамических зависимостей и целостности файлов
после переноса на целевой сервер:
```bash
ldd bin/control-api # => "not a dynamic executable"
file bin/control-api # => ELF 64-bit LSB executable, x86-64, statically linked
# После scp/rsync на целевой сервер — проверить, что файлы не повреждены:
sha256sum -c bin/SHA256SUMS
```
Перенос на целевые серверы, например:
```bash
scp bin/control-api control-api-host:/tmp/
scp bin/validator-agent validator-host-01:/tmp/
scp bin/prober probe-site-1:/tmp/
```
> Если целевая платформа отличается от linux/amd64 (например, ВМ на
> arm64) — готовые бинарники не подойдут, используйте
> [вариант B](#вариант-b-сборка-из-исходников).
### Вариант B: сборка из исходников
Из корня репозитория:
```bash
export PATH=$PATH:/usr/local/go/bin # если go не в PATH
go build -o bin/control-api ./cmd/control-api
go build -o bin/validator-agent ./cmd/validator-agent
go build -o bin/prober ./cmd/prober
export CGO_ENABLED=0 GOOS=linux GOARCH=amd64 # поменяйте GOARCH для другой платформы
go build -trimpath -ldflags="-s -w" -o bin/control-api ./cmd/control-api
go build -trimpath -ldflags="-s -w" -o bin/validator-agent ./cmd/validator-agent
go build -trimpath -ldflags="-s -w" -o bin/prober ./cmd/prober
```
Каждый бинарник самодостаточен — скопируйте нужный файл на
@@ -67,6 +125,14 @@ go build -o bin/prober ./cmd/prober
go build ./... && go test ./...
```
Пересобирайте из исходников и обновляйте `bin/` с зафиксированными
`SHA256SUMS`, если меняли код — готовые бинарники в репозитории **не
обновляются автоматически**:
```bash
sha256sum bin/control-api bin/validator-agent bin/prober | sed 's#bin/##' > bin/SHA256SUMS
```
## Быстрая проверка без OpenStack (offline-режим)
Прежде чем разворачивать реальный стенд, рекомендуется убедиться, что всё