# Подготовка стенда и первичная инициализация Документ описывает, как подготовить конфигурацию и запустить стенд с нуля — от чистой машины до работающего control-api, валидаторов и проберов. Бинарники брать не обязательно из исходников: в репозитории уже лежат готовые сборки для Linux x86_64 (`bin/`) — это самый быстрый путь к развёртыванию, см. [«Получение бинарников»](#получение-бинарников). Если нужно просто быстро посмотреть систему в работе без реального OpenStack — сразу переходите к разделу [«Быстрая проверка без OpenStack»](#быстрая-проверка-без-openstack-offline-режим). ## Содержание - [Компоненты и роли машин](#компоненты-и-роли-машин) - [Требования](#требования) - [Получение бинарников](#получение-бинарников) - [Вариант A: готовые бинарники из репозитория (рекомендуется)](#вариант-a-готовые-бинарники-из-репозитория-рекомендуется) - [Вариант B: сборка из исходников](#вариант-b-сборка-из-исходников) - [Быстрая проверка без OpenStack (offline-режим)](#быстрая-проверка-без-openstack-offline-режим) - [Подготовка конфигурации для реального стенда](#подготовка-конфигурации-для-реального-стенда) - [Развёртывание control-api](#развёртывание-control-api) - [Развёртывание validator-agent на ВМ-валидаторах](#развёртывание-validator-agent-на-вм-валидаторах) - [Развёртывание prober на внешних площадках](#развёртывание-prober-на-внешних-площадках) - [Проверка после запуска](#проверка-после-запуска) - [Сетевые доступы](#сетевые-доступы) ## Компоненты и роли машин | Компонент | Где запускается | Кол-во | |---|---|---| | `control-api` | Отдельная управляющая машина/ВМ с доступом к OpenStack API | 1 (без HA) | | `validator-agent` | Каждая ВМ-валидатор в сервисном проекте облака | по числу валидаторов | | `prober` | По одному на каждой из внешних тестовых площадок | 3 (по числу площадок) | `control-api` — единственный компонент с состоянием (SQLite). Валидаторы и проберы не хранят локального состояния и полностью управляются через опрос control-api (см. [API.md](API.md)). ## Требования - Целевые серверы (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 — инструмент их **не создаёт**, только привязывает/отвязывает существующие. - Для `validator-agent` и `prober` — возможность отправлять ICMP echo (нужен root либо capability `CAP_NET_RAW`, см. юниты systemd). - `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 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 ``` Каждый бинарник самодостаточен — скопируйте нужный файл на соответствующую машину (control-api → управляющая машина, validator-agent → каждый валидатор, prober → каждая площадка). Убедиться, что всё собирается и юнит-тесты проходят: ```bash go build ./... && go test ./... ``` Пересобирайте из исходников и обновляйте `bin/` с зафиксированными `SHA256SUMS`, если меняли код — готовые бинарники в репозитории **не обновляются автоматически**: ```bash sha256sum bin/control-api bin/validator-agent bin/prober | sed 's#bin/##' > bin/SHA256SUMS ``` ## Быстрая проверка без OpenStack (offline-режим) Прежде чем разворачивать реальный стенд, рекомендуется убедиться, что всё собирается и работает корректно на локальной машине — без облака и внешних площадок: ```bash scripts/run-local-e2e.sh ``` Скрипт сам поднимает control-api (в режиме `openstack.mode: mock`), одного validator-agent и трёх проберов как локальные процессы, прогоняет один тестовый адрес через полный цикл проверки и печатает итоговый результат. Подробности — в [docs/LOCAL_E2E.md](LOCAL_E2E.md). Это же хороший способ разобраться в поведении системы перед первым боевым запуском. ## Подготовка конфигурации для реального стенда Все три компонента конфигурируются YAML-файлами. Шаблоны лежат в `configs/*.example.yaml` — скопируйте их и заполните под ваш стенд. ### 1. `control-api.yaml` ```bash cp configs/control-api.example.yaml /etc/cloud-ip-validator/control-api.yaml ``` Что обязательно нужно заполнить: - **`validators`** — список валидаторов, у каждого `validator_id` (произвольное имя, должно совпадать с `validator_id` в конфиге соответствующего `validator-agent`) и `os_port_id` — **ID Neutron-порта** основного сетевого интерфейса ВМ-валидатора (узнать: `openstack port list --server <имя-ВМ>` или в веб-консоли облака). - **`sites`** — три внешние площадки, `site_id` + `index` (1, 2 или 3). `site_id` должен совпадать с `site_id` в конфиге соответствующего `prober`. - **`ip_addresses`** — список публичных IPv4-адресов на проверку, **в порядке обработки**. Адреса должны существовать в сервисном проекте как уже выделенные (allocated) floating IP — инструмент их не создаёт. - **`openstack.mode: "real"`** и `*_env` поля — имена переменных окружения, из которых будут прочитаны реальные учётные данные (сами значения в этот файл **не пишутся**, см. следующий пункт). - **`targets`** и **`check_types`** — при необходимости смените набор целей для egress-проверок (по умолчанию — hub.docker.com, github.com, packages.ubuntu.com) или включите `ssh` (по умолчанию выключен). ### 2. Переменные окружения для OpenStack Учётные данные передаются **только** через переменные окружения — никогда через YAML. Создайте файл (доступный на чтение только сервисному пользователю): ```bash install -m 0600 -o cloud-ip-validator -g cloud-ip-validator /dev/null /etc/cloud-ip-validator/control-api.env cat >> /etc/cloud-ip-validator/control-api.env <<'EOF' OS_AUTH_URL=https://keystone.example.com:5000/v3 OS_TOKEN=<токен администратора с правами на управление floating IP> OS_PROJECT_ID= OS_REGION_NAME=<регион> EOF ``` Имена переменных должны совпадать с тем, что указано в `control-api.yaml` в секции `openstack` (`auth_url_env`, `token_env` и т.д.) — в шаблоне это ровно `OS_AUTH_URL`, `OS_TOKEN`, `OS_PROJECT_ID`, `OS_PROJECT_NAME`, `OS_PROJECT_DOMAIN_NAME`, `OS_REGION_NAME`. ### 3. `validator-agent.yaml` (свой на каждом валидаторе) ```bash cp configs/validator-agent.example.yaml /etc/cloud-ip-validator/validator-agent.yaml ``` Обязательно поменять: - `validator_id` — должен совпадать с одним из `validators[].validator_id` в конфиге control-api. - `control_api_url` — адрес, по которому эта ВМ достучится до control-api. ### 4. `prober.yaml` (свой на каждой площадке) ```bash cp configs/prober.example.yaml /etc/cloud-ip-validator/prober.yaml ``` Обязательно поменять: - `site_id` — должен совпадать с одним из `sites[].site_id` в конфиге control-api (для трёх площадок — три разных файла с `site-1`, `site-2`, `site-3` или как вы их назвали). - `control_api_url` — адрес control-api, доступный с площадки (обычно через интернет — площадки внешние). ## Развёртывание control-api ```bash useradd --system --no-create-home --shell /usr/sbin/nologin cloud-ip-validator mkdir -p /var/lib/cloud-ip-validator /etc/cloud-ip-validator chown cloud-ip-validator:cloud-ip-validator /var/lib/cloud-ip-validator cp bin/control-api /usr/local/bin/control-api cp deploy/systemd/control-api.service /etc/systemd/system/ systemctl daemon-reload systemctl enable --now control-api ``` **Первичная инициализация базы данных происходит автоматически** — при первом старте `control-api` создаёт файл SQLite по пути `database.path` из конфига (миграция схемы применяется один раз, повторные запуски — no-op). Отдельной команды "init db" не требуется. При каждом старте control-api также: 1. Регистрирует в БД всех валидаторов из `validators` конфига (если их там ещё нет). 2. Добавляет в очередь все адреса из `ip_addresses`, которых там ещё нет (уже обработанные ранее адреса повторно не добавляются и не сбрасываются — см. [USAGE.md](USAGE.md#добавление-новых-ip-в-очередь)). Проверить, что процесс поднялся: ```bash curl -s http://localhost:8080/healthz # {"ok":true} journalctl -u control-api -f ``` ## Развёртывание validator-agent на ВМ-валидаторах Повторить на каждой ВМ-валидаторе: ```bash cp bin/validator-agent /usr/local/bin/validator-agent cp deploy/systemd/validator-agent.service /etc/systemd/system/ mkdir -p /etc/cloud-ip-validator # скопировать сюда заполненный validator-agent.yaml с уникальным validator_id systemctl daemon-reload systemctl enable --now validator-agent journalctl -u validator-agent -f ``` Юнит выдаёт процессу capability `CAP_NET_RAW` (без root) — она нужна для отправки ICMP echo в рамках проверок. ## Развёртывание prober на внешних площадках Аналогично, на каждой из трёх площадок: ```bash cp bin/prober /usr/local/bin/prober cp deploy/systemd/prober.service /etc/systemd/system/ mkdir -p /etc/cloud-ip-validator # скопировать сюда prober.yaml с уникальным site_id для этой площадки systemctl daemon-reload systemctl enable --now prober journalctl -u prober -f ``` ## Проверка после запуска После того как control-api, все валидаторы и все три пробера запущены: ```bash curl -s http://:8080/api/v1/admin/status | python3 -m json.tool ``` Ожидаемая картина сразу после старта: часть адресов в состоянии `queued`, часть уже переходит в `assigning_fip`/`awaiting_self_check`/`checking` по мере того, как освобождаются валидаторы. Через некоторое время появляются записи в `done`/`failed`. Подробнее о том, как читать этот вывод и что делать дальше — в [USAGE.md](USAGE.md). Также стоит убедиться, что все валидаторы видны и не «зависли»: ```bash curl -s http://:8080/api/v1/admin/validators | python3 -m json.tool ``` Все зарегистрированные валидаторы должны рано или поздно оказываться в состоянии `idle` (между заданиями) — если валидатор надолго застрял в `unreachable`, проверьте сетевую связность до control-api и логи агента (`journalctl -u validator-agent`). ## Сетевые доступы Минимально необходимая связность: - `validator-agent` → `control-api`: TCP, порт из `server.listen_addr` (обычно 8080). - `prober` (на каждой из 3 площадок) → `control-api`: тот же порт, обычно через интернет. - `prober` → адрес, который в данный момент проверяется (динамический, меняется по ходу работы очереди): TCP 22/80/443/8080 + ICMP — собственно и есть проверяемый трафик, его нельзя заранее ограничить одним IP. - `validator-agent` → интернет: HTTPS/ICMP до целей из `targets` конфига (по умолчанию hub.docker.com, github.com, packages.ubuntu.com) — именно через floating IP, который в данный момент привязан к валидатору. - `control-api` → OpenStack Keystone/Neutron API (`OS_AUTH_URL` и далее по каталогу сервисов). API control-api сейчас не аутентифицирован (см. предупреждение в начале [API.md](API.md)) — ограничивайте доступ к порту control-api на уровне сети/firewall теми хостами, где реально работают валидаторы и проберы.