Міграція Traefik v2 на v3: що змінилося
Виправте помилку несумісності static configuration, якщо використовуєте swarmMode або pilot. Дізнайтеся про зміни в middleware та синтаксисі правил роутера.
Що змінилося між Traefik v2 та v3
Міграція з Traefik v2 на v3 — це переважно перейменування компонентів. Зокрема, middleware ipWhiteList тепер називається ipAllowList. Крім цього, у v3 змінено синтаксис правил роутера (PathPrefix більше не підтримує regex, деякі матчери перейменовані або видалені). Також видалено кілька провайдерів та опцій. Інші функції залишаються без змін: entrypoints, налаштування сертифікатів ACME, робочий процес Docker labels та ваш acme.json працюватимуть і далі. У v3 також додано режим сумісності, який дозволяє використовувати синтаксис правил v2. Це дає можливість спочатку оновити binary, а потім переписувати правила для кожного сервісу окремо, замість ризикованого одномоментного оновлення.
Цей посібник базується на налаштуванні Docker Compose через labels із the Traefik reverse proxy guide. Та сторінка призначена для v3; ця сторінка — для систем, де все ще використовується тег traefik:v2.
Перейменування та видалення
ipWhiteListтепер називаєтьсяipAllowListдля middleware HTTP та TCP. Параметри всередині не змінилися, томуsourcerangeзберігає своє значення. Поточні релізи v3, включаючи v3.5, все ще приймають стару назву як deprecated alias і зберігають список, тому це перейменування нічого не зламає. Проте перейменуйте її: видалення alias заплановано, і він зникне зі списку deprecation без попереджень.providers.docker.swarmMode=trueвидалено. Swarm отримав власний provider, який налаштовується якproviders.swarm.endpoint.- Розділ
pilotповністю видалено. experimental.http3видалено. HTTP/3 тепер вмикається безпосередньо на entrypoint.tls.caOptionalвидалено з provider та middleware forwardAuth.- Provider для InfluxDB v1, provider для Rancher та provider для Marathon видалено.
- Tracing перенесено на OpenTelemetry. Спеціалізовані tracing backends, включаючи інтеграції Jaeger та Zipkin, видалено; v3 тепер експортує OTLP (OpenTelemetry protocol).
- Deprecated опції
ssl*у middleware headers (sslRedirect,sslHostта інші) видалено. Їх замінили redirection на entrypoint та middleware redirectScheme.
Ці видалення є критичними, оскільки Traefik не запускається, якщо статична конфігурація містить невідому йому опцію. Залишена стрічка pilot або swarmMode зупиняє контейнер під час завантаження з повідомленням incompatible deprecated static option found, що вказує на невідому опцію; якщо ж опція взагалі невідома Traefik (друкарська помилка або tls.caOptional), виникне помилка field not found. Очищуйте статичну конфігурацію перед зміною тегу образу.
Якщо Traefik дійсно не знає назву middleware (друкарська помилка або назва, яку видалили замість створення alias), результат інший: роутер, що посилається на неї, завантажується з помилкою замість створення маршруту, dashboard позначає її, а API повертає middleware "offce@docker" does not exist. Запити до цього hostname отримують 404, оскільки роутер не запустився. Зверніть увагу, що ipwhitelist НЕ належить до цієї категорії в поточній v3: вона залишається як deprecated alias, тому неперейменований label продовжує працювати без помилок.
Зміни синтаксису правил
Правила — це місце, де відбуваються основні перейменування. Зміни у v3:
- Значення всередині матчерів мають бути в зворотних лапках. 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для перевірки адреси клієнта всередині правила.
Хороша новина: звичайне правило Host(app.example.com), записане зі зворотними лапками, вже є валідним синтаксисом v3. Більшість невеликих налаштувань Compose використовують саме такий формат, тому більшість міток перенесеться без редагування правил.
Перевірте ваші labels перед початком
Ви можете оцінити обсяг міграції за допомогою одного пошуку. Кожна зміна, що порушує сумісність, залишає патерн, який можна знайти через grep:
grep -rnE 'ipwhitelist|HostHeader|Headers\(|PathPrefix\(`[^`]*\{|Host\(`[^`]*`,' docker-compose*.ymlКожне знаходження — це один рядок для редагування. ipwhitelist стає ipallowlist. HostHeader стає Host. Headers стає Header. Плейсхолдер {...} всередині PathPrefix стає матчером PathRegexp. Кома всередині Host() стає двома матчерами Host(), з'єднаними за допомогою ||. Якщо результатів пошуку нуль, ваші labels вже відповідають синтаксису v3. У такому разі міграція обмежується статичною конфігурацією та тегом образу.
Що залишається без змін
Entrypoints та їхнє перенаправлення з HTTP на HTTPS, ACME-резолвери з обома типами перевірок, exposedByDefault, мітки router та service, loadbalancer.server.port, а також панель керування (dashboard) у v3 працюють так само, як і у v2. Сертифікати також зберігаються, оскільки v3 продовжує зчитувати acme.json, записаний у v2. Попри це, перед початком роботи зробіть резервну копію файлу. Якщо під час відкату (rollback) цей файл буде втрачено, ви потрапите під обмеження Let's Encrypt щодо дублювання сертифікатів (duplicate-certificate rate limit):
cp ./letsencrypt/acme.json ./letsencrypt/acme.json.v2-backupШлях міграції
Step 1: зафіксуйте поточну версію. Замініть будь-який тег traefik:latest або traefik:v2 на точну версію, яку ви використовуєте, наприклад traefik:v2.11, і зробіть commit усієї директорії compose у git. Кожен наступний крок можна буде скасувати за допомогою checkout. Якщо перестворення окремого сервісу за допомогою docker compose up -d <service> ще не є для вас звичним, базовий посібник з Docker Compose описує операції, на яких базується ця міграція.
Step 2: очистьте статичну конфігурацію та увімкніть режим сумісності. Видаліть усі параметри, які було видалено у v3 (pilot, swarmMode, tls.caOptional, experimental.http3), а потім вкажіть v3 використовувати синтаксис v2 для правил за замовчуванням. У traefik.yml:
core:
defaultRuleSyntax: v2Або як прапорець у списку compose command:: --core.defaultRuleSyntax=v2. Режим сумісності стосується лише синтаксису правил. Він не відновлює видалені параметри та не перейменовує middleware автоматично.
Step 3: підготуйте перейменування middleware. Знайдіть у ваших файлах compose старі назви: grep -rn ipwhitelist docker-compose*.yml. Змініть кожен лейбл ipwhitelist на ipallowlist, але не застосовуйте зміни зараз, оскільки нової назви не існує у v2. Ці правки мають бути застосовані одночасно з перемиканням на наступному кроці. (Якщо ви пропустите одну назву, поточна v3 все ще розпізнаватиме стару назву як застарілий аліас, тому список продовжуватиме працювати; краще виправте це наступним циклом, ніж о 2 годині ночі.)
Step 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 з лейбла middlewares цього роутера перед перемиканням і додайте його знову після, а також заздалегідь вирішіть, чи може цей маршрут працювати без списку дозволених IP протягом цієї хвилини.
Step 5: мігруйте правила по одному сервісу. Працюйте з одним додатком за раз: перепишіть його правило на синтаксис v3, перестворіть лише цей сервіс за допомогою docker compose up -d app і протестуйте його перед переходом до наступного. Якщо у сервісу є правило, яке ви ще не можете переписати, додайте цьому роутеру лейбл для виходу з ситуації traefik.http.routers.app.ruleSyntax=v2 і продовжуйте роботу.
Step 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 не може розпарсити. Потім підтвердьте роботу кожного хостнейму окремо із зовнішнього пристрою:
curl -sI https://app.example.com/api/v1/status200 або звичайний редирект вашого додатка означає, що маршрутизація та TLS працюють коректно. 404 від Traefik означає, що роутер не запустився; поверніться до dashboard, щоб прочитати помилку. Тримайте docker compose logs -f traefik відкритим у другому терміналі під час роботи, оскільки будь-яка помилка парсингу з'являється там одразу після перезапуску контейнера.
Honesty при відкаті
Зберігайте compose file v2, його статичну конфігурацію та резервну копію acme.json до моменту, поки кожен сервіс не перейде на v3 і не пройде реальне тестування. Відкат означає перехід на комміт до міграції та запуск docker compose up -d. Потрібно використовувати весь файл, а не лише тег образу. Це необхідно, оскільки лейбли, специфічні для v3, некоректно працюють у v2, так само як лейбли v2 некоректно працювали у v3: ipallowlist не існує у v2, а матчер PathRegexp там також не розпізнається. Якщо під час процесу acme.json було втрачено або пошкоджено, відновіть резервну копію перед запуском v2. Це запобіжить перевищенню лімітів Let's Encrypt через одночасне перевипуск п'яти сертифікатів.
FAQ
Чи потрібно переписувати всі правила роутера для Traefik v3?
Ні. Звичайне правило Host(app.example.com), написане з використанням зворотних лапок (backticks), є коректним в обох версіях, що покриває більшість налаштувань Compose. Переписування необхідне лише у випадках використання функцій, доступних тільки у v2: regex або placeholder всередині 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, все ще приймають стару назву як застарілий аліас, тому неперейменований лейбл продовжує працювати. Це тимчасове рішення: аліас буде видалено. Якщо використати назву 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 та назву причини. Для невідомих параметрів, як-от tls.caOptional, буде вказано field not found та назву вузла. Видаліть або замініть кожен такий параметр, після чого знову запустіть контейнер.