Files
awg-dash/deploy/dev-stand.md
embeddevio 94d3a28adf docs(#21): README netns и runbook dev-stand — ci.sh, приоритет AWG_NS_EXEC_MODE, DEV_SKIP_BUILD
Приведение документации к фактическому поведению после ревью PR #53 (раунд 2):
точка входа для CI без make (контракт 0/1/3/4), приоритет AWG_NS_EXEC_MODE над
make-алиасом, сборка без сети (DEV_SKIP_BUILD=1).

Refs #21
Refs #56
2026-10-28 21:58:15 +03:00

128 lines
9.0 KiB
Markdown
Raw Permalink 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.
# dev/staging стенд awg-dash — runbook
Задача **#21** (эпик **#15**). Стенд для локальной разработки и проверки
acceptance criteria до появления staging-окружения.
* Docker-хост: **192.168.1.147** (`ssh root@192.168.1.147`), Docker 29.4.x + compose v5.
* Каталог состояния: **`/opt/awg-dash-dev/{config,data}`** (bind mount → `/config`, `/data`).
* Compose project: **`awg-dash-dev`** (изолирован от PoC-контейнеров `amneziawg-client`).
* Хост-порт приложения: **8180** (`AWG_DASH_PORT`), внутри контейнера — **8080**.
Порт 8080 на dev-хосте занят другим сервисом (drawio), поэтому проброс нестандартный.
## Быстрый старт
```bash
# на Docker-хосте, из корня репозитория
export AWG_DASH_HOST_DIR=/opt/awg-dash-dev
make dev-up # docker compose up -d --build (проект awg-dash-dev)
make dev-verify # проверка AC: health 200 + состояние переживает restart
curl -fsS http://127.0.0.1:8180/api/v1/health
make dev-logs # логи контейнера
make dev-down # остановить (каталоги состояния сохраняются)
```
`dev-up` добавляет `--build`, когда в дереве есть `deploy/Dockerfile` (после мержа #18).
Если у хоста нет сети/DNS для `docker build` (офлайн-стенд, CI без прокси), сборку
нужно пропустить — образ `awg-dash:dev` уже должен существовать:
```bash
make dev-up DEV_SKIP_BUILD=1 # up -d --no-build — использовать готовый образ
make dev-up DEV_UP_BUILD= # вообще не передавать флаги сборки
```
До реализации FastAPI-каркаса (**#31**) `/api/v1/health` не отвечает — контейнер
работает как агент и помечается `unhealthy`. Чтобы проверить плумбинг стенда
(порт, healthcheck, тома, restart) **до** #31, используйте health-заглушку:
```bash
make dev-up-stub # + deploy/docker-compose.stub.yml (DEV-ONLY, api_stub.py)
make dev-verify-stub # AC-1 проходит на заглушке, в отчёте api=stub
```
Заглушка отвечает `{"status":"ok","stub":true,...}` только на `/api/v1/health` и
никогда не должна использоваться в staging/prod.
## Проверка AC (#21)
| AC | Команда | Ожидание |
|---|---|---|
| AC-1: health 200 | `curl -fsS -o /dev/null -w '%{http_code}' http://127.0.0.1:8180/api/v1/health` | `200` (после мержа #31; до него — заглушка через `dev-verify-stub`) |
| AC-2: состояние переживает restart | `make dev-verify` | маркеры в `/config` и `/data` совпадают до и после `docker compose restart` и `--force-recreate` |
| AC-3: netns + мок-endpoint | `make test-netns` | 8/8 тестов, netns `awgt21-{client,gw,uplink}` создаются и сносятся |
`deploy/verify-dev-stand.sh` (за `make dev-verify`) печатает отчёт и возвращает:
| Код | Значение |
|---|---|
| 0 | AC-1 и AC-2 выполнены |
| 1 | регрессия стенда (health не 200 с заглушкой, состояние не сохранилось) |
| 2 | AC-1 заблокирован: API (#31) ещё не реализован, стенд при этом поднят |
| 3 | заблокировано окружением: нет docker/compose или compose-файлов |
## Состав стенда
| Файл | Назначение |
|---|---|
| `docker-compose.dev.yml` | приложение: порт 8080 (наружу `${AWG_DASH_PORT:-8180}`), bind mount `/config` `/data`, healthcheck, NET_ADMIN/NET_RAW/SYS_MODULE, `/dev/net/tun` |
| `docker-compose.stub.yml` | DEV-ONLY оверрайд: health-заглушка до #31 (`api_stub.py`) |
| `docker-compose.test.yml` | тестовый стенд: привилегированный `netns`-раннер + `app` для API-тестов |
| `api_stub.py` | минимальный HTTP-сервер `/api/v1/health` (только dev) |
| `verify-dev-stand.sh` | проверка AC на Docker-хосте + JSON-отчёт |
| `../tests/netns/` | netns-харнесс: топология client/gw/uplink + мок WireGuard-endpoint |
## Переменные окружения
| Переменная | По умолчанию | Назначение |
|---|---|---|
| `AWG_DASH_PORT` | `8180` | хост-порт приложения |
| `AWG_DASH_HOST_DIR` | `/opt/awg-dash-dev` | каталог состояния на хосте |
| `AWG_DASH_IMAGE` | `awg-dash:dev` | имя образа (build или pull) |
| `AWG_DASH_DOCKERFILE` | `deploy/Dockerfile` | путь к Dockerfile для build |
| `COMPOSE_PROJECT_NAME` | `awg-dash-dev` | изоляция от других стендов |
| `AWG_LOG_LEVEL` | `info` | уровень логирования приложения |
| `DEV_SKIP_BUILD` | — | `1` → `make dev-up` выполняет `up -d --no-build` (образ уже собран) |
| `DEV_UP_BUILD` | авто | переопределение флагов сборки (`--build`, пусто, `--no-build`) |
| `AWG_NS_EXEC_MODE` | `auto` | режим входа в netns: `auto|ip|nsenter` (issue #56) |
| `NETNS_EXEC_MODE` | `auto` | make-алиас `AWG_NS_EXEC_MODE` (приоритет у `AWG_NS_EXEC_MODE`) |
## Зависимости
| Зависимость | Состояние | Влияние на стенд |
|---|---|---|
| #16 (каркас репо, Makefile) | PR #47 | нужен `Makefile`, `requirements.txt`, `deploy/` |
| #18 (образ, entrypoint) | PR #49 | нужен `deploy/Dockerfile` для `--build` |
| #31 (каркас FastAPI, `/api/v1/health`) | Sprint 2 | без него AC-1 выполняется только с заглушкой |
| #17 (CI-пайплайн) | Sprint 0 | гейты для пайплайна: `bash tests/netns/ci.sh` (коды 0/1/3/4), `make test-manifests`, `make test-deploy`, `make lint-shell` |
## Откат и уборка
```bash
make dev-down # остановить контейнеры проекта awg-dash-dev
make dev-reset # down --remove-orphans (состояние сохраняется)
docker image rm awg-dash:dev # откатить образ (пересобрать из предыдущего коммита)
du -sh /opt/awg-dash-dev # состояние стенда
```
Перед откатом образа проверьте проект: `docker compose -p awg-dash-dev ls`.
Состояние (`/opt/awg-dash-dev`) не удаляется автоматически — это осознанно: там
конфиги туннеля (`/config/awg0.conf`). Удаляйте вручную и только после бэкапа.
## Pitfalls
* **Порт 8080 занят** на dev-хосте — наружу публикуется 8180. Меняйте `AWG_DASH_PORT`.
* **`/dev/net/tun` обязателен**: без него entrypoint падает (`fail '/dev/net/tun не проброшен'`).
* **Права на каталоги состояния**: entrypoint делает `chown awg:awg /config /data`;
каталоги создаются на хосте от root — не меняйте владельца на хосте вручную.
* **`docker compose restart` сохраняет тома**; `down -v` — нет. Никогда не используйте
`down -v` на этом стенде: это удалит `/config` и `/data`.
* **Заглушка `api_stub.py`** — только dev: она отвечает 200 на `/api/v1/health` и
маскирует отсутствие API. Не включайте `docker-compose.stub.yml` в staging.
* **netns-стенд вне Docker** требует root: `make test-netns` вернёт код 3, если нет
CAP_NET_ADMIN/CAP_SYS_ADMIN (например, в непривилегированном CI-раннере).
* **netns в контейнере (`make test-netns-ci`, `bash tests/netns/ci.sh`)**: `ip netns exec`
падает (`mount of /sys failed`), харнесс сам переходит на `nsenter`; контракт кодов
`0/1/3/4` действует на уровне контейнера. **make возвращает 2 на любом провале** —
в CI вызывайте `bash tests/netns/ci.sh`, иначе ветки 3 и 4 неразличимы (#56).
* **`--build` без сети**: после мержа #18 `dev-up` собирает образ; если на хосте нет
DNS/доступа к registry, используйте `DEV_SKIP_BUILD=1` (готовый `awg-dash:dev`).