SSD Nodes Learn
Руководства Matt ConnorАвтор: Matt Connor · Обновлено 2026-07-24

Миграция Traefik v2 на v3: основные изменения

Узнайте, почему Traefik v3 не запускается при наличии swarmMode или pilot в static config. Исправьте ошибку несовместимых опций и обновите правила роутера.

Отличия между Traefik v2 и v3

Миграция с Traefik v2 на v3 в основном заключается в переименовании компонентов. Известное изменение — middleware ipWhiteList теперь называется ipAllowList. Помимо этого, в v3 ужесточен синтаксис правил роутера (функция PathPrefix утратила возможности использования регулярных выражений, некоторые матчеры переименованы или удалены). Также удалены некоторые провайдеры и опции. Остальные функции работают без изменений: entrypoints, настройка сертификатов ACME, рабочий процесс с Docker labels и ваш acme.json сохраняются. В v3 также добавлен режим совместимости, который поддерживает синтаксис правил v2. Это позволяет сначала обновить бинарный файл, а затем переписывать правила для каждого сервиса по отдельности, вместо того чтобы делать это за один рискованный вечер.

В данном руководстве используется настройка Docker Compose на основе labels из руководства по реверс-прокси Traefik. Та страница написана для v3; данная страница предназначена для систем, где все еще используется тег traefik:v2.

Переименования и удаления

  • ipWhiteList теперь называется ipAllowList для middleware HTTP и TCP. Параметры внутри не изменились, поэтому sourcerange сохраняет свое значение. Текущие версии v3, включая v3.5, все еще принимают старое имя как устаревший псевдоним (deprecated alias) и продолжают применять список настроек. Это переименование не приведет к сбоям. Тем не менее, выполните переименование: псевдоним будет удален, и он исчезнет из списка устаревших без уведомлений.
  • providers.docker.swarmMode=true удален. Swarm теперь использует собственный провайдер, настроенный как providers.swarm.endpoint.
  • Раздел pilot полностью удален.
  • experimental.http3 удален. HTTP/3 теперь включается непосредственно на entrypoint.
  • tls.caOptional удален из провайдеров и из middleware forwardAuth.
  • Провайдеры метрик InfluxDB v1, Rancher и Marathon удалены.
  • Трассировка перенесена в OpenTelemetry. Специализированные бэкенды трассировки, включая интеграции с Jaeger и Zipkin, удалены; вместо них v3 экспортирует OTLP (протокол OpenTelemetry).
  • Устаревшие опции ssl* внутри middleware headers (sslRedirect, sslHost и другие) удалены. Их заменили перенаправления на entrypoint и middleware redirectScheme.

Эти удаления важнее, чем кажется, так как Traefik не запустится, если в статическом конфигуреции содержится неизвестная ему опция. Лишняя строка pilot или swarmMode остановит контейнер при загрузке с сообщением об ошибке incompatible deprecated static option found, указывающим на эту строку; если же опция вообще неизвестна Traefik (опечатка или tls.caOptional), возникнет ошибка field not found. Очистите статический конфиг перед обновлением тега образа.

Если имя middleware действительно неизвестно Traefik (опечатка или имя, которое было удалено, а не заменено псевдонимом), ошибка проявляется иначе: роутер, ссылающийся на него, загружается с ошибкой вместо создания маршрута, в dashboard он помечается, а API возвращает middleware "offce@docker" does not exist. Запросы к этому hostname вернут 404, так как роутер не был создан. Обратите внимание, что ipwhitelist НЕ относится к этой категории в текущей v3: он сохраняется как устаревший псевдоним, поэтому непереименованный label продолжит работать без ошибок.

Изменения синтаксиса правил

