Info
Content

Routing & Load Balancing

Overview

Что происходит с запросами?

Давайте приблизимся к архитектуре Traefik'a и поговорим о том какие компоненты позволяют создавать роуты

Сперва, когда ты запускаешь Traefik, ты определяешь entrypoint'ы (в их наипростейшей форме - номер порта). Далее, подключенный к этим entrypoint'ас, роутер анализирует входящие запросы чтобы увидеть как они матчатся на набор рулов. Если матчатся, то роутер может трансформировать запрос используя фрагменты middleware перед тем как перенаправить его к твоему сервису

Screenshot_2021_02_02-12_49_03-2023-05-19-at-1archataglance.png

Clear Responsibilities

  • Providers - находят сервисы которые живут в твоей инфре
  • Entrypoints - принимают входящий трафик
  • Routers - анализируют запросы
  • Services - перенаправляют запросы на твои сервисы
  • Middlewares - могут изменять запросы или принимать решения на основе запросов

Example with a File Provider

Ниже пример полного конфига для file-провайдера который будет форвардить запросы к http://example.com/whoami/ на сервис доступный на ttp://private/whoami-service/. В процессе Traefik будет производить проверку что пользователь аутентифицирован (используется BasicAuth middleware)

Статическая конфигурация:

entryPoints:
  web:
    # Listen on port 8081 for incoming requests
    address: :8081

providers:
  # Enable the file provider to define routers / middlewares / services in file
  file:
    directory: /path/to/dynamic/conf

Динамическая конфигурация:

# http routing section
http:
  routers:
    # Define a connection between requests and services
    to-whoami:
      rule: "Host(`example.com`) && PathPrefix(`/whoami/`)"
       # If the rule matches, applies the middleware
      middlewares:
      - test-user
      # If the rule matches, forward to the whoami service (declared below)
      service: whoami

  middlewares:
    # Define an authentication mechanism
    test-user:
      basicAuth:
        users:
        - test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/

  services:
    # Define how to reach an existing service on our infrastructure
    whoami:
      loadBalancer:
        servers:
        - url: http://private/whoami-service

Transport configuration

Много чего происходит в подключении между клиентом и Traefik'ом, а также между Traefik'ом и бэкенд серверами
В дополнение несколько параметров позволяют глобально конфигурировать поведение подключений между Traefik'ом и бэкендами. Это достигается за счет секции serversTransport

insecureSkipVerify

Optional, Default=false

insecureSkipVerify выключает проверку сертификата

--serversTransport.insecureSkipVerify=true
rootCAs

Лист CA сертификатов для использования с самосертами

serversTransport:
  rootCAs:
    - foo.crt
    - bar.crt
maxIdleConnsPerHost

Optional, Default=2

Если стоит не ноль, то maxIdleConnsPerHost контролирует максимальное кол-во idle (keep-alive) подключений которые будут поддерживаться per-host

--serversTransport.maxIdleConnsPerHost=7
forwardingTimeouts

Секция forwardingTimeouts о количестве тайм-аутов, относящихся к переадресации запросов на внутренние серверы

forwardingTimeouts.dialTimeout

Optional, Default=30s

dialTimeout - как долго может устанавливаться подключение. Ноль означает отсутствие таймаута

forwardingTimeouts.responseHeaderTimeout

Optional, Default=0s

responseHeaderTimeout если не ноль то задает длительность ожидания ответных заголовков после полной отправки запроса (включая тело запроса). Это время не включает время чтения тела ответа. Ноль означает отсутствие таймаута

forwardingTimeouts.idleConnTimeout

Optional, Default=90s

idleConnTimeout максимальное время жизни idle (keep-alive) подключения пока оно будет оставаться в idle состоянии перед закрытием. Ноль означает отсутствие таймаута

serversTransport:
  forwardingTimeouts:
    dialTimeout: 1s
    responseHeaderTimeout: 1s
    idleConnTimeout: 1s

EntryPoints

Открытие подключений для входящих запросов

Screenshot_2021_02_02-12_49_03-2023-05-19-at-15entrypoints.png

Entrypoints это сетевые входные точки в Traefik. Они определяют порт через который будут приниматься пакеты и то будет это TCP или UDP

