6.2 KiB
traefik-selectel-dns
Демон, который создаёт A-записи в Selectel DNS (API v2) для хостов из роутеров Traefik.
Сертификаты выписывает сам Traefik (встроенный dnsChallenge.provider: selectelv2) — кода для этого не нужно.
Почему не плагин Traefik
Плагин (Yaegi) работает внутри цепочки обработки запросов: он не видит создание/удаление роутов
и не должен хранить токен с правом записи в DNS. Отдельный демон читает Traefik API
(/api/http/routers), поэтому одинаково покрывает Docker labels и file-provider.
Как работает
- Раз в
interval(и сразу после событий Docker) читаетGET /api/http/routers. - Из
ruleберёт всеHost(...)у роутеров со статусомenabled(HostRegexp,!Host(...)игнорируются,*.xпропускаются с warning). - Хосты, попадающие в
zonesиз конфига (равны зоне или её поддомен; при вложенных зонах — самая длинная), получают A-записьip/ttl. - Записи, созданные демоном, помечаются
comment: managed-by=traefik-selectel-dns. Меняются/удаляются только они. Существующая A-запись без метки (и имя с CNAME) не трогается — только warning. - Удаление выключено по умолчанию. При
delete.enabled: trueзапись удаляется после того, как роут отсутствует непрерывноdelete.gracePeriod(состояние в памяти; после рестарта отсчёт начинается заново). Роутеры со статусомwarningсчитаются присутствующими. При ошибке Traefik API или пустом списке (после непустого) цикл пропускается и ничего не удаляется.
Настройка
Пример полного стенда: deploy/ (docker-compose.example.yml, traefik.example.yml, config.example.yaml, dynamic/).
- Создайте в Selectel сервисного пользователя с минимальной ролью на DNS проекта.
- Положите креды в файлы секретов (
deploy/secrets/*, не коммитить) — см. комментарий в compose. - Поправьте
zones,ip,traefik.apiURLвconfig.example.yaml; wildcardtls.domains— вtraefik.example.yml. - Для первого запуска включите
dryRun: trueи проверьте логи.
Сборка: docker build -t traefik-selectel-dns . (distroless, non-root, HEALTHCHECK через -healthcheck).
Конфигурация
YAML (-config или TSD_CONFIG), неизвестные поля — ошибка. Переопределение через env:
| YAML | env | По умолчанию |
|---|---|---|
zones |
TSD_ZONES (через запятую) |
обязательно |
ip |
TSD_IP |
обязательно, IPv4 |
ttl |
TSD_TTL |
300 (60..604800) |
interval |
TSD_INTERVAL |
30s |
dryRun |
TSD_DRY_RUN |
false |
traefik.apiURL / .timeout |
TSD_TRAEFIK_API_URL / TSD_TRAEFIK_TIMEOUT |
http://traefik:8080 / 10s |
docker.enabled / .host |
TSD_DOCKER_ENABLED / TSD_DOCKER_HOST |
true / unix:///var/run/docker.sock (tcp:// тоже) |
delete.enabled / .gracePeriod |
TSD_DELETE_ENABLED / TSD_DELETE_GRACE_PERIOD |
false / 10m |
selectel.baseURL / .authURL / .timeout |
TSD_SELECTEL_BASE_URL / _AUTH_URL / _TIMEOUT |
api.selectel.ru/domains/v2, cloud.api.selcloud.ru/identity/v3, 30s |
listen |
TSD_LISTEN |
:9090 (/healthz) |
logLevel / logFormat |
TSD_LOG_LEVEL / TSD_LOG_FORMAT |
info / json |
Секреты — только env (каждая поддерживает суффикс _FILE; одновременно обе — ошибка):
SELECTEL_USERNAME, SELECTEL_PASSWORD, SELECTEL_ACCOUNT_ID, SELECTEL_PROJECT_ID.
Для Traefik (lego) те же значения передаются как SELECTELV2_USERNAME_FILE, SELECTELV2_PASSWORD_FILE, SELECTELV2_ACCOUNT_ID_FILE, SELECTELV2_PROJECT_ID_FILE.
Безопасность
- Секреты не попадают в конфиг, образ и логи; IAM-токен (Keystone) кэшируется в памяти и обновляется заранее.
- Traefik API не публикуется наружу и ограничен
ipAllowListподсетью сетиcontrol; пользовательские контейнеры в неё не подключать. - Docker socket = root на хосте. Демону нужны только события, поэтому в примере используется
docker-socket-proxy(EVENTS=1), а не прямой сокет. Без Docker events демон работает по опросу. - Чужие записи не перезаписываются; удаление выключено по умолчанию.
Ограничения
- Только A-записи, один фиксированный IPv4 для всех хостов; AAAA нет.
- Только
Host(...)с ASCII-именами (IDN — в punycode);HostRegexpи wildcard-хосты не поддерживаются. - Метка владения — exact-match комментария; если её вручную изменить/стереть, запись считается чужой.
- Grace-состояние в памяти; несколько реплик демона одновременно не поддерживаются.
- Поток Docker events без общего таймаута (переподключается при обрыве; страховка — периодический опрос).
- Реальный Selectel API не проверялся (нет кредов) — см. отчёт в
swarm-report/.