Правила определяют логику перенаправления. Изменения в v3:

  • Значения внутри матчеров теперь должны быть заключены в обратные кавычки (backticks). v2 допускал использование двойных кавычек; в v3 это недопустимо, поэтому Host("app.example.com") необходимо заменить на Host(app.example.com).
  • PathPrefix больше не поддерживает регулярные выражения или плейсхолдеры в стиле {id}. Правило из v2, например PathPrefix(/api/{version:v[0-9]+}), должно быть преобразовано в матчер PathRegexp с использованием синтаксиса регулярных выражений Go.
  • Теперь матчеры принимают только одно значение. v2 позволял использовать Host(app.example.com,www.example.com); в v3 необходимо использовать Host(app.example.com) || Host(www.example.com). Исключения составляют Header, HeaderRegexp, Query и QueryRegexp — они по-прежнему принимают имя и значение.
  • Headers и HeadersRegexp переименованы в Header и HeaderRegexp.
  • HostHeader удален. Используйте Host, который в v3 выполняет те же функции.
  • Добавлены два новых матчера: QueryRegexp и ClientIP для сопоставления IP-адреса клиента внутри правила.

Положительный момент: обычное правило Host(app.example.com), записанное с использованием обратных кавычек, уже является валидным синтаксисом v3. Большинство простых конфигураций Compose используют именно такой формат, поэтому в большинстве случаев правила не потребуют правок при миграции.

Проверьте ваши метки перед началом

Вы можете оценить объем миграции с помощью одного поиска. Любое критическое изменение меток создает паттерн, который может найти grep:

grep -rnE 'ipwhitelist|HostHeader|Headers\(|PathPrefix\(`[^`]*\{|Host\(`[^`]*`,' docker-compose*.yml

Каждое совпадение — это одна строка для редактирования. ipwhitelist заменяется на ipallowlist. HostHeader заменяется на Host. Headers заменяется на Header. Плейсхолдер {...} внутри PathPrefix заменяется на матчер PathRegexp. Запятая внутри Host() заменяется на два матчера Host(), соединенных через ||. Если совпадений нет, ваши метки уже соответствуют синтаксису v3. В этом случае объем миграции ограничивается статической конфигурацией и тегом образа.

Что остается без изменений

Точки входа и их перенаправление с HTTP на HTTPS, ACME-резолверы с обоими типами проверок, exposedByDefault, метки роутера и сервиса, loadbalancer.server.port, а также панель управления работают в v3 так же, как в v2. Сертификаты также сохраняются, так как v3 считывает те же данные в acme.json, которые записывала v2. Тем не менее, перед началом работы сделайте резервную копию файла; если при откате версии этот файл будет утерян, вы сразу столкнетесь с ограничением Let's Encrypt на дубликаты сертификатов:

cp ./letsencrypt/acme.json ./letsencrypt/acme.json.v2-backup

Путь миграции

Шаг 1: зафиксируйте текущую версию. Замените любой тег traefik:latest или traefik:v2 на точную версию, которую вы используете (например, traefik:v2.11), и выполните commit всей директории compose в git. Каждый последующий шаг можно будет отменить с помощью checkout. Если вы еще не привыкли пересоздавать отдельные сервисы с помощью docker compose up -d <service>, базовое руководство по Docker Compose содержит описание операций, на которых основана эта миграция.

Шаг 2: очистите статическую конфигурацию и включите режим совместимости. Удалите все параметры, которые были удалены в v3 (pilot, swarmMode, tls.caOptional, experimental.http3), затем укажите v3 обрабатывать правила как синтаксис v2 по умолчанию. В traefik.yml:

core:
  defaultRuleSyntax: v2

Или используйте флаг в списке compose command:: --core.defaultRuleSyntax=v2. Режим совместимости относится только к синтаксису правил. Он не возвращает удаленные параметры и не переименовывает middleware автоматически.

Шаг 3: подготовьте переименование middleware. Найдите в ваших compose-файлах старые названия: grep -rn ipwhitelist docker-compose*.yml. Измените каждый label ipwhitelist на ipallowlist, но не применяйте изменения сразу, так как нового названия не существует в v2. Эти правки должны быть применены одновременно с переключением на следующем шаге. (Если вы пропустите одно имя, текущая v3 все равно примет старое имя как устаревший псевдоним, поэтому список будет продолжать работать; исправьте это при следующем проходе, а не в 2 часа ночи.)