Configuration Examples

Port 80 only:

entryPoints:
  web:
   address: ":80"

Мы описали entrypoint который слушает 80 порт и назвали его web


Port 80 & 443:

entryPoints:
  web:
    address: ":80"

  websecure:
    address: ":443"

Описаны два entrypoint'a один называется web, другой websecure
web слушает 80 порт, а websecure 443


UDP на порту 1704:

entryPoints:
  streaming:
    address: ":1704/udp"

Configuration

General

Entrypoint'ы это часть статической конфигурации. Они могут быть заданы через файл или через cli

entryPoints:                               |
  name:                                    |
    address: ":8888" # same as ":8888/tcp" | --entryPoints.name.address=:8888 # same as :8888/tcp
    http2:                                 |
      maxConcurrentStreams: 42             | --entryPoints.name.http2.maxConcurrentStreams=42
    http3:                                 |
      advertisedPort: 8888                 | --entryPoints.name.http3.advertisedport=8888
    transport:                             |
      lifeCycle:                           |
        requestAcceptGraceTimeout: 42      | --entryPoints.name.transport.lifeCycle.requestAcceptGraceTimeout=42
        graceTimeOut: 42                   | --entryPoints.name.transport.lifeCycle.graceTimeOut=42
      respondingTimeouts:                  |
        readTimeout: 42                    | --entryPoints.name.transport.respondingTimeouts.readTimeout=42
        writeTimeout: 42                   | --entryPoints.name.transport.respondingTimeouts.writeTimeout=42
        idleTimeout: 42                    | --entryPoints.name.transport.respondingTimeouts.idleTimeout=42
    proxyProtocol:                         |
      insecure: true                       | --entryPoints.name.proxyProtocol.insecure=true
      trustedIPs:                          |
        - "127.0.0.1"                      | --entryPoints.name.proxyProtocol.trustedIPs=127.0.0.1,192.168.0.1
        - "192.168.0.1"                    |
    forwardedHeaders:                      |
      insecure: true                       | --entryPoints.name.forwardedHeaders.insecure=true
      trustedIPs:                          |
        - "127.0.0.1"                      | --entryPoints.name.forwardedHeaders.trustedIPs=127.0.0.1,192.168.0.1
        - "192.168.0.1"                    |
Address

Адрес определяет порт и опционально хостнейм на котором нужно слушать входящие запросы и пакеты. Он также определяет протокол который нужно использовать (TCP/UDP). Если протокол не указан то по умолчанию используется TCP. Формат следующий:

[host]:port[/tcp|/udp]

Если нужно использовать и TCP и UDP на одном и том же порту, то нужно описать два entrypoint'a

entryPoints:
  tcpep:
   address: ":3179"
  udpep:
   address: ":3179/udp"

Пример указания конкретного айпишника

entryPoints:
  specificIPv4:
    address: "192.168.2.7:8888"
  specificIPv6:
    address: "[2001:db8::1]:8888"
HTTP/2
maxConcurrentStreams

Optional, Default=250

maxConcurrentStreams определяет кол-во одновременных потоков на подключение которые может инициировать клиент. Значение должно быть больше нуля

--entryPoints.name.http2.maxConcurrentStreams=250
HTTP/3
http3

Опция http3 включает протокол HTTP/3 для entrypoint'a. HTTP/3 требует TCP entrypoint, так как HTTP/3 всегда стартует как TCP подключение которое впоследствии будет апгрейднуто до UDP. В основном это тот же entrypoint что и для TLS

Так как HTTP/3 использует UDP, то ты не можешь иметь TCP entrypoint с HTTP/3 на том же порту что и UDP entrypoint. HTTP/3 требует использования TLS, поэтому только роутеры с TLS могут использовать HTTP/3

Так как спецификация HTTP/3 все еще находится в состоянии черновика, то поддержка протокола в Traefik является экспериментальной и должна быть активирована в секции experimental статической конфигурации

experimental:
  http3: true

entryPoints:
  name:
    http3: {}
advertisedPort

