Files
cloud-ip-validator/docs/SETUP.md
T

443 lines
27 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.
# Подготовка стенда и первичная инициализация
Документ описывает, как подготовить конфигурацию и запустить стенд с нуля
— от чистой машины до работающего 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-на-внешних-площадках)
- [Развёртывание admin-dashboard](#развёртывание-admin-dashboard)
- [Проверка после запуска](#проверка-после-запуска)
- [Сетевые доступы](#сетевые-доступы)
## Компоненты и роли машин
| Компонент | Где запускается | Кол-во |
|---|---|---|
| `control-api` | Отдельная управляющая машина/ВМ с доступом к OpenStack API | 1 (без HA) |
| `validator-agent` | Каждая ВМ-валидатор в сервисном проекте облака | по числу валидаторов |
| `prober` | По одному на каждой из внешних тестовых площадок | 3 (по числу площадок) |
| `admin-dashboard` | Любая машина с сетевым доступом до `control-api` (опционально) | 0 или 1 |
`control-api` — единственный компонент с состоянием (SQLite). Валидаторы,
проберы и `admin-dashboard` не хранят локального состояния и полностью
управляются через опрос control-api (см. [API.md](API.md),
[DASHBOARD.md](DASHBOARD.md)). `admin-dashboard` не обязателен — вся его
функциональность доступна и через `curl` напрямую по API.
## Требования
- Целевые серверы (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 МБ
├── admin-dashboard # ~9 МБ (опционален, см. DASHBOARD.md)
└── 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/
scp bin/admin-dashboard dashboard-host:/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
go build -trimpath -ldflags="-s -w" -o bin/admin-dashboard ./cmd/admin-dashboard
```
Каждый бинарник самодостаточен — скопируйте нужный файл на
соответствующую машину (control-api → управляющая машина, validator-agent
→ каждый валидатор, prober → каждая площадка, admin-dashboard →
опционально, любая машина с доступом до control-api).
Убедиться, что всё собирается и юнит-тесты проходят:
```bash
go build ./... && go test ./...
```
Пересобирайте из исходников и обновляйте `bin/` с зафиксированными
`SHA256SUMS`, если меняли код — готовые бинарники в репозитории **не
обновляются автоматически**:
```bash
sha256sum bin/control-api bin/validator-agent bin/prober bin/admin-dashboard | 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` (число слотов не
ограничено; в примере ниже — три). `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` (по умолчанию выключен).
> `validators`, `sites`, `targets` и `check_types` читаются из этого файла
> только один раз — при самом первом старте против пустой базы данных
> (bootstrap). После этого все последующие изменения этих четырёх секций
> вносятся через `/api/v1/admin/config/*`, а не правкой YAML — см.
> [API.md](API.md#управление-очередью-и-конфигурацией) и
> [USAGE.md](USAGE.md#управление-валидаторами). `ip_addresses` — исключение,
> он остаётся YAML + аддитивным добавлением при каждом старте (плюс
> `POST /api/v1/admin/ips` для управления очередью без рестарта).
### 2. Переменные окружения для OpenStack
Учётные данные передаются **только** через переменные окружения — никогда
через YAML. Есть два режима аутентификации, выбираются полем
`openstack.auth_method` в `control-api.yaml`:
**`auth_method: "token"` (по умолчанию)** — вы предоставляете уже
готовый, заранее scoped на нужный проект токен (например, полученный
через `openstack --os-project-id=<id> token issue`). Control-api
использует его как есть, ни на что не обменивает. Просто, но токен не
самообновляется: когда он истечёт, `control-api` начнёт получать ошибки
от OpenStack API, пока вы вручную не перевыпустите токен, не обновите
переменную и не перезапустите процесс.
```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=<токен администратора, уже scoped на сервисный проект>
OS_PROJECT_ID=<id сервисного проекта>
OS_REGION_NAME=<регион>
EOF
```
**`auth_method: "password"`** — вы предоставляете обычные логин/пароль;
control-api сам получает токен через Keystone и автоматически
переполучает новый при истечении текущего (весь срок жизни процесса, без
ручного вмешательства). Компромисс — в файле окружения лежит долгоживущий
пароль, а не токен.
```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_PROJECT_ID=<id сервисного проекта>
OS_REGION_NAME=<регион>
OS_USERNAME=<логин>
OS_USER_DOMAIN_NAME=<домен пользователя>
OS_PASSWORD=<пароль>
EOF
```
и в `control-api.yaml`: `openstack.auth_method: "password"`.
Опционально в обоих режимах — `OS_INTERFACE` (`public`/`internal`/`admin`,
по умолчанию `public`): выбирает, какой из адресов Neutron в каталоге
сервисов использовать, если у эндпоинта их несколько.
Имена переменных должны совпадать с тем, что указано в
`control-api.yaml` в секции `openstack` (`auth_url_env`, `token_env` и
т.д.) — в шаблоне это ровно `OS_AUTH_URL`, `OS_PROJECT_ID`,
`OS_REGION_NAME`, `OS_INTERFACE`, и, в зависимости от режима, либо
`OS_TOKEN`, либо `OS_USERNAME`/`OS_USER_DOMAIN_NAME`/`OS_PASSWORD` — это
стандартные имена, принятые в python-openstackclient/RC-файлах, менять их
обычно не требуется.
### 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. **Bootstrap-once для `validators`/`sites`/`targets`/`check_types`.**
YAML применяется **только если соответствующая таблица в БД сейчас
пуста** — то есть только на самом первом старте против чистой базы.
Как только в таблице появилась хотя бы одна строка (через этот
bootstrap либо через `/api/v1/admin/config/*`, см.
[API.md](API.md#управление-очередью-и-конфигурацией)), YAML для этой
секции больше не перечитывается ни при одном последующем рестарте —
источник истины переключается на БД. Это осознанное отличие от более
ранних версий, где `validators` из YAML переприменялись при каждом
рестарте: теперь правки, сделанные через admin API (например, смена
`os_port_id` валидатора), переживают рестарт вместо того, чтобы
тихо откатываться.
2. **Всегда аддитивно** добавляет в очередь все адреса из
`ip_addresses`, которых там ещё нет (уже обработанные ранее адреса
повторно не добавляются и не сбрасываются — см.
[USAGE.md](USAGE.md#добавление-новых-ip-в-очередь)). Это отдельный,
не завязанный на bootstrap-once путь — не путайте с
`POST /api/v1/admin/ips`, который умеет то же самое (и ещё
принудительный повтор уже проверенных адресов) без перезапуска.
Проверить, что процесс поднялся:
```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
```
## Развёртывание admin-dashboard
Опционально — вся его функциональность доступна и через `curl` напрямую
по API (см. [API.md](API.md)). На любой машине с сетевым доступом до
`control-api`:
```bash
cp bin/admin-dashboard /usr/local/bin/admin-dashboard
cp deploy/systemd/admin-dashboard.service /etc/systemd/system/
mkdir -p /etc/cloud-ip-validator
cp configs/admin-dashboard.example.yaml /etc/cloud-ip-validator/admin-dashboard.yaml
# отредактировать control_api.base_url под ваш стенд
systemctl daemon-reload
systemctl enable --now admin-dashboard
journalctl -u admin-dashboard -f
```
Открыть `http://<admin-dashboard>:8090/` в браузере. Подробнее о
страницах и о том, что дашборд может (и не может) — в
[DASHBOARD.md](DASHBOARD.md).
## Проверка после запуска
После того как control-api, все валидаторы и все три пробера запущены:
```bash
curl -s http://<control-api>: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://<control-api>: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, который в данный момент привязан к валидатору.
- `validator-agent` → внешние IP-echo сервисы из `self_check.ip_echo_urls`
(по умолчанию `api.ipify.org`, `ifconfig.me`) — **обязательно вне
облака**: это и есть механизм self-check (см.
[DIAGRAMS.md](DIAGRAMS.md#2-поток-данных-от-валидатора-к-целевому-серверу-egress-проверка)).
Если валидатор не может достучаться ни до одного из этих адресов,
self-check никогда не пройдёт и IP будет бесконечно возвращаться в
очередь — см. [USAGE.md](USAGE.md#частые-проблемы-и-что-с-ними-делать).
- `control-api` → OpenStack Keystone/Neutron API (`OS_AUTH_URL` и далее по
каталогу сервисов).
- `admin-dashboard` → `control-api`: тот же порт (`server.listen_addr`),
адрес задаётся в `control_api.base_url` конфига дашборда.
- Оператор (браузер) → `admin-dashboard`: порт из `server.listen_addr`
дашборда (по умолчанию 8090).
API control-api сейчас не аутентифицирован (см. предупреждение в начале
[API.md](API.md)) — то же самое верно и для `admin-dashboard`, который
это API оборачивает. Ограничивайте доступ к обоим портам на уровне
сети/firewall: к control-api — теми хостами, где реально работают
валидаторы, проберы и сам дашборд; к дашборду — теми, кому разрешено
администрировать стенд.