Files
SergObsidian/WORK & PROJECTS/Mol/Серверы/PROXY_PASS/Traefik config.md
2025-05-13 18:32:31 +05:00

26 KiB
Raw Blame History

Отличный вопрос! Давай сравним, как реализовать ту же задачу в Traefik, и посмотрим, проще ли это будет по сравнению с Angie.


🎯 Цель (повторение)

Нужно организовать систему обратного прокси, где:

  • Пользователи разделены на группы:

    • public — публичный доступ ко всем общедоступным сайтам.
    • internal — сотрудникам доступны внутренние сервисы (git, jira и т.д.).
    • client-X — клиенты с доступом только к своему поддомену (client1.site.com, client2.site.com).
  • Каждая группа имеет свои IP-подсети.

  • Каждый домен/поддомен имеет список разрешённых групп.

  • Конфиги должны обновляться динамически без перезапуска.

  • Желательно наличие GUI и API управления.


Вывод сразу: Traefik лучше подходит для этой задачи

Почему?

Функция Traefik / Angie /
ACL по IP
Группы пользователей через middleware через allow/deny
Динамическая конфигурация через API или файл через /control
Поддержка GUI встроенный dashboard (нужно внешнее)
Простота автоматизации ⚠️ сложнее
Интеграция с Lets Encrypt ⚠️ нужно допилить
Удобство масштабирования

🔧 Как реализовать в Traefik

1. Базовая структура конфигурации

Traefik использует два типа конфигов:

  • traefik.yml — статическая часть (порт, провайдеры, логирование и т.п.)
  • dynamic_conf.yml — динамическая часть (маршруты, middleware, TLS и т.п.)

Также можно управлять через REST API, но начнём с файла.


2. Middleware для групп доступа

В Traefik есть мощная система middleware, которую мы будем использовать для контроля доступа по IP.

Пример: определяем middleware для каждой группы

http:
  middlewares:
    public-access:
      ipWhiteList:
        sourceRange:
          - "0.0.0.0/0" # все IP

    internal-access:
      ipWhiteList:
        sourceRange:
          - "192.168.1.0/24"
          - "10.10.0.0/16"

    client1-access:
      ipWhiteList:
        sourceRange:
          - "203.0.113.0/24"

3. Роуты с указанием middleware

Каждому роуту можно указать, какие middleware применять.

Пример: маршрут для site1.com

http:
  routers:
    site1-router:
      rule: "Host(`site1.com`, `www.site1.com`)"
      entryPoints:
        - web
      service: site1-service
      middlewares:
        - public-access
        - internal-access

Пример: маршрут для git.site1.com

http:
  routers:
    git-router:
      rule: "Host(`git.site1.com`)"
      entryPoints:
        - web
      service: git-service
      middlewares:
        - internal-access

Пример: маршрут для client1.site.com

http:
  routers:
    client1-router:
      rule: "Host(`client1.site.com`)"
      entryPoints:
        - web
      service: client1-service
      middlewares:
        - client1-access

4. Сервисы (бэкенды)

Определяешь бэкенд для каждого сайта:

http:
  services:
    site1-service:
      loadBalancer:
        servers:
          - url: http://192.168.10.10:8080

    git-service:
      loadBalancer:
        servers:
          - url: http://192.168.10.11:3000

    client1-service:
      loadBalancer:
        servers:
          - url: http://192.168.20.10:8000

5. Динамическое обновление конфига

Можно использовать:

А. Файл с динамическим конфигом

Traefik следит за изменениями в файле и применяет их автоматически.

Пример запуска:

providers:
  file:
    filename: /etc/traefik/dynamic_conf.yml
    watch: true

При изменении dynamic_conf.yml — конфиг применяется без перезагрузки!

Б. REST API

Если хочешь полностью управлять через API, можешь использовать Traefik Pilot или свой микросервис.

Пример добавления маршрута через API:

curl -X POST "http://traefik:8080/api/http/routers" \
     -H "Content-Type: application/json" \
     -d '{
           "name": "client2-router",
           "rule": "Host(`client2.site.com`)",
           "service": "client2-service",
           "entryPoints": ["web"],
           "middlewares": ["client2-access"]
         }'

6. Генерация конфигов

Как и в случае с Angie, можно написать небольшой генератор конфигов, который:

  • Получает данные о новом клиенте.
  • Создаёт middleware с его IP-диапазоном.
  • Создаёт новый роут.
  • Обновляет dynamic_conf.yml.

Или делает всё через API.


7. Dashboard (GUI)

Traefik предоставляет встроенный веб-интерфейс по адресу http://localhost:8080.