http3.advertisedPort описывает какой UDP порт предлагать как HTTP/3 authority. По умолчанию это entypoint порт. Эта опция может быть использована для оверайдинга outhority в заголовке alt-svc, например если публично торчащий порт отличается от того который слушает Traefik

experimental:
  http3: true

entryPoints:
  name:
    http3:
      advertisedPort: 443
Forwarded Headers

Можно сказать Traefik'у доверять информации из X-Forwarded-* заголовков

entryPoints:
  web:
    address: ":80"
    forwardedHeaders:
      trustedIPs:
        - "127.0.0.1/32"
        - "192.168.1.7"
entryPoints:
  web:
    address: ":80"
    forwardedHeaders:
      insecure: true
Transport
respondingTimeouts

respondingTimeouts таймаут для входящих в Traefik запросов. Это опция не имеет эффекта для UDP entrypoint'ов
https://doc.traefik.io/traefik/routing/entrypoints/#respondingtimeouts

transport.respondingTimeouts.readTimeout
Optional, Default=0s

readTimeout задает максимальную продоложительность чтения всего запроса включая тело
Если стоит 0 то лимита нет
Может быть указано в форматах поддерживаемых типом time.ParseDuration. Если юнит не указан то воспринимается как секунды

transport.respondingTimeouts.writeTimeout
Optional, Default=0s

writeTimeout задает таймаут записи ответа
Этот таймаут покрывает время от начала чтения заголовков запроса и до конца записи ответа
Если 0 то лимита нет

transport.respondingTimeouts.idleTimeout
Optional, Default=180s

idleTimeout как долго keep-alive подключение может находиться в состоянии idle Если 0 то лимита нет

entryPoints:
  name:
    address: ":8888"
    transport:
      respondingTimeouts:
        readTimeout: 42
        writeTimeout: 42
        idleTimeout: 42
lifeCycle

Контролирует поведение Traefik'a во время фазы выключения

lifeCycle.requestAcceptGraceTimeout
Optional, Default=0s

Как долго продолжать принимать запросы перед инициацией graceful termination периода (как гласит опция graceTimeOut). Эта опция дает нижележащим балансерам возможность выкинуть Traefik из ротации

Может быть указано в форматах поддерживаемых типом time.ParseDuration. Если юнит не прописан то воспринимается как секунды

Ноль отключает прием запросов в grace period, то есть он будет переходить в grace period сразу

lifeCycle.graceTimeOut
Optional, Default=10s

Задает как долго ждать завершения уже начатых (активных) запросов перед тем как окончательно выключиться

Может быть указано в форматах поддерживаемых типом time.ParseDuration. Если юнит не прописан то воспринимается как секунды

В этот период уже не будут приниматься новые запросы

entryPoints:
  name:
    address: ":8888"
    transport:
      lifeCycle:
        requestAcceptGraceTimeout: 42
        graceTimeOut: 42
ProxyProtocol

https://doc.traefik.io/traefik/routing/entrypoints/#proxyprotocol

HTTP Options

Вся эта секция посвящена только опциям связанных с entrypoint'ами и применимым только к http роутингу

Redirection
entryPoints:
  web:
    address: :80
    http:
      redirections:
        entryPoint:
          to: websecure
          scheme: https

  websecure:
    address: :443
entryPoint

Эта секция удобна для включения постоянного редиректа всех входящих запросов на другой entrypoint

entryPoint.to
Required

Может содержать имя другого entrypoint (websecure) или порт :443

entryPoint.scheme
Optional, Default="https"

Схема цели редиректа (http/https/etc)

entryPoint.permanent
Optional, Default=true

Перманентен ли редирект

entryPoint.priority
Optional, Default=MaxInt32-1 (2147483646)

Приоритет сгенеренного роутера

entryPoints:
  foo:
    http:
      redirections:
        entryPoint:
          priority: 10
          permanent: true
          scheme: https
          to: websecure
Middlewares

Список middlewares которые будут добавляться по умолчанию в список middlewares каждого роутера ассоциированного с этим entrypoint'ом

entryPoints:
  websecure:
    address: ':443'
    http:
      middlewares:
        - auth@file
        - strip@file
TLS

Эта секция о дефолтных настройках TLS которые будут применяться ко всем роутерам ассоциированным с этим entrypoint'ом

