5.6 KiB
5.6 KiB
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 + envTSD_*+ секреты*_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на entrypointtraefikс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, выпуск сертификатов и wildcardtls.domains— не запускалось, деплой не выполнялся. - Не проверялись права сервисного пользователя Selectel (минимальная роль на DNS).