2026-08-21 07:34:45 +03:00
|
|
|
|
# Работа со стендом
|
|
|
|
|
|
|
|
|
|
|
|
Этот документ — для оператора, который уже развернул стенд (см.
|
|
|
|
|
|
[SETUP.md](SETUP.md)) и теперь использует его в повседневной работе:
|
|
|
|
|
|
добавляет адреса на проверку, следит за очередью, разбирается в
|
|
|
|
|
|
результатах и реагирует на проблемы. Прямые вызовы API описаны в
|
|
|
|
|
|
[API.md](API.md) — здесь мы используем их только как инструмент, не
|
|
|
|
|
|
углубляясь в протокол.
|
|
|
|
|
|
|
|
|
|
|
|
## Содержание
|
|
|
|
|
|
|
|
|
|
|
|
- [Как устроена работа с системой](#как-устроена-работа-с-системой)
|
|
|
|
|
|
- [Добавление новых IP в очередь](#добавление-новых-ip-в-очередь)
|
|
|
|
|
|
- [Наблюдение за очередью](#наблюдение-за-очередью)
|
|
|
|
|
|
- [Значения полей IP](#значения-полей-ip)
|
|
|
|
|
|
- [Как читать итоговый результат (pass/partial/fail)](#как-читать-итоговый-результат-passpartialfail)
|
|
|
|
|
|
- [Просмотр деталей и истории по конкретному адресу](#просмотр-деталей-и-истории-по-конкретному-адресу)
|
|
|
|
|
|
- [Управление валидаторами](#управление-валидаторами)
|
|
|
|
|
|
- [Управление площадками (проберами)](#управление-площадками-проберами)
|
2026-08-23 20:39:22 +03:00
|
|
|
|
- [Управление целями проверки](#управление-целями-проверки)
|
2026-08-21 07:34:45 +03:00
|
|
|
|
- [Повторная проверка адреса](#повторная-проверка-адреса)
|
2026-08-23 20:39:22 +03:00
|
|
|
|
- [Принудительная остановка проверки](#принудительная-остановка-проверки)
|
2026-08-21 07:34:45 +03:00
|
|
|
|
- [Частые проблемы и что с ними делать](#частые-проблемы-и-что-с-ними-делать)
|
|
|
|
|
|
|
|
|
|
|
|
## Как устроена работа с системой
|
|
|
|
|
|
|
|
|
|
|
|
Оператор не взаимодействует с валидаторами и проберами напрямую — вся
|
|
|
|
|
|
работа идёт через `control-api`. Цикл жизни одного IP-адреса:
|
|
|
|
|
|
|
|
|
|
|
|
1. Адрес встаёт в очередь (`queued`).
|
|
|
|
|
|
2. Control-api сам находит свободный валидатор, привязывает адрес к нему
|
|
|
|
|
|
как Floating IP.
|
|
|
|
|
|
3. Валидатор проверяет, что действительно вышел в интернет именно через
|
|
|
|
|
|
этот адрес (self-check), затем прогоняет исходящие проверки (HTTPS,
|
|
|
|
|
|
ICMP, опционально SSH до заданных внешних целей).
|
|
|
|
|
|
4. Одновременно три внешние площадки проверяют, что этот адрес доступен
|
|
|
|
|
|
*снаружи* (входящие TCP-подключения на 22/80/443/8080 и ICMP) — это
|
|
|
|
|
|
ловит блокировки/чёрные списки на конкретных внешних сетях.
|
|
|
|
|
|
5. Как только все источники (валидатор + 3 площадки) отчитались — или
|
|
|
|
|
|
истекло время ожидания — control-api подводит итог и освобождает
|
|
|
|
|
|
адрес (отвязывает Floating IP).
|
|
|
|
|
|
|
|
|
|
|
|
Всё это происходит автоматически, без участия оператора. Задача оператора
|
|
|
|
|
|
— положить адреса в очередь и снять с них результат.
|
|
|
|
|
|
|
|
|
|
|
|
## Добавление новых IP в очередь
|
|
|
|
|
|
|
2026-08-23 20:39:22 +03:00
|
|
|
|
Основной способ — API, без перезапуска процесса:
|
2026-08-21 07:34:45 +03:00
|
|
|
|
|
2026-08-23 20:39:22 +03:00
|
|
|
|
```bash
|
|
|
|
|
|
curl -s -X POST http://<control-api>:8080/api/v1/admin/ips \
|
|
|
|
|
|
-d '{"addresses": ["203.0.113.10", "203.0.113.11"]}'
|
|
|
|
|
|
```
|
2026-08-21 07:34:45 +03:00
|
|
|
|
|
2026-08-23 20:39:22 +03:00
|
|
|
|
```json
|
|
|
|
|
|
{"added": ["203.0.113.10", "203.0.113.11"], "requeued": [], "reordered": [], "skipped_in_progress": []}
|
|
|
|
|
|
```
|
2026-08-21 07:34:45 +03:00
|
|
|
|
|
2026-08-23 20:39:22 +03:00
|
|
|
|
Адреса обрабатываются в порядке, в котором перечислены в `addresses` —
|
|
|
|
|
|
именно в этом порядке они и встанут в очередь друг за другом. Метод
|
|
|
|
|
|
идемпотентен относительно уже идущих проверок: адрес, который сейчас
|
|
|
|
|
|
активно проверяется, в ответе окажется в `skipped_in_progress` и не будет
|
|
|
|
|
|
тронут (см. [«Повторная проверка адреса»](#повторная-проверка-адреса)
|
|
|
|
|
|
ниже — тот же метод форсирует перепроверку уже завершённых адресов).
|
|
|
|
|
|
|
|
|
|
|
|
Также по-прежнему можно добавить адреса через `ip_addresses` в
|
|
|
|
|
|
`/etc/cloud-ip-validator/control-api.yaml` и перезапустить control-api —
|
|
|
|
|
|
при каждом старте control-api доливает в очередь только новые адреса из
|
|
|
|
|
|
этого списка (уже обработанные ранее не сбрасываются и повторно не
|
|
|
|
|
|
проверяются). Держать `control-api.yaml` под версионным контролем (git)
|
|
|
|
|
|
по-прежнему полезно как журнал того, что изначально ставилось в очередь
|
|
|
|
|
|
при разворачивании стенда — но для повседневного добавления адресов проще
|
|
|
|
|
|
и быстрее пользоваться API выше.
|
2026-08-21 07:34:45 +03:00
|
|
|
|
|
|
|
|
|
|
## Наблюдение за очередью
|
|
|
|
|
|
|
|
|
|
|
|
Общая сводка:
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
curl -s http://<control-api>:8080/api/v1/admin/status | python3 -m json.tool
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"total_ips": 25,
|
|
|
|
|
|
"ips_by_state": {"queued": 10, "awaiting_self_check": 1, "checking": 3, "done": 10, "failed": 1},
|
|
|
|
|
|
"total_validators": 4
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
`ips_by_state` — сколько адресов в каждом состоянии прямо сейчас. Если
|
|
|
|
|
|
хотите наблюдать за прогрессом в реальном времени:
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
watch -n 2 'curl -s http://<control-api>:8080/api/v1/admin/status | python3 -m json.tool'
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Полный список всех адресов со всеми полями:
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
curl -s http://<control-api>:8080/api/v1/admin/ips | python3 -m json.tool
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Только финальные результаты (уже готовые адреса), с помощью `jq`:
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
curl -s http://<control-api>:8080/api/v1/admin/ips \
|
|
|
|
|
|
| jq '[.[] | select(.State=="done" or .State=="failed") | {IPAddress, State, OverallResult}]'
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## Значения полей IP
|
|
|
|
|
|
|
|
|
|
|
|
| Поле | Значение |
|
|
|
|
|
|
|---|---|
|
|
|
|
|
|
| `IPAddress` | Проверяемый адрес |
|
2026-08-23 20:39:22 +03:00
|
|
|
|
| `Sequence` | Позиция в очереди (порядок постановки — из конфига при первом старте либо из последнего вызова `POST /api/v1/admin/ips`) |
|
2026-08-21 07:34:45 +03:00
|
|
|
|
| `State` | Текущий этап: `queued`, `assigning_fip`, `awaiting_self_check`, `checking`, `aggregating`, `done`, `failed` |
|
|
|
|
|
|
| `OwnerValidatorID` | Какой валидатор сейчас (или последним) занимался этим адресом |
|
|
|
|
|
|
| `FIPID` | Идентификатор Floating IP в OpenStack, к которому привязан адрес (пусто, если ещё/уже не привязан) |
|
|
|
|
|
|
| `AttemptNumber` | Номер попытки — растёт при каждом requeue (сбой привязки, сбой self-check, реклейм по таймауту) |
|
|
|
|
|
|
| `RetryCount` | Сколько раз адрес уже переставлялся в очередь заново |
|
|
|
|
|
|
| `EgressComplete` | Валидатор закончил исходящие проверки |
|
|
|
|
|
|
| `Site1Complete` / `Site2Complete` / `Site3Complete` | Соответствующая площадка закончила входящие проверки |
|
2026-08-23 20:39:22 +03:00
|
|
|
|
| `OverallResult` | Итог: `pass`, `partial`, `fail`, `cancelled` (принудительно остановлена, см. [«Принудительная остановка проверки»](#принудительная-остановка-проверки)), либо пусто, пока проверка не завершена |
|
2026-08-21 07:34:45 +03:00
|
|
|
|
| `AssignedAt` / `AggregatedAt` / `FIPReleasedAt` | Метки времени соответствующих этапов |
|
|
|
|
|
|
|
|
|
|
|
|
## Как читать итоговый результат (pass/partial/fail)
|
|
|
|
|
|
|
2026-08-21 11:25:52 +03:00
|
|
|
|
- **`pass`** — прошли все проверки: все исходящие, плюс все площадки по
|
|
|
|
|
|
всем портам и ICMP — если площадки вообще настроены (`sites` в конфиге
|
|
|
|
|
|
control-api может быть пустым, см.
|
|
|
|
|
|
[«Управление площадками»](#управление-площадками-проберами) — тогда
|
|
|
|
|
|
учитываются только исходящие). Адрес можно считать пригодным к
|
|
|
|
|
|
повторной выдаче.
|
2026-08-21 07:34:45 +03:00
|
|
|
|
- **`partial`** — часть проверок прошла, часть — нет (например, площадка
|
|
|
|
|
|
site-2 не смогла достучаться по 8080/tcp, но остальное в порядке).
|
|
|
|
|
|
Означает частичную деградацию — например, адрес заблокирован в
|
|
|
|
|
|
отдельном сегменте сети/у отдельного провайдера. Требует решения
|
|
|
|
|
|
оператора: годится ли адрес для данного случая использования.
|
|
|
|
|
|
- **`fail`** — либо ни одна проверка не прошла, либо адрес вообще не
|
|
|
|
|
|
дошёл до стадии проверок (например, self-check не подтвердился —
|
|
|
|
|
|
трафик валидатора не пошёл через назначенный FIP — и попытки
|
|
|
|
|
|
исчерпались). Смотрите `events` по этому адресу (см. ниже), чтобы
|
|
|
|
|
|
понять, на каком шаге и почему.
|
2026-08-23 20:39:22 +03:00
|
|
|
|
- **`cancelled`** — проверку остановил оператор через `POST
|
|
|
|
|
|
/api/v1/admin/ips/{ip}/cancel` (`State` при этом — `failed`), а не
|
|
|
|
|
|
система по итогам проверок. Отличать от обычного `fail` полезно, чтобы
|
|
|
|
|
|
не путать «адрес не прошёл проверку» с «проверку прервали вручную».
|
2026-08-21 07:34:45 +03:00
|
|
|
|
|
|
|
|
|
|
Отсутствие ответа от источника (площадка не прислала результат до
|
|
|
|
|
|
истечения `checking_window_seconds`) засчитывается как провал — это
|
|
|
|
|
|
управляется настройкой `aggregation.missing_counts_as_fail` в конфиге
|
|
|
|
|
|
control-api (по умолчанию включено).
|
|
|
|
|
|
|
|
|
|
|
|
## Просмотр деталей и истории по конкретному адресу
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
curl -s http://<control-api>:8080/api/v1/admin/ips/203.0.113.10 | python3 -m json.tool
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Ответ содержит три части:
|
|
|
|
|
|
- `ip` — те же поля, что и в списке `admin/ips`, но для одного адреса;
|
|
|
|
|
|
- `checks` — все отдельные проверки текущей попытки: кто проверял
|
|
|
|
|
|
(`Source`: `egress` или `inbound-site-N`), что именно (`CheckType`,
|
|
|
|
|
|
`Target`), результат (`Success`), задержка (`LatencyMS`), и
|
|
|
|
|
|
человекочитаемая деталь (`Detail`, например текст ошибки при отказе);
|
|
|
|
|
|
- `events` — журнал аудита по этому адресу в хронологическом порядке
|
|
|
|
|
|
(регистрация, привязка FIP, self-check, агрегация и т.д.) — полезен,
|
|
|
|
|
|
чтобы восстановить точную последовательность событий при разборе
|
|
|
|
|
|
инцидента.
|
|
|
|
|
|
|
|
|
|
|
|
Пример: почему адрес получил `fail`?
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
curl -s http://<control-api>:8080/api/v1/admin/ips/203.0.113.10 \
|
|
|
|
|
|
| jq '.checks[] | select(.Success==false)'
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## Управление валидаторами
|
|
|
|
|
|
|
|
|
|
|
|
Список валидаторов и их текущее состояние:
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
curl -s http://<control-api>:8080/api/v1/admin/validators | python3 -m json.tool
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Состояния валидатора: `unregistered` (в конфиге есть, агент ещё не
|
|
|
|
|
|
подключался), `idle` (свободен, готов взять адрес), `assigned`/`checking`
|
|
|
|
|
|
(занят), `unreachable` (пропустил heartbeat дольше
|
|
|
|
|
|
`orchestrator.heartbeat_timeout_seconds`).
|
|
|
|
|
|
|
2026-08-23 20:39:22 +03:00
|
|
|
|
**Добавление нового валидатора (без перезапуска control-api):**
|
2026-08-21 07:34:45 +03:00
|
|
|
|
1. Поднимите новую ВМ в сервисном проекте облака, узнайте её Neutron
|
|
|
|
|
|
`port_id`.
|
2026-08-23 20:39:22 +03:00
|
|
|
|
2. Зарегистрируйте валидатора через API:
|
|
|
|
|
|
```bash
|
|
|
|
|
|
curl -s -X POST http://<control-api>:8080/api/v1/admin/config/validators \
|
|
|
|
|
|
-d '{"validator_id": "validator_05", "os_port_id": "port-abc123"}'
|
|
|
|
|
|
```
|
2026-08-21 07:34:45 +03:00
|
|
|
|
3. Разверните и запустите `validator-agent` на новой ВМ с тем же
|
|
|
|
|
|
`validator_id` в его конфиге (см. [SETUP.md](SETUP.md#развёртывание-validator-agent-на-вм-валидаторах)).
|
|
|
|
|
|
|
2026-08-23 20:39:22 +03:00
|
|
|
|
Сменить `os_port_id` уже существующего валидатора (например, после
|
|
|
|
|
|
пересоздания ВМ) — `PUT /api/v1/admin/config/validators/{id}` с телом
|
|
|
|
|
|
`{"os_port_id": "новый-port-id"}`.
|
|
|
|
|
|
|
|
|
|
|
|
Полный список зарегистрированных валидаторов — `GET
|
|
|
|
|
|
/api/v1/admin/config/validators` (в отличие от `GET
|
|
|
|
|
|
/api/v1/admin/validators`, отдаёт `snake_case` и без текущего IP —
|
|
|
|
|
|
только конфигурационные поля).
|
|
|
|
|
|
|
2026-08-21 07:34:45 +03:00
|
|
|
|
**Вывод валидатора из эксплуатации:** остановите на нём
|
|
|
|
|
|
`validator-agent` (`systemctl stop validator-agent`). Он перестанет
|
|
|
|
|
|
получать новые задания после того, как закончит текущее (если оно было);
|
|
|
|
|
|
если он был убит посреди работы — control-api сам заберёт у него
|
|
|
|
|
|
незавершённый адрес обратно в очередь по истечении
|
2026-08-23 20:39:22 +03:00
|
|
|
|
`orchestrator.lease_ttl_seconds`. Удалять регистрацию валидатора не
|
|
|
|
|
|
обязательно — просто выключенный агент не будет ничего забирать. Если всё
|
|
|
|
|
|
же нужно убрать валидатора из системы совсем:
|
|
|
|
|
|
```bash
|
|
|
|
|
|
curl -s -X DELETE http://<control-api>:8080/api/v1/admin/config/validators/validator_05
|
|
|
|
|
|
```
|
|
|
|
|
|
Возвращает `409`, если валидатор прямо сейчас владеет каким-то IP —
|
|
|
|
|
|
дождитесь освобождения (или принудительно остановите его проверку, см.
|
|
|
|
|
|
[«Принудительная остановка проверки»](#принудительная-остановка-проверки))
|
|
|
|
|
|
перед удалением.
|
|
|
|
|
|
|
|
|
|
|
|
> Правки через `validators[]` в `control-api.yaml` тоже поддерживаются,
|
|
|
|
|
|
> но только как bootstrap пустой базы данных при самом первом старте — как
|
|
|
|
|
|
> только в БД есть хотя бы один валидатор, YAML для этой секции
|
|
|
|
|
|
> игнорируется при всех последующих рестартах (см.
|
|
|
|
|
|
> [SETUP.md](SETUP.md#развёртывание-control-api)). Для стенда, который уже
|
|
|
|
|
|
> хоть раз запускался, используйте API выше.
|
2026-08-21 07:34:45 +03:00
|
|
|
|
|
|
|
|
|
|
## Управление площадками (проберами)
|
|
|
|
|
|
|
2026-08-21 11:25:52 +03:00
|
|
|
|
**Входящие (inbound/prober) проверки полностью опциональны.** Список
|
|
|
|
|
|
`sites` в конфиге control-api и есть переключатель: пусто — inbound-
|
|
|
|
|
|
проверки выключены целиком, итоговый результат считается только по
|
|
|
|
|
|
исходящим (egress) проверкам, и агрегация не ждёт вообще ни одного
|
|
|
|
|
|
пробера. Указан один или два слота — ждём только их, остальные не
|
|
|
|
|
|
учитываются. Указаны все три — работает как в исходной схеме процесса.
|
|
|
|
|
|
Явного отдельного флага "включить/выключить" нет — самого списка `sites`
|
|
|
|
|
|
достаточно.
|
2026-08-21 07:34:45 +03:00
|
|
|
|
|
2026-08-23 20:39:22 +03:00
|
|
|
|
Чтобы добавить площадку (без перезапуска control-api) — назначьте
|
|
|
|
|
|
`site_id` на один из трёх слотов (`index` 1, 2 или 3 — см. ограничение
|
|
|
|
|
|
ниже) через API:
|
|
|
|
|
|
```bash
|
|
|
|
|
|
curl -s -X PUT http://<control-api>:8080/api/v1/admin/config/sites/1 \
|
|
|
|
|
|
-d '{"site_id": "site-1"}'
|
|
|
|
|
|
```
|
|
|
|
|
|
и разверните на площадке `prober` с тем же `site_id`. Чтобы отключить
|
|
|
|
|
|
конкретную площадку — освободите слот:
|
|
|
|
|
|
```bash
|
|
|
|
|
|
curl -s -X DELETE http://<control-api>:8080/api/v1/admin/config/sites/1
|
|
|
|
|
|
```
|
2026-08-21 11:25:52 +03:00
|
|
|
|
процесс `prober` на ней можно не останавливать (он просто перестанет
|
2026-08-23 20:39:22 +03:00
|
|
|
|
получать назначения — `POST /api/v1/probers/register` для отвязанного
|
|
|
|
|
|
`site_id` начнёт отвечать `400`). Текущее распределение слотов — `GET
|
|
|
|
|
|
/api/v1/admin/config/sites`.
|
|
|
|
|
|
|
|
|
|
|
|
> Правки через `sites[]` в `control-api.yaml` тоже поддерживаются, но
|
|
|
|
|
|
> только как bootstrap пустой базы данных при самом первом старте — как
|
|
|
|
|
|
> только в БД есть хотя бы одна площадка, YAML для этой секции
|
|
|
|
|
|
> игнорируется при всех последующих рестартах. Для стенда, который уже
|
|
|
|
|
|
> хоть раз запускался, используйте API выше.
|
2026-08-21 11:25:52 +03:00
|
|
|
|
|
|
|
|
|
|
> Важно: количество *возможных* слотов площадок жёстко зашито в схему БД
|
|
|
|
|
|
> (`Site1Complete`/`Site2Complete`/`Site3Complete`) — не более **трёх**,
|
|
|
|
|
|
> как и описано в исходной схеме процесса. `index` может быть только 1, 2
|
|
|
|
|
|
> или 3. Использовать *меньше* трёх (в том числе ноль) — штатный,
|
|
|
|
|
|
> поддерживаемый сценарий; *больше* трёх потребует доработки схемы
|
|
|
|
|
|
> данных, одной правкой конфига не обойтись.
|
2026-08-21 07:34:45 +03:00
|
|
|
|
|
2026-08-23 20:39:22 +03:00
|
|
|
|
## Управление целями проверки
|
|
|
|
|
|
|
|
|
|
|
|
Набор egress-целей (`targets`) и типов проверок (`check_types`,
|
|
|
|
|
|
привязывающих тип — `https`/`icmp`/`ssh` — к одной или нескольким группам
|
|
|
|
|
|
целей) управляется через API так же, как валидаторы и площадки —
|
|
|
|
|
|
изменения подхватываются немедленно, следующим же назначением от
|
|
|
|
|
|
оркестратора, без перезапуска.
|
|
|
|
|
|
|
|
|
|
|
|
Посмотреть текущий набор:
|
|
|
|
|
|
```bash
|
|
|
|
|
|
curl -s http://<control-api>:8080/api/v1/admin/config/targets | python3 -m json.tool
|
|
|
|
|
|
curl -s http://<control-api>:8080/api/v1/admin/config/check-types | python3 -m json.tool
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Создать/заменить группу целей и включить тип проверки, ссылающийся на
|
|
|
|
|
|
неё:
|
|
|
|
|
|
```bash
|
|
|
|
|
|
curl -s -X PUT http://<control-api>:8080/api/v1/admin/config/targets/web \
|
|
|
|
|
|
-d '{"targets": ["https://hub.docker.com", "https://github.com"]}'
|
|
|
|
|
|
|
|
|
|
|
|
curl -s -X PUT http://<control-api>:8080/api/v1/admin/config/check-types/ssh \
|
|
|
|
|
|
-d '{"enabled": true, "targets": ["web"]}'
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Отключить тип проверки, не удаляя его (значения целей сохраняются):
|
|
|
|
|
|
```bash
|
|
|
|
|
|
curl -s -X PUT http://<control-api>:8080/api/v1/admin/config/check-types/ssh \
|
|
|
|
|
|
-d '{"enabled": false, "targets": ["web"]}'
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Удалить группу целей можно только если на неё не ссылается ни один
|
|
|
|
|
|
`check_type` (иначе — `409`); удалить сам `check_type` можно в любой
|
|
|
|
|
|
момент (`DELETE /api/v1/admin/config/check-types/{name}`).
|
|
|
|
|
|
|
|
|
|
|
|
**Важное следствие принятого компромисса**: если конфигурация меняется
|
|
|
|
|
|
ровно в момент, когда чей-то IP уже находится в `checking` (self-check
|
|
|
|
|
|
уже пройден, проверки уже назначены агенту), агрегация этой конкретной
|
|
|
|
|
|
попытки посчитает уже изменённую конфигурацию, а не ту, что была на
|
|
|
|
|
|
момент выдачи задания. На практике это узкое окно в несколько секунд;
|
|
|
|
|
|
деградирует безопасно — через `aggregation.missing_counts_as_fail` худший
|
|
|
|
|
|
исход для одной попытки — `partial` вместо `pass`, самоисправляется на
|
|
|
|
|
|
следующей попытке (в том числе через принудительный повтор, см. ниже).
|
|
|
|
|
|
|
|
|
|
|
|
> Правки через `targets`/`check_types` в `control-api.yaml` тоже
|
|
|
|
|
|
> поддерживаются, но только как bootstrap пустой базы данных при самом
|
|
|
|
|
|
> первом старте — см. примечание в разделах выше.
|
|
|
|
|
|
|
2026-08-21 07:34:45 +03:00
|
|
|
|
## Повторная проверка адреса
|
|
|
|
|
|
|
|
|
|
|
|
Если адрес завершился с `failed` или `partial`, а вы хотите перепроверить
|
2026-08-23 20:39:22 +03:00
|
|
|
|
его ещё раз (например, после устранения блокировки на стороне сети) —
|
|
|
|
|
|
отправьте его тем же методом, что используется для постановки новых
|
|
|
|
|
|
адресов в очередь:
|
2026-08-21 07:34:45 +03:00
|
|
|
|
|
2026-08-23 20:39:22 +03:00
|
|
|
|
```bash
|
|
|
|
|
|
curl -s -X POST http://<control-api>:8080/api/v1/admin/ips \
|
|
|
|
|
|
-d '{"addresses": ["203.0.113.10"]}'
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{"added": [], "requeued": ["203.0.113.10"], "reordered": [], "skipped_in_progress": []}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Адрес в `requeued` означает, что он был в терминальном состоянии
|
|
|
|
|
|
(`done`/`failed`) и его перезапустили: `AttemptNumber` увеличился,
|
|
|
|
|
|
`RetryCount` обнулён, предыдущий `OverallResult` сброшен, адрес снова
|
|
|
|
|
|
`queued` и будет обработан на общих основаниях. Никакой особой обработки
|
|
|
|
|
|
для уже проверенных адресов не требуется — тот же вызов безопасно
|
|
|
|
|
|
принимает список из новых и уже проверенных адресов одновременно;
|
|
|
|
|
|
единственное, что метод не сделает — не запустит вторую параллельную
|
|
|
|
|
|
проверку адреса, который прямо сейчас уже проверяется (такой адрес
|
|
|
|
|
|
вернётся в `skipped_in_progress`, см.
|
|
|
|
|
|
[«Добавление новых IP в очередь»](#добавление-новых-ip-в-очередь)).
|
|
|
|
|
|
|
|
|
|
|
|
## Принудительная остановка проверки
|
|
|
|
|
|
|
|
|
|
|
|
Если проверка адреса зависла дольше ожидаемого либо просто больше не
|
|
|
|
|
|
актуальна, не дожидайтесь истечения `checking_window_seconds` —
|
|
|
|
|
|
остановите её сразу:
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
curl -s -X POST http://<control-api>:8080/api/v1/admin/ips/203.0.113.10/cancel
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Работает из любого состояния, кроме уже терминального (`done`/`failed`
|
|
|
|
|
|
вернут `409` — отменять нечего). Если на момент отмены был привязан
|
|
|
|
|
|
Floating IP — он отвязывается (best-effort, как и при обычном завершении
|
|
|
|
|
|
проверки), владевший валидатор освобождается и снова становится `idle`.
|
|
|
|
|
|
Итог записывается как `OverallResult: "cancelled"` (в `State: "failed"`),
|
|
|
|
|
|
и виден в истории адреса наравне с обычными результатами:
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
curl -s http://<control-api>:8080/api/v1/admin/ips/203.0.113.10 | python3 -m json.tool
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Чтобы позже всё же проверить этот адрес — используйте
|
|
|
|
|
|
[«Повторную проверку адреса»](#повторная-проверка-адреса) выше, она
|
|
|
|
|
|
одинаково работает и для отменённых, и для обычно завершённых адресов.
|
2026-08-21 07:34:45 +03:00
|
|
|
|
|
|
|
|
|
|
## Частые проблемы и что с ними делать
|
|
|
|
|
|
|
|
|
|
|
|
**Валидатор долго висит в `unreachable`.**
|
|
|
|
|
|
Проверьте сетевую связность ВМ-валидатора до `control-api` (порт из
|
|
|
|
|
|
`server.listen_addr`) и что процесс `validator-agent` вообще запущен
|
|
|
|
|
|
(`systemctl status validator-agent`, `journalctl -u validator-agent`).
|
|
|
|
|
|
|
2026-08-21 11:04:49 +03:00
|
|
|
|
**Адрес не выходит из `awaiting_self_check` (статус не меняется вообще).**
|
|
|
|
|
|
Self-check запрашивает внешние (вне облака) сервисы из
|
|
|
|
|
|
`self_check.ip_echo_urls` в конфиге валидатора (по умолчанию
|
|
|
|
|
|
`api.ipify.org`, `ifconfig.me`) — если у ВМ-валидатора нет исходящего
|
|
|
|
|
|
доступа в интернет к этим адресам, запрос не проходит вообще, и агент
|
|
|
|
|
|
даже не может *сообщить* результат control-api (ни успешный, ни
|
|
|
|
|
|
неуспешный) — тогда статус реально зависает до истечения
|
|
|
|
|
|
`orchestrator.lease_ttl_seconds`, после чего адрес возвращается в
|
|
|
|
|
|
`queued` и цикл повторяется. Проверьте связность до
|
|
|
|
|
|
`self_check.ip_echo_urls` прямо с ВМ-валидатора (`curl -s
|
|
|
|
|
|
https://api.ipify.org`) и логи `journalctl -u validator-agent` на предмет
|
|
|
|
|
|
`ip echo request failed`.
|
|
|
|
|
|
|
|
|
|
|
|
**Адрес постоянно проваливает self-check (не зависает, а именно
|
|
|
|
|
|
возвращается в очередь снова и снова).**
|
2026-08-21 07:34:45 +03:00
|
|
|
|
Смотрите `events` по адресу (`GET /api/v1/admin/ips/{ip}`) — в детали
|
|
|
|
|
|
события `self_check_result` будет указан обнаруженный исходящий адрес.
|
|
|
|
|
|
Если он не совпадает с ожидаемым — вероятно, на ВМ-валидаторе есть другой
|
|
|
|
|
|
маршрут наружу (не через назначенный Floating IP), либо привязка FIP на
|
|
|
|
|
|
стороне OpenStack не применилась. Проверьте вручную в OpenStack
|
|
|
|
|
|
(`openstack floating ip show <адрес>`), что `port_id` совпадает с портом
|
2026-08-21 11:04:49 +03:00
|
|
|
|
валидатора. Обратите внимание: адрес для сравнения обязан быть **вне**
|
|
|
|
|
|
облака (см. `self_check.ip_echo_urls`) — запрос к чему-либо внутри
|
|
|
|
|
|
проекта (в том числе к самому control-api, если он в той же внутренней
|
|
|
|
|
|
сети) покажет приватный адрес валидатора независимо от того, правильно
|
|
|
|
|
|
ли привязан FIP, и всегда будет давать ложный провал.
|
2026-08-21 07:34:45 +03:00
|
|
|
|
|
|
|
|
|
|
**Площадка (`site-N`) никогда не отчитывается (`SiteNComplete` всегда
|
|
|
|
|
|
`false`).**
|
|
|
|
|
|
Проверьте, что `prober` на этой площадке запущен и его `site_id` в
|
|
|
|
|
|
конфиге совпадает с `site_id` в конфиге control-api. Проверьте, что
|
|
|
|
|
|
площадка имеет сетевой доступ и до `control-api`, и до проверяемого
|
|
|
|
|
|
адреса (входящий трафик на 22/80/443/8080 + ICMP — это отдельная
|
|
|
|
|
|
связность от связи с control-api, см.
|
|
|
|
|
|
[SETUP.md](SETUP.md#сетевые-доступы)).
|
|
|
|
|
|
|
|
|
|
|
|
**Много адресов зависло в `checking` дольше ожидаемого.**
|
|
|
|
|
|
Это нормально, если ещё не истёк `orchestrator.checking_window_seconds` —
|
|
|
|
|
|
агрегация ждёт либо полного набора ответов, либо истечения окна. Если
|
|
|
|
|
|
адрес завис заметно дольше окна — проверьте, что фоновый цикл control-api
|
|
|
|
|
|
вообще работает (смотрите `journalctl -u control-api` на предмет ошибок
|
|
|
|
|
|
в `sweep checking window`).
|
|
|
|
|
|
|
|
|
|
|
|
**Нужно посмотреть на данные "из первых рук", в обход API.**
|
|
|
|
|
|
`control-api` использует SQLite, файл — по пути `database.path` из
|
|
|
|
|
|
конфига. Можно (только для чтения, на **той же машине**, где крутится
|
|
|
|
|
|
control-api) открыть его `sqlite3` в режиме WAL — это безопасно для
|
|
|
|
|
|
чтения параллельно с работающим процессом:
|
|
|
|
|
|
```bash
|
|
|
|
|
|
sqlite3 /var/lib/cloud-ip-validator/control-api.db \
|
|
|
|
|
|
"select ip_address, state, overall_result from ip_queue order by sequence"
|
|
|
|
|
|
```
|
|
|
|
|
|
Не редактируйте эту базу вручную во время работы control-api — это может
|
|
|
|
|
|
рассинхронизировать состояние с реальными привязками Floating IP в
|
|
|
|
|
|
OpenStack.
|