Если TLS секция (любое из ее полей) прописано пользователем, то дефолтная конфигурация не применяется вообще

Эта секция конфигурируется точно так же как у HTTP роутеров

entryPoints:
  websecure:
    address: ':443'
    http:
      tls:
        options: foobar
        certResolver: leresolver
        domains:
          - main: example.com
            sans:
              - foo.example.com
              - bar.example.com
          - main: test.com
            sans:
              - foo.test.com
              - bar.test.com

UDP Options

Эта секция посвящена опциям от entrypoint для UDP роутинга

Timeout

Optional, Default=3s

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

--entrypoints.foo.address=:8000/udp
--entrypoints.foo.udp.timeout=10s

Routers

Соединение запросов с сервисами

Screenshot_2021_02_02-12_49_03-2023-05-19-at-19routers.png

Роутер занят направлением входящих запросов в сервисы которые их обработают. В процессе этого роутеры могут использовать middleware для модифицирования запросов перед отправкой их в сервис

Configuration Example

Requests /foo are Handled by service-foo -- Using the File Provider

http:
  routers:
    my-router:
      rule: "Path(`/foo`)"
      service: service-foo

Forwarding all (non-tls) requests on port 3306 to a database service

tcp:
  routers:
    to-database:
      entryPoints:
        - "mysql"
      # Catch every request (only available rule for non-tls routers. See below.)
      rule: "HostSNI(`*`)"
      service: database
## Static configuration
entryPoints:
  web:
    address: ":80"
  mysql:
    address: ":3306"

Configuring HTTP Routers

Символ @ запрещено использовать в именах роутеров

EntryPoints

Если не прописано то роутер будет принимать запросы из всех описанных entrypoint'ов. Если надо ограничить охват то можно прописать опцию entryPoints

http:
  routers:
    Router-1:
      # won't listen to entry point web
      entryPoints:
        - "websecure"
        - "other"
      rule: "Host(`example.com`)"
      service: "service-1"
Rule

Рулы это набор матчеров сконфигурированных значениями которые определяют подпадает ли конкретный запрос под их критерии. Если рулы пройдены, то роутер становится активным, вызывает middleware и потом перенаправляет запрос в сервис

Чтобы указать значение рула используй обратные тики ` или экранированные двойные кавычки \"
Одиночные кавычки не разрешено использовать в качестве значения golang string literals

Примеры:

rule = "Host(`example.com`)"
rule = "Host(`example.com`) || (Host(`example.org`) && Path(`/traefik`))"

Далее таблица с доступными матчерами

Rule Description
Headers(`key`, `value`) Check if there is a key keydefined in the headers, with the value value
HeadersRegexp(`key`, `regexp`) Check if there is a key keydefined in the headers, with a value that matches the regular expression regexp
Host(`example.com`, ...) Check if the request domain (host header value) targets one of the given domains.
HostHeader(`example.com`, ...) Same as Host, only exists for historical reasons.
HostRegexp(`example.com`, `{subdomain:[a-z]+}.example.com`, ...) Match the request domain. See "Regexp Syntax" below.
Method(`GET`, ...) Check if the request method is one of the given methods (GET, POST, PUT, DELETE, PATCH, HEAD)
Path(`/path`, `/articles/{cat:[a-z]+}/{id:[0-9]+}`, ...) Match exact request path. See "Regexp Syntax" below.
PathPrefix(`/products/`, `/articles/{cat:[a-z]+}/{id:[0-9]+}`) Match request prefix path. See "Regexp Syntax" below.
Query(`foo=bar`, `bar=baz`) Match Query String parameters. It accepts a sequence of key=value pairs.
ClientIP(`10.0.0.0/16`, `::1`) Match if the request client IP is one of the given IP/CIDR. It accepts IPv4, IPv6 and CIDR formats.
Priority
Middlewares
Service
TLS
General
options
certResolver
domains

Configuring TCP Routers

General
EntryPoints
Rule
Priority
Middlewares
Services
TLS
General
passthrough
options
certResolver
domains

Configuring UDP Routers

General
EntryPoints
Services

Services

Providers

No Comments
Back to top