# Работа со стендом Этот документ — для оператора, который уже развернул стенд (см. [SETUP.md](SETUP.md)) и теперь использует его в повседневной работе: добавляет адреса на проверку, следит за очередью, разбирается в результатах и реагирует на проблемы. Прямые вызовы API описаны в [API.md](API.md) — здесь мы используем их только как инструмент, не углубляясь в протокол. ## Содержание - [Как устроена работа с системой](#как-устроена-работа-с-системой) - [Добавление новых IP в очередь](#добавление-новых-ip-в-очередь) - [Наблюдение за очередью](#наблюдение-за-очередью) - [Значения полей IP](#значения-полей-ip) - [Как читать итоговый результат (pass/partial/fail)](#как-читать-итоговый-результат-passpartialfail) - [Просмотр деталей и истории по конкретному адресу](#просмотр-деталей-и-истории-по-конкретному-адресу) - [Управление валидаторами](#управление-валидаторами) - [Управление площадками (проберами)](#управление-площадками-проберами) - [Повторная проверка адреса](#повторная-проверка-адреса) - [Частые проблемы и что с ними делать](#частые-проблемы-и-что-с-ними-делать) ## Как устроена работа с системой Оператор не взаимодействует с валидаторами и проберами напрямую — вся работа идёт через `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 в очередь **В текущей версии добавление адресов происходит только через конфиг control-api**, отдельного API-метода "добавить IP в очередь" нет. 1. Добавьте новые адреса в список `ip_addresses` в `/etc/cloud-ip-validator/control-api.yaml` (в конец списка, либо в нужном порядке — очередь обрабатывается строго в порядке следования списка, `sequence`). 2. Перезапустите control-api: ```bash systemctl restart control-api ``` Это безопасно для уже идущей работы: при старте control-api добавляет в очередь только **новые** адреса (те, которых там ещё нет) — уже обработанные ранее адреса не сбрасываются и повторно не проверяются. Адреса, которые были удалены из `ip_addresses`, но уже есть в базе, **не удаляются** из очереди/истории автоматически — если конкретный адрес больше не нужно проверять и его нет в очереди/в процессе, можно просто оставить как есть (историю он не портит). > Совет: держите `control-api.yaml` под версионным контролем (git) — > список адресов на проверку тогда одновременно служит и журналом того, > что вообще когда-либо ставилось в очередь. ## Наблюдение за очередью Общая сводка: ```bash curl -s http://: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://:8080/api/v1/admin/status | python3 -m json.tool' ``` Полный список всех адресов со всеми полями: ```bash curl -s http://:8080/api/v1/admin/ips | python3 -m json.tool ``` Только финальные результаты (уже готовые адреса), с помощью `jq`: ```bash curl -s http://:8080/api/v1/admin/ips \ | jq '[.[] | select(.State=="done" or .State=="failed") | {IPAddress, State, OverallResult}]' ``` ## Значения полей IP | Поле | Значение | |---|---| | `IPAddress` | Проверяемый адрес | | `Sequence` | Позиция в очереди (порядок из конфига) | | `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` | Соответствующая площадка закончила входящие проверки | | `OverallResult` | Итог: `pass`, `partial`, `fail`, либо пусто, пока проверка не завершена | | `AssignedAt` / `AggregatedAt` / `FIPReleasedAt` | Метки времени соответствующих этапов | ## Как читать итоговый результат (pass/partial/fail) - **`pass`** — прошли все проверки (все исходящие + все три площадки по всем портам и ICMP). Адрес можно считать пригодным к повторной выдаче. - **`partial`** — часть проверок прошла, часть — нет (например, площадка site-2 не смогла достучаться по 8080/tcp, но остальное в порядке). Означает частичную деградацию — например, адрес заблокирован в отдельном сегменте сети/у отдельного провайдера. Требует решения оператора: годится ли адрес для данного случая использования. - **`fail`** — либо ни одна проверка не прошла, либо адрес вообще не дошёл до стадии проверок (например, self-check не подтвердился — трафик валидатора не пошёл через назначенный FIP — и попытки исчерпались). Смотрите `events` по этому адресу (см. ниже), чтобы понять, на каком шаге и почему. Отсутствие ответа от источника (площадка не прислала результат до истечения `checking_window_seconds`) засчитывается как провал — это управляется настройкой `aggregation.missing_counts_as_fail` в конфиге control-api (по умолчанию включено). ## Просмотр деталей и истории по конкретному адресу ```bash curl -s http://: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://:8080/api/v1/admin/ips/203.0.113.10 \ | jq '.checks[] | select(.Success==false)' ``` ## Управление валидаторами Список валидаторов и их текущее состояние: ```bash curl -s http://:8080/api/v1/admin/validators | python3 -m json.tool ``` Состояния валидатора: `unregistered` (в конфиге есть, агент ещё не подключался), `idle` (свободен, готов взять адрес), `assigned`/`checking` (занят), `unreachable` (пропустил heartbeat дольше `orchestrator.heartbeat_timeout_seconds`). **Добавление нового валидатора:** 1. Поднимите новую ВМ в сервисном проекте облака, узнайте её Neutron `port_id`. 2. Добавьте запись в `validators` в `control-api.yaml` (`validator_id` + `os_port_id`) и перезапустите `control-api`. 3. Разверните и запустите `validator-agent` на новой ВМ с тем же `validator_id` в его конфиге (см. [SETUP.md](SETUP.md#развёртывание-validator-agent-на-вм-валидаторах)). **Вывод валидатора из эксплуатации:** остановите на нём `validator-agent` (`systemctl stop validator-agent`). Он перестанет получать новые задания после того, как закончит текущее (если оно было); если он был убит посреди работы — control-api сам заберёт у него незавершённый адрес обратно в очередь по истечении `orchestrator.lease_ttl_seconds`. Удалять запись из `control-api.yaml` не обязательно — просто выключенный агент не будет ничего забирать. ## Управление площадками (проберами) Аналогично валидаторам: чтобы добавить площадку, добавьте `site_id` + `index` (свободный от 1 до 3, или больше — но текущая схема БД рассчитана ровно на 3 площадки, см. ниже) в `sites` конфига control-api, разверните на площадке `prober` с тем же `site_id`. > Важно: количество площадок в текущей версии жёстко зашито в схему БД > (`Site1Complete`/`Site2Complete`/`Site3Complete`) — система рассчитана > ровно на **три** внешние площадки, как и описано в исходной схеме > процесса. Изменение их числа потребует доработки схемы данных, это не > делается только правкой конфига. ## Повторная проверка адреса Если адрес завершился с `failed` или `partial`, а вы хотите перепроверить его ещё раз (например, после устранения блокировки на стороне сети): на данный момент нет отдельного API-метода "перезапустить проверку". Самый простой путь: 1. Убедитесь, что адрес не находится в активном состоянии (`checking` и т.п.) — то есть уже `done`/`failed`. 2. Временно уберите и снова добавьте адрес в список `ip_addresses` (либо просто пересоздайте запись в БД вручную, если это единичный случай и у вас есть доступ к SQLite) и перезапустите `control-api`. Поскольку сидирование очереди идёт по уникальности `ip_address` (конфликт по уже существующей записи просто игнорируется), самый чистый способ гарантированно перепроверить конкретный адрес — обратиться к администратору БД (см. следующий раздел) либо дождаться штатной доработки API под повторные проверки. ## Частые проблемы и что с ними делать **Валидатор долго висит в `unreachable`.** Проверьте сетевую связность ВМ-валидатора до `control-api` (порт из `server.listen_addr`) и что процесс `validator-agent` вообще запущен (`systemctl status validator-agent`, `journalctl -u validator-agent`). **Адрес постоянно проваливает self-check.** Смотрите `events` по адресу (`GET /api/v1/admin/ips/{ip}`) — в детали события `self_check_result` будет указан обнаруженный исходящий адрес. Если он не совпадает с ожидаемым — вероятно, на ВМ-валидаторе есть другой маршрут наружу (не через назначенный Floating IP), либо привязка FIP на стороне OpenStack не применилась. Проверьте вручную в OpenStack (`openstack floating ip show <адрес>`), что `port_id` совпадает с портом валидатора. **Площадка (`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.