Там ты увидишь:

  • Все маршруты,
  • Сервисы,
  • Middleware,
  • Состояние бэкендов.

🔄 Автоматизация всего процесса

Ты можешь создать:

  • API-сервис, принимающий запросы на добавление клиентов/групп.
  • Шаблонизатор, генерирующий YAML или JSON.
  • Систему хранения правил (например, PostgreSQL или Redis).
  • Синхронизацию с файлом или API Traefik.

🔐 Как работает проверка доступа?

  1. Запрос приходит в Traefik.
  2. Traefik проверяет IP клиента через middleware ipWhiteList.
  3. Если IP не в списке — возвращает 403 Forbidden.
  4. Иначе — направляет запрос на нужный бэкенд.

📦 Пример структуры проекта

traefik/
├── traefik.yml              # статический конфиг
├── dynamic_conf.yml         # динамические маршруты и middleware
└── data/
    └── clients/             # шаблоны или скрипты для клиентов

🎯 Общая цель

Ты хочешь реализовать систему, где:

  1. Клиенты добавляются/удаляются автоматически из внешней БД.
  2. Правила доступа пересоздаются регулярно, оставляя только актуальные.
  3. Скорость обработки не критична, но важно понимать, как поведёт себя система при росте числа правил.

Как это сделать в Traefik

1. Механизм хранения правил

В Traefik есть 2 основных способа управления конфигом:

Способ Подходит для динамических правил? Простота интеграции
Файл dynamic_conf.yml
REST API ⚠️ требует кода

Рекомендация:

Используй файл с динамическим конфигом (file provider) — он проще в управлении, особенно если ты хочешь периодически перезаписывать его целиком на основе данных из БД.


2. Интеграция с внешней БД

Шаги:

  1. Периодически запускай скрипт (например, раз в час или по cron):

    • Выбираешь из БД список активных клиентов.
    • Для каждого клиента генерируешь middleware (ACL) и router (маршрут).
    • Перезаписываешь файл dynamic_conf.yml.
  2. Traefik сам применяет изменения (если watch: true).

Пример структуры файла dynamic_conf.yml:

http:
  middlewares:
    client1-access:
      ipWhiteList:
        sourceRange:
          - "203.0.113.0/24"
    client2-access:
      ipWhiteList:
        sourceRange:
          - "198.51.100.0/24"

  routers:
    client1-router:
      rule: "Host(`client1.example.com`)"
      service: client1-service
      middlewares:
        - client1-access
    client2-router:
      rule: "Host(`client2.example.com`)"
      service: client2-service
      middlewares:
        - client2-access

  services:
    client1-service:
      loadBalancer:
        servers:
          - url: http://192.168.20.10:8080
    client2-service:
      loadBalancer:
        servers:
          - url: http://192.168.20.20:8080

🧪 Пример нагрузки (гипотетический)

Конфигурация Запросов в секунду (RPS)
Traefik + 1000 клиентов ~80009000 RPS
Angie + 1000 клиентов ~1000011000 RPS
Traefik + простой прокси (без ACL) ~12000 RPS
Angie + простой прокси (без ACL) ~14000 RPS

🔄 Рекомендуемая архитектура

[База данных] → [Генератор dynamic_conf.yml] → [Traefik]
  1. База данных — хранит список клиентов, их домены и IP-подсети.
  2. Генератор — скрипт (Python, Go и т.п.), который берёт данные из БД и генерирует YAML.
  3. Traefik — читает файл и применяет правила без перезапуска.

Можно ли разнести конфигурацию общего доступа + сотрудников и клиентов?

Да, и это даже рекомендуется!

Разделение конфигов позволяет:

  • Упростить поддержку.
  • Лучше управлять обновлениями.
  • Изолировать статические правила от динамических.

🛠️ Как это сделать в Traefik?

Traefik поддерживает множественные файловые провайдеры, что позволяет загружать несколько YAML-файлов независимо.

Пример структуры:

traefik/
├── traefik.yml                # основной статический конфиг
├── dynamic-common.yml         # маршруты и middleware для public/internal
└── dynamic-clients.yml        # маршруты и middleware для клиентов

В traefik.yml указываешь:

providers:
  file:
    directory: /etc/traefik/dynamic
    watch: true

Traefik автоматически загрузит все .yml из этой папки.


Пример dynamic-common.yml (для всех):

