Files
traefik-selectel/swarm-report/traefik-selectel-dns-2026-09-21.md
T
vasyanskandClaude Sonnet 5 273cd54415
Build / Tests (push) Successful in 13s
Build / Build image (push) Failing after 15s
Build / Notify on failure (push) Failing after 0s
feat: traefik-selectel-dns — A-записи Selectel по роутам Traefik + CI сборка образа
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-21 21:50:07 +07:00

39 lines
5.6 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.
# traefik-selectel-dns — отчёт (2026-09-21)
## Что сделано
Go-демон `traefik-selectel-dns` (модуль `github.com/realmanual/traefik-selectel`, Go 1.27.1, единственная зависимость — `gopkg.in/yaml.v3`):
- `internal/hostparse` — разбор `Host(...)` (несколько аргументов, `||`, `&&`, кавычки, отрицания `!Host`/`!(...)`, `HostRegexp`/`HostSNI` не считаются), валидация DNS-имён, сопоставление зон (longest match).
- `internal/traefik` — клиент `GET /api/http/routers` с пагинацией (`page`/`per_page`, `X-Next-Page`).
- `internal/selectel` — Keystone-токен (кэш в памяти, обновление за 10 минут до `expires_at`), DNS API v2 (зоны с кэшем id, rrset list/create/PATCH/delete), повтор при 401 со сбросом токена, 404 на delete = успех.
- `internal/reconciler` — create/update/skip-foreign/skip-CNAME/delete-grace/safe-guard, dry-run, цикл с debounce по событиям Docker.
- `internal/dockerevents` — raw HTTP `/events` по unix-сокету или tcp (без docker SDK), переподключение с backoff, недоступность не фатальна.
- `internal/config` (YAML strict + env `TSD_*` + секреты `*_FILE`), `internal/httpx` (ретраи 429/5xx с backoff и Retry-After), `internal/health` (`/healthz`, флаг `-healthcheck`).
- Dockerfile (multi-stage, distroless static nonroot 65532), `.dockerignore`, `deploy/` (compose, traefik.yml, config, dynamic/, whoami-пример), README.
Проверено: `go vet ./...` — чисто; `go test -race ./...` — 79 тестов проходят; `docker build` собирается, образ запускается (`-version`), USER 65532; `docker compose config -q` валиден.
## Сверка с документацией
- DNS API v2: base URL `https://api.selectel.ru/domains/v2` (docs.selectel.ru/api/urls), `X-Auth-Token` (по исходникам lego selectelv2), пути `/zones`, `/zones/{id}/rrset[/{rrset_id}]`, тело `{name,type,ttl,records:[{content,disabled}],comment}`, PATCH — `ttl`, `records`, `comment`; имена — FQDN с точкой.
- Токен: `POST https://cloud.api.selcloud.ru/identity/v3/auth/tokens`, токен в заголовке `X-Subject-Token`, срок 24 ч.
- Переменные lego `selectelv2`: `SELECTELV2_USERNAME/PASSWORD/ACCOUNT_ID/PROJECT_ID` (+`_FILE`) — сверено через context7 (/go-acme/lego).
## Принятые решения / отступления
- Роутеры со статусом `warning` не создают записи, но считаются «присутствующими» (не запускают grace-удаление) — чтобы временный warning не удалил запись.
- Список rrset читается целиком (все типы) и фильтруется на клиенте: формат query-параметра `rrset_types` в доке не уточнён; так же позволяет обнаружить CNAME-конфликт.
- Зона ищется по `filter` + точное сравнение имени на клиенте (семантика filter не описана).
- Traefik API: вместо `api.insecure: true` — роутер `api@internal` на entrypoint `traefik` с `ipAllowList` подсети control, т.к. Traefik также сидит в сети proxy с пользовательскими контейнерами. Docker events демон получает через `docker-socket-proxy`, а не прямой сокет.
- Добавлены сверх ТЗ: `dryRun`, `-healthcheck`, детекция CNAME-конфликта.
## Риски
- Остаточный: подсеть `172.30.250.0/24` дублируется в compose и dynamic/api-internal.yml — при расхождении демон получит 403.
- Docker socket, смонтированный в Traefik (штатно для Docker provider) — root-эквивалент; в примере ro-монтирование не ограничивает API.
- POST при 5xx может повториться (возможен дубль) — reconcile идемпотентен, но при дубле API вернёт ошибку до следующего цикла.
- Метка владения — exact-match комментария (до 255 символов ок).
- Образы `traefik:v3`, `docker-socket-proxy:latest`, `golang:1.27-alpine`, distroless — не закреплены по digest; в проде закрепить.
- Имя образа `ghcr.io/realmanual/traefik-selectel-dns` в compose — заглушка.
## Не проверено
- Реальный Selectel API (нет кредов): формат ответа Keystone (`expires_at`; при ошибке разбора берётся 1 час), точное поведение `filter` у зон, поведение POST на дубликат, признак конца пагинации (используется `len(result) < limit`), значение `managed_by` у записей, созданных через API.
- Реальный Traefik (структура роутеров, пагинация, статус `warning`), реальное Docker events, выпуск сертификатов и wildcard `tls.domains` — не запускалось, деплой не выполнялся.
- Не проверялись права сервисного пользователя Selectel (минимальная роль на DNS).