Шаг 4: измените тег образа. Установите для Traefik образ текущей версии v3 (на момент написания — traefik:v3.5), затем:

docker compose up -d
docker compose logs -f traefik

Поскольку режим совместимости включен, ваши правила v2 продолжат работать. Поскольку up -d также пересоздаст сервисы, чьи метки middleware вы переименовали, эти роутеры запустятся корректно. В исправном логе отсутствуют строки field not found и does not exist.

Оцените риски, которые несет этот шаг. Роутер, который ссылается на имя middleware, неизвестное для v3 (опечатка или удаленный параметр), будет неработоспособен с момента запуска нового Traefik до момента пересоздания контейнера приложения. На одной машине это занимает столько времени, сколько требуется docker compose up -d для обработки списка. Если маршрут критически важен, удалите переименованный middleware из label middlewares этого роутера перед переключением и добавьте его снова после, а также заранее решите, может ли этот маршрут работать без списка разрешенных IP в течение этой минуты.

Шаг 5: мигрируйте правила по одному сервису. Обрабатывайте приложения по очереди: перепишите правило на синтаксис v3, пересоздайте только этот сервис с помощью docker compose up -d app и протестируйте его перед переходом к следующему. Если у одного сервиса есть правило, которое вы пока не можете переписать, добавьте этому роутеру метку для обхода ограничений traefik.http.routers.app.ruleSyntax=v2 и продолжайте работу.

Шаг 6: отключите режим совместимости. Когда все правила будут приведены к синтаксису v3, удалите defaultRuleSyntax и любые метки ruleSyntax, перезапустите Traefik и убедитесь, что все роутеры в dashboard отображаются корректно (зеленым цветом). Не оставляйте режим совместимости включенным: Traefik объявил оба параметра устаревшими в v3.4 и удалит их в следующей мажорной версии. Это лишь временный переходный этап, а не целевое состояние.

До и после: метки сервиса

Ниже приведен пример приложения, в котором одновременно применены все основные изменения: многозначное значение Host, плейсхолдер PathPrefix и middleware ipWhiteList. Блок v2:

  app:
    image: app:1.4
    restart: unless-stopped
    networks:
      - proxy
    labels:
      - traefik.enable=true
      - traefik.http.routers.app.rule=Host(`app.example.com`,`www.example.com`) && PathPrefix(`/api/{version:v[0-9]+}`)
      - traefik.http.routers.app.entrypoints=websecure
      - traefik.http.routers.app.tls.certresolver=le
      - traefik.http.routers.app.middlewares=office
      - traefik.http.middlewares.office.ipwhitelist.sourcerange=10.0.0.0/24
      - traefik.http.services.app.loadbalancer.server.port=8080

Тот же сервис после миграции на v3:

  app:
    image: app:1.4
    restart: unless-stopped
    networks:
      - proxy
    labels:
      - traefik.enable=true
      - traefik.http.routers.app.rule=(Host(`app.example.com`) || Host(`www.example.com`)) && PathRegexp(`^/api/v[0-9]+`)
      - traefik.http.routers.app.entrypoints=websecure
      - traefik.http.routers.app.tls.certresolver=le
      - traefik.http.routers.app.middlewares=office
      - traefik.http.middlewares.office.ipallowlist.sourcerange=10.0.0.0/24
      - traefik.http.services.app.loadbalancer.server.port=8080

Изменились две метки. Правило разделило многозначное значение Host на два матчера, соединенных через ||, и заменило плейсхолдер на PathRegexp. Метка middleware была изменена с ipwhitelist на ipallowlist. Entrypoint, resolver сертификатов, связь router-to-middleware и порт сервиса остались без изменений.

Проверка каждого сервиса через dashboard

После каждого переключения открывайте страницу HTTP routers в dashboard. Все роутеры должны быть отмечены зеленым цветом. Если у роутера есть значок ошибки, в нем указана точная причина. Обычно это middleware, который не существует под новым именем, или правило, которое v3 не может обработать. Затем выполните проверку извне, по одному hostname за раз:

curl -sI https://app.example.com/api/v1/status