http:
  middlewares:
    public-access:
      ipWhiteList:
        sourceRange:
          - "0.0.0.0/0"

    internal-access:
      ipWhiteList:
        sourceRange:
          - "192.168.1.0/24"
          - "10.10.0.0/16"

  routers:
    site1-router:
      rule: "Host(`site1.com`, `www.site1.com`)"
      service: site1-service
      middlewares:
        - public-access
        - internal-access

    git-router:
      rule: "Host(`git.site1.com`)"
      service: git-service
      middlewares:
        - internal-access

Пример dynamic-clients.yml (динамически обновляется):

http:
  middlewares:
    client1-access:
      ipWhiteList:
        sourceRange:
          - "203.0.113.0/24"

    client2-access:
      ipWhiteList:
        sourceRange:
          - "198.51.100.0/24"

  routers:
    client1-router:
      rule: "Host(`client1.site.com`)"
      service: client1-service
      middlewares:
        - client1-access

    client2-router:
      rule: "Host(`client2.site.com`)"
      service: client2-service
      middlewares:
        - client2-access

  services:
    client1-service:
      loadBalancer:
        servers:
          - url: http://192.168.20.10:8080

    client2-service:
      loadBalancer:
        servers:
          - url: http://192.168.20.20:8080

🔄 Обновление только клиентской части

Поскольку файлы разделены, можно:

  • Часто обновлять только dynamic-clients.yml (например, ежечасно) без затрагивания остальной конфигурации.
  • Не трогать dynamic-common.yml, если нет изменений в общих правилах.

📦 Полезная архитектура

[База данных] → [Генератор dynamic-clients.yml] ↔ [Traefik]
                        ↓
               [API для других сервисов]
  • База данных — хранит клиентов, группы, IP.
  • Генератор — создаёт/обновляет dynamic-clients.yml.
  • Traefik — применяет конфиг без перезагрузки.
  • Внешний API — даёт доступ к данным о клиентах (в т.ч. IP-диапазонам).

Отличный и важный вопрос! Давай разберём, какие требования к железу будут у Traefik, если:

  • Он будет работать вместе с:
    • UFW (брандмауэр),
    • Prometheus (мониторинг),
    • Grafana (визуализация),
  • И в будущем ожидается нагрузка до 20 000 RPS (запросов в секунду),
  • Нужно понять: что важнее — CPU или RAM?
  • А также: можно ли логировать подключения и собирать метрики для Prometheus

🧮 1. Требования к серверу

Traefik написан на Go, работает быстро и эффективно, но при высокой нагрузке требует определённых ресурсов.

🔁 Примерная производительность Traefik (на одном ядре):

Запросы/сек RAM (примерно) CPU (ядро ~Xeon E5)
5 000 300500 MB ~0.4 ядра
10 000 600800 MB ~0.7 ядра
20 000 11.5 GB ~1.21.5 ядра

Это оценка для простого reverse proxy без TLS, сложных middleware, WAF и т.п.


🖥️ Рекомендуемая конфигурация для 20 000 RPS + дополнительные сервисы

Компонент Рекомендация
CPU 46 ядер (минимум), лучше 8
RAM 46 ГБ
Диск SSD, 2040 ГБ
ОС Linux (Debian, Ubuntu Server)
Сеть 1 Гбит/с минимум

Если нагрузка будет расти постепенно, можно начать с 24 ядер и 24 ГБ RAM, масштабируя дальше при необходимости.


💡 Что важнее: RAM или CPU?

Ответ: и то, и другое важно, но первым ограничителем станет CPU

  • RAM обычно расходуется не очень много (~11.5 ГБ при 20K RPS).
  • CPU становится бутылочным горлышком из-за обработки маршрутов, middleware, шифрования TLS (если есть), проверок IP, генерации логов и т.п.

📊 2. Логирование и мониторинг через Prometheus

Traefik имеет встроенную поддержку метрик Prometheus, а также позволяет логировать запросы.

Включить экспорт метрик Prometheus:

Добавь в traefik.yml:

metrics:
  prometheus:
    addRoutersLabels: true
    addServicesLabels: true
    entryPoint: metrics

И открой соответствующий entryPoint:

entryPoints:
  metrics:
    address: ":8082"

Теперь ты можешь забирать метрики по адресу:
👉 http://<traefik>:8082/metrics

Примеры доступных метрик:

  • traefik_http_requests_total{status, method, router}
  • traefik_http_in_flight_requests
  • traefik_backend_requests_total
  • traefik_router_requests_total

📝 Включить логирование запросов:

Добавь в traefik.yml:

accessLog:
  filePath: "/var/log/traefik/access.log"
  format: "json" # или "common", "jsonWithTime"

Можно дополнительно отправлять логи в Loki, Fluentd, ELK и т.д.


