Skip to content

Traefik

Traefik — обратный прокси и терминатор TLS для Meduza. Он автоматически обнаруживает сервисы, зарегистрированные в каталоге сервисов Nomad, и строит правила маршрутизации на основе их тегов — без ручных конфигурационных файлов.

Как работает обнаружение сервисов

Traefik работает как системная задача в кластере Nomad и настроен на использование Nomad в качестве провайдера. Процесс обнаружения:

mermaid
sequenceDiagram
    participant Nomad
    participant Traefik
    participant LetsEncrypt as Let's Encrypt
    participant Client

    Nomad->>Traefik: Service registered with traefik.* tags
    Traefik->>Traefik: Parse tags → build router + service
    Traefik->>LetsEncrypt: Request TLS certificate for domain
    LetsEncrypt-->>Traefik: Certificate issued
    Client->>Traefik: HTTPS request (Host: app.meduza.io)
    Traefik->>Traefik: Match router rule → resolve backend
    Traefik->>Nomad: Forward to healthy task allocation

Когда Nomad-задача деплоится с тегами сервисов traefik.*, Traefik автоматически подхватывает их и:

  1. Создаёт роутер с указанным правилом Host()
  2. Привязывает его к точке входа websecure (порт 443)
  3. Запрашивает TLS-сертификат у Let's Encrypt, если он ещё не закеширован
  4. Создаёт сервис (балансировщик нагрузки), указывающий на адрес и порт задачи

TIP

Перезапуск Traefik не требуется при деплое новых сервисов или обновлении существующих. Обнаружение полностью динамическое.

Точки входа

Traefik настроен с двумя точками входа:

Точка входаПортНазначение
web80HTTP — перенаправляет на HTTPS
websecure443HTTPS — весь продакшн-трафик

Точка входа web настроена на постоянное перенаправление всего трафика на websecure:

yaml
# traefik static configuration (excerpt)
entryPoints:
  web:
    address: ":80"
    http:
      redirections:
        entryPoint:
          to: websecure
          scheme: https
          permanent: true
  websecure:
    address: ":443"

Маршрутизация на основе тегов

Маршрутизация полностью настраивается через теги сервисов Nomad. Вот паттерн, используемый для всех фронтенд-сервисов Meduza:

hcl
service {
  name     = "hub-${var.env}-frontend"
  port     = "http"
  provider = "nomad"

  tags = [
    "traefik.enable=true",
    "traefik.http.routers.hub-${var.env}-frontend.rule=Host(`${var.domain}`)",
    "traefik.http.routers.hub-${var.env}-frontend.entrypoints=websecure",
    "traefik.http.routers.hub-${var.env}-frontend.tls.certresolver=letsencrypt",
  ]
}

Расшифровка тегов

Каждый тег соответствует директиве конфигурации Traefik:

ТегНазначение
traefik.enable=trueУказывает Traefik подхватить этот сервис (сервисы без этого тега игнорируются)
traefik.http.routers.NAME.rule=Host(...)Сопоставление запросов, у которых заголовок Host равен указанному домену
traefik.http.routers.NAME.entrypoints=websecureПрослушивание только на HTTPS точке входа (порт 443)
traefik.http.routers.NAME.tls.certresolver=letsencryptИспользование Let's Encrypt для автоматического выпуска и обновления сертификатов

WARNING

Имя роутера (например, hub-prod-frontend) должно быть уникальным среди всех сервисов. Если два сервиса используют одно имя роутера, Traefik объединит их конфигурации непредсказуемо. Всегда включайте окружение в имя.

Соглашение об именовании

Имя роутера следует паттерну: {service}-{env}-{role}

ОкружениеИмя роутераДомен
prodhub-prod-frontendПродакшн-домен
stagehub-stage-frontendСтейджинг-домен
devhub-dev-frontendDev-домен

TLS с Let's Encrypt

Traefik автоматически выпускает и обновляет TLS-сертификаты, используя протокол ACME с Let's Encrypt.

Конфигурация

yaml
# traefik static configuration (excerpt)
certificatesResolvers:
  letsencrypt:
    acme:
      email: admin@meduza.io
      storage: /data/acme.json
      httpChallenge:
        entryPoint: web

Как это работает

  1. Когда новый роутер ссылается на certresolver=letsencrypt, Traefik проверяет, есть ли действительный сертификат в acme.json.
  2. Если нет, инициируется HTTP-01 challenge: Let's Encrypt отправляет запрос на http://<domain>/.well-known/acme-challenge/<token>.
  3. Traefik автоматически отвечает на challenge через точку входа web.
  4. После валидации сертификат сохраняется в acme.json и используется для всех последующих HTTPS-запросов.
  5. Traefik обновляет сертификаты автоматически до истечения срока (обычно за 30 дней до 90-дневного срока).

TIP

Файл acme.json содержит приватные ключи. Он должен быть сохранён на томе хоста и иметь права 600. Потеря этого файла означает, что все сертификаты будут запрошены заново при перезапуске.

Балансировка нагрузки

Когда Nomad-задача имеет несколько аллокаций (например, backend_replicas = 2), Traefik автоматически балансирует нагрузку между всеми здоровыми экземплярами. Стратегия по умолчанию — взвешенный round-robin.

mermaid
flowchart LR
    Client -->|HTTPS| Traefik
    Traefik -->|round-robin| A1["Backend Alloc 1\n:dynamic-port"]
    Traefik -->|round-robin| A2["Backend Alloc 2\n:dynamic-port"]

Traefik маршрутизирует только на аллокации, чьи проверки здоровья Nomad проходят успешно. Если аллокация становится нездоровой, она автоматически удаляется из пула балансировщика.

Отладка

Проверка Traefik Dashboard

SSH-туннель к Traefik Dashboard:

bash
ssh -L 8080:localhost:8080 user@kvm-host

Затем откройте http://localhost:8080 в браузере. Dashboard показывает:

  • Все обнаруженные роутеры и их правила
  • Все сервисы и их статус здоровья
  • Статус TLS-сертификатов
  • Конфигурацию точек входа

Проверка роутеров через API

bash
# List all HTTP routers
curl -s http://localhost:8080/api/http/routers | jq .

# Check a specific router
curl -s http://localhost:8080/api/http/routers/hub-prod-frontend@nomad | jq .

Типичные проблемы

СимптомВероятная причинаРешение
404 на валидном доменеТеги сервиса отсутствуют или несовпадение имени роутераПроверьте nomad job inspect на корректность тегов
Ошибка TLS-сертификатаНе прошёл ACME challenge (порт 80 заблокирован?)Убедитесь, что порт 80 открыт и точка входа web работает
502 Bad GatewayБэкенд не работает или проверка здоровья падаетПроверьте nomad alloc status для целевого сервиса
Запросы уходят не в тот сервисДублирование имён роутеров между задачамиУбедитесь, что имена роутеров содержат ${var.env}

Дополнительное чтение

  • Nomad — где определяются теги сервисов
  • Consul — управление конфигурацией для сервисов, к которым Traefik маршрутизирует трафик

Документация по инфраструктуре