Статус 200 или обычный редирект вашего приложения означает, что маршрутизация и TLS работают корректно. Статус 404 от Traefik означает, что роутер не запустился; вернитесь в dashboard и прочитайте текст ошибки. Держите docker compose logs -f traefik открытым во втором терминале во время работы, так как любая ошибка парсинга отображается там сразу после перезапуска контейнера.

Правила отката

Сохраняйте compose file версии v2, его статическую конфигурацию и резервную копию acme.json до тех пор, пока все сервисы не перейдут на v3 и не пройдут полноценное тестирование. Откат подразумевает переключение на коммит до миграции и запуск docker compose up -d. Необходимо использовать весь файл целиком, а не только тег образа. Это связано с тем, что метки (labels), специфичные для v3, некорректно работают в v2, точно так же, как метки v2 некорректно работали в v3: в v2 отсутствует ipallowlist, и матчер PathRegexp там также не будет работать. Если в процессе работы acme.json был утерян или поврежден, восстановите резервную копию перед запуском v2. Это необходимо, чтобы при откате не было израсходовано ограничение Let's Encrypt на повторный выпуск пяти сертификатов одновременно.

FAQ

Нужно ли переписывать все правила роутера для Traefik v3?

Нет. Обычное правило Host(app.example.com), записанное с использованием обратных кавычек (backticks), является валидным в обеих версиях; это применимо к большинству конфигураций Compose. Переписывание требуется только в тех случаях, когда правило использует функции, доступные только в v2: регулярные выражения или плейсхолдеры внутри Path и PathPrefix, несколько хостнеймов внутри одного Host(), кавычки вместо обратных кавычек или удаленные матчеры Headers, HeadersRegexp и HostHeader.

Что произошло с ipWhiteList в Traefik v3?

Параметр был переименован в ipAllowList, при этом содержимое конфигурации осталось прежним. Таким образом, метка v2, такая как traefik.http.middlewares.office.ipwhitelist.sourcerange=10.0.0.0/24, превращается в ту же строку, но с ipallowlist внутри. Текущие релизы v3, включая v3.5, все еще принимают старое имя как устаревший псевдоним (deprecated alias), поэтому непереименованная метка продолжает работать. Рассматривайте это как временное решение, а не повод не выполнять переименование: удаление псевдонима запланировано. Если использовать имя middleware, которое Traefik не распознает, возникнет явная ошибка роутера и статус 404. Ошибка отображается в dashboard, а запросы к этому хостнейму возвращают 404.

Может ли Traefik v3 по-прежнему читать синтаксис правил v2?

Да. Установите core.defaultRuleSyntax: v2 в статической конфигурации, чтобы сохранить синтаксис v2 в качестве значения по умолчанию на время миграции. После возврата значения по умолчанию используйте метку ruleSyntax=v2 для отдельных оставшихся роутеров. Считайте оба варианта временными: Traefik объявил их устаревшими в v3.4 и удалит в следующей мажорной версии.

Сохранятся ли мои сертификаты Let's Encrypt после обновления?

Да. Traefik v3 продолжает читать файл acme.json, созданный v2, поэтому сертификаты не перевыпускаются только из-за смены бинарного файла. Тем не менее, перед началом работы скопируйте файл в безопасное место. Откат системы или удаление volume, в котором находится acme.json, приведет к необходимости массового перевыпуска всех сертификатов, а Let's Encrypt разрешает только пять дублирующих сертификатов в неделю для одного и того же набора хостнеймов.

Почему Traefik v3 не запускается после обновления?

Почти всегда это происходит из-за того, что в статической конфигурации все еще указана опция, удаленная в v3. Traefik отказывается запускаться, если встречает неизвестные параметры. Для общеизвестных устаревших параметров (pilot, providers.docker.swarmMode, experimental.http3) в логах будет указано incompatible deprecated static option found с именем виновника; для всего, что v3 никогда не поддерживала (например, tls.caOptional), будет выведено field not found с указанием узла. Удалите или замените каждый такой параметр, затем перезапустите контейнер.