📈 Пример сбора данных в Prometheus + Grafana

  1. Prometheus сканирует /metrics у Traefik.
  2. Grafana строит дашборды:
    • Запросы в секунду,
    • Коды ответов (2xx, 4xx, 5xx),
    • Время отклика,
    • Нагрузка на конкретные роутеры и сервисы.

Выводы

Пункт Рекомендация
Минимальный CPU 4 ядра (начало), 8 комфортно
Минимальный RAM 4 ГБ
Диск SSD, 20+ ГБ
Что важнее CPU
Логирование Да, через accessLog
Мониторинг через Prometheus Да, встроено
Можно ли всё запустить на одном сервере Да, через Docker или Kubernetes
Как масштабироваться Горизонтально: добавление ещё Traefik-нод (в кластере)

Отлично, давай разберём конкретный сценарий:

Ты хочешь:

  • Добавить новый поддомен (например, client1.example.com),
  • Чтобы Traefik автоматически получил для него TLS-сертификат через HTTP-01 чаллендж,
  • Чтобы домен работал по HTTPS,
  • А внутрь сети проксировался на бэкенд в подсети (например, http://192.168.10.10:8080),
  • И всё это — без ручного участия после добавления конфига.

Что нужно сделать

1. Настроить статический конфиг (traefik.yml)

entryPoints:
  web:
    address: ":80"
  websecure:
    address: ":443"

providers:
  file:
    filename: /etc/traefik/dynamic_conf.yml
    watch: true

certificatesResolvers:
  myresolver:
    acme:
      email: admin@example.com
      storage: acme.json
      httpChallenge:
        entryPoint: web

📌 Важные моменты:

  • myresolver — это имя resolver'а, которое будем использовать в динамическом конфиге.
  • storage: acme.json — файл, где будут храниться сертификаты.
  • httpChallenge.entryPoint: web — указывает, что проверка будет идти через порт 80.

2. Добавить динамический маршрут в dynamic_conf.yml

http:
  routers:
    client1-router:
      rule: "Host(`client1.example.com`)"
      service: client1-service
      entryPoints:
        - websecure
      tls:
        certResolver: myresolver

  services:
    client1-service:
      loadBalancer:
        servers:
          - url: http://192.168.10.10:8080

🔍 Что здесь происходит:

  • При запросе https://client1.example.com:
    • Traefik проверяет, есть ли уже выданный сертификат.
    • Если нет — запрашивает его у Lets Encrypt.
    • Для проверки прав на домен — создаёт временный маршрут //.well-known/acme-challenge/....
    • После успешной проверки — сохраняет сертификат в acme.json.
    • Запрос перенаправляется на внутренний сервер http://192.168.10.10:8080.

3. Как работает HTTP-челлендж?

Lets Encrypt делает GET-запрос:

GET http://client1.example.com/.well-known/acme-challenge/<токен>

Traefik:

  • Автоматически отвечает на этот запрос,
  • Не требует дополнительных правил,
  • Работает без участия пользователя.

⚠️ Убедись, что порт 80 открыт и доступен извне (Let's Encrypt должен видеть твой сервер).


4. Файл acme.json

Это ключевой файл, в котором Traefik хранит:

  • Приватные ключи,
  • Сертификаты,
  • Сроки действия,
  • Информацию о доменах.

Создай его и установи права:

touch /etc/traefik/acme.json
chmod 600 /etc/traefik/acme.json

🧩 Как работает вся система?

  1. Ты добавляешь новый поддомен в dynamic_conf.yml
  2. Traefik обнаруживает изменение (если включен watch: true)
  3. Запрашивает сертификат у Lets Encrypt
    • Через HTTP-чаллендж (порт 80),
    • Проверяет владение доменом,
    • Получает сертификат.
  4. Начинает обслуживать сайт по HTTPS
  5. Проксирует запросы во внутреннюю сеть
  6. Автоматически обновляет сертификат за 7 дней до истечения

📋 Пример полной структуры файлов

/etc/traefik/
├── traefik.yml         # основной статический конфиг
├── dynamic_conf.yml    # динамические маршруты
├── acme.json           # хранилище сертификатов

📈 Полезные советы

Задача Совет
Обновление сертификатов Происходит автоматически каждые 24 часа
Проверка сертификатов Открой Traefik Dashboard → раздел HTTPS > Certificates
Лимиты Let's Encrypt Не более 300 новых сертификатов в день на один домен
Избегать блокировок Не делай много ошибочных запросов
Бэкапы Регулярно бэкапь acme.json