Migrazione da Traefik v2 a v3: cosa cambia
Traefik v3 non si avvia con swarmMode o pilot nella configurazione statica. Risolvi l'errore "incompatible deprecated static option found" e aggiorna le regole.
Cosa cambia tra Traefik v2 e v3
La migrazione da Traefik v2 a v3 consiste soprattutto nel rinominare alcuni elementi. Il cambio di nome più noto è quello del middleware ipWhiteList, diventato ipAllowList. Inoltre, v3 rende più rigida la sintassi delle regole dei router: PathPrefix non supporta più le funzionalità regex e diversi matcher sono stati rinominati o rimossi. Alcuni provider e opzioni sono stati eliminati completamente. Il resto continua a funzionare: entrypoint, configurazione dei certificati ACME, flusso di lavoro basato sulle label Docker e il tuo acme.json vengono mantenuti. v3 include anche una modalità di compatibilità che mantiene il supporto per la sintassi delle regole di v2. Puoi quindi aggiornare prima il binario e riscrivere le regole un servizio alla volta, senza eseguire tutte le modifiche in un'unica finestra di manutenzione rischiosa.
Questa guida presuppone la configurazione Docker Compose basata sulle label descritta in guida al reverse proxy Traefik. Quella pagina usa nativamente v3; questa guida è destinata al server che esegue ancora un tag traefik:v2.
Rinominazioni e rimozioni
ipWhiteListora èipAllowList, sia per il middleware HTTP sia per quello TCP. Le opzioni al suo interno non cambiano, quindisourcerangemantiene esattamente lo stesso significato. Le versioni v3 attuali, inclusa la v3.5, accettano ancora il vecchio nome come alias deprecato e continuano ad applicare l'elenco, quindi questa singola rinominazione non interrompe il servizio al momento del passaggio. Rinominalo comunque: l'alias è destinato a essere rimosso e scompare dall'elenco delle funzionalità deprecate senza messaggi espliciti.providers.docker.swarmMode=trueè stato rimosso. Swarm dispone ora di un provider dedicato, configurato comeproviders.swarm.endpoint.- La sezione
pilotè stata rimossa completamente. experimental.http3è stato rimosso. HTTP/3 viene abilitato direttamente sull'entrypoint.tls.caOptionalè stato rimosso dai provider e dal middleware forwardAuth. Se questo middleware precede un SSO Authentik self-hosted, eliminare la rigacaOptionalè sufficiente per completare la migrazione, perché l'indirizzo forwardAuth, gli header attendibili e l'outpost che li gestisce si comportano tutti allo stesso modo in v3.- Il provider delle metriche InfluxDB v1, il provider Rancher e il provider Marathon sono stati rimossi.
- Il tracing è passato a OpenTelemetry. I backend di tracing dedicati, comprese le integrazioni Jaeger e Zipkin, sono stati rimossi e v3 esporta invece OTLP (il protocollo OpenTelemetry).
- Le opzioni
ssl*deprecate all'interno del middleware headers (sslRedirect,sslHoste le altre) sono state rimosse. I redirect dell'entrypoint e il middleware redirectScheme le hanno sostituite.
Queste rimozioni sono più importanti di quanto possa sembrare, perché Traefik rifiuta di avviarsi quando la configurazione statica contiene un'opzione che non riconosce. Una riga pilot o swarmMode rimasta nella configurazione arresta il container durante l'avvio con un messaggio incompatible deprecated static option found che indica l'elemento rimasto; un'opzione che Traefik non ha mai riconosciuto, come un refuso o tls.caOptional, causa invece un errore field not found. Pulisci la configurazione statica prima di modificare il tag dell'immagine.
Un nome di middleware che Traefik non riconosce realmente, per esempio un refuso o un nome rimosso anziché mantenuto come alias, produce un errore diverso: il router che lo utilizza viene caricato con un errore invece di una route, la dashboard lo segnala e l'API restituisce middleware "offce@docker" does not exist. Le richieste dirette a quell'hostname ricevono un 404 perché il router non è mai entrato in funzione. Tieni presente che ipwhitelist NON rientra in questa categoria nelle versioni v3 attuali: sopravvive come alias deprecato, quindi un label non rinominato continua a funzionare senza messaggi.
La sintassi delle regole cambia
Le regole consentono di eseguire le riscritture vere e proprie. In v3 cambiano i seguenti aspetti:
- I valori all’interno dei matcher devono essere racchiusi tra backtick. v2 accettava anche le virgolette doppie; v3 non le accetta. Di conseguenza,
Host("app.example.com")deve diventareHost(app.example.com). PathPrefixnon interpreta più le espressioni regolari né i segnaposto nello stile di{id}. Una regola v2 comePathPrefix(/api/{version:v[0-9]+})deve diventare un matcherPathRegexpscritto usando la sintassi delle espressioni regolari Go.- I matcher ora accettano un solo valore. v2 consentiva
Host(app.example.com,www.example.com); v3 richiedeHost(app.example.com) || Host(www.example.com). Fanno eccezioneHeader,HeaderRegexp,QueryeQueryRegexp, che accettano ancora un nome e un valore. HeaderseHeadersRegexpvengono rinominati rispettivamente inHeadereHeaderRegexp.HostHeaderviene rimosso. In v3 usareHost, che esegue lo stesso tipo di corrispondenza.- Sono stati aggiunti due matcher:
QueryRegexpeClientIP, che consentono di verificare l’indirizzo del client all’interno di una regola.
La buona notizia è che una semplice regola Host(app.example.com) scritta con i backtick è già valida in v3. La maggior parte delle configurazioni Compose di piccole dimensioni usa esattamente questa sintassi. Di conseguenza, nella maggior parte dei casi le label possono essere migrate senza modificare le regole.
Verifica le label prima di iniziare
Puoi misurare l'entità della migrazione con una sola ricerca, perché ogni modifica incompatibile alle label lascia un modello che grep può trovare:
grep -rnE 'ipwhitelist|HostHeader|Headers\(|PathPrefix\(`[^`]*\{|Host\(`[^`]*`,' docker-compose*.ymlOgni risultato corrisponde a una riga da modificare. ipwhitelist diventa ipallowlist. HostHeader diventa Host. Headers diventa Header. Un placeholder {...} all'interno di PathPrefix diventa un matcher PathRegexp. Una virgola all'interno di Host() diventa due matcher Host() collegati da ||. Nessun risultato significa che le label usano già una sintassi v3 valida e che la migrazione si riduce alla configurazione statica e al tag dell'immagine. Una schermata piena di risultati è anche un buon momento per chiedersi se questo sia ancora il proxy più adatto al server; il confronto tra Traefik, Nginx e Caddy mette il costo della riscrittura in relazione a ciò che gli altri due richiedono per ogni applicazione.
Cosa resta invariato
Gli entrypoint e il relativo redirect da HTTP a HTTPS, i resolver ACME con entrambi i tipi di challenge, exposedByDefault, le label di router e servizio, loadbalancer.server.port e la dashboard funzionano in v3 come in v2. Anche i certificati vengono mantenuti, perché v3 continua a leggere acme.json, scritto da v2. Esegui comunque un backup del file prima di iniziare: un rollback che lo perda porta direttamente al limite di frequenza di Let's Encrypt per i certificati duplicati:
cp ./letsencrypt/acme.json ./letsencrypt/acme.json.v2-backupIl percorso di migrazione
Passaggio 1: fissa ciò che esegui oggi. Modifica ogni tag traefik:latest o traefik:v2 impostandolo sulla release esatta in uso, ad esempio traefik:v2.11, quindi esegui il commit dell'intera directory Compose in git. Ogni passaggio successivo potrà essere annullato con un checkout. Se ricreare un singolo servizio con docker compose up -d <service> non è ancora un'operazione abituale, la guida alle basi di Docker Compose descrive le operazioni utilizzate in questa migrazione.
Passaggio 2: pulisci la configurazione statica e abilita la modalità di compatibilità. Rimuovi ogni opzione eliminata dalla v3 (pilot, swarmMode, tls.caOptional, experimental.http3), quindi configura la v3 affinché interpreti per impostazione predefinita le regole come sintassi v2. In traefik.yml:
core:
defaultRuleSyntax: v2Oppure usa un flag nell'elenco compose command:: --core.defaultRuleSyntax=v2. La modalità di compatibilità riguarda soltanto la sintassi delle regole. Non ripristina le opzioni rimosse e non rinomina automaticamente i middleware.
Passaggio 3: prepara la rinomina dei middleware. Cerca nei file Compose i nomi precedenti: grep -rn ipwhitelist docker-compose*.yml. Modifica ogni label ipwhitelist in ipallowlist, ma non applicare ancora la modifica, perché il nuovo nome non esiste nella v2. Queste modifiche devono essere applicate insieme all'attivazione descritta nel passaggio successivo. (Se un riferimento sfugge, la v3 attuale continua a riconoscere il nome precedente come alias deprecato, quindi l'elenco continua a essere applicato; correggilo nel passaggio successivo, non alle 2 di notte.)
Passaggio 4: modifica il tag dell'immagine. Imposta l'immagine Traefik sulla release v3 corrente, traefik:v3.5 al momento della stesura, quindi:
docker compose up -d
docker compose logs -f traefikPoiché la modalità di compatibilità è attiva, le regole v2 continuano a funzionare. Inoltre, poiché up -d ha ricreato anche i servizi con le label dei middleware rinominati, i router si avviano correttamente. Un log in condizioni normali non contiene alcuna riga field not found né alcuna riga does not exist.
Valuta con attenzione la finestra operativa aperta da questo passaggio. Un router che fa riferimento a un nome di middleware che la v3 non riconosce realmente, a causa di un errore di battitura o di un'opzione rimossa, non è operativo dal momento in cui si avvia la nuova istanza di Traefik fino alla ricreazione del relativo container applicativo. Su un singolo host, questo richiede i pochi secondi necessari a docker compose up -d per elaborare l'elenco. Se una route non può subire nemmeno una breve interruzione, rimuovi il middleware rinominato dalla label middlewares di quel router prima dell'attivazione e aggiungilo nuovamente dopo. Decidi in anticipo se la route può rimanere senza il relativo elenco di indirizzi IP consentiti durante il minuto intermedio.
Passaggio 5: migra le regole servizio per servizio. Procedi un'applicazione alla volta: riscrivi la relativa regola usando la sintassi v3, ricrea soltanto quel servizio con docker compose up -d app e testalo prima di continuare. Se un servizio contiene una regola che non puoi ancora riscrivere, assegna a quel singolo router la label di deroga traefik.http.routers.app.ruleSyntax=v2 e continua.
Passaggio 6: disattiva la modalità di compatibilità. Quando tutte le regole usano la sintassi v3, elimina defaultRuleSyntax e tutte le label ruleSyntax, riavvia Traefik e verifica che ogni router continui a essere visualizzato in verde nella dashboard. Non mantenere la modalità di compatibilità più del necessario: Traefik ha dichiarato deprecate entrambe le opzioni nella v3.4 e le rimuoverà nella prossima versione principale. Sono quindi un passaggio temporaneo, non una configurazione definitiva.
Prima e dopo: le label di un servizio
Questa applicazione include contemporaneamente tutte le modifiche più comuni: un Host con più valori, un segnaposto PathPrefix e un middleware ipWhiteList. Il blocco 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=8080E lo stesso servizio migrato a 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=8080Sono cambiate due label. La regola ha suddiviso il suo Host con più valori in due matcher collegati da || e ha sostituito il segnaposto con PathRegexp; la label del middleware ha sostituito ipwhitelist con ipallowlist. L'entrypoint, il resolver dei certificati, il collegamento tra router e middleware e la porta del servizio non sono cambiati.
Testare ogni servizio con il dashboard
Dopo ogni modifica, aprire la pagina dei router HTTP nel dashboard. Ogni router dovrebbe essere verde. Un router con un badge di errore indica il problema esatto. Di solito si tratta di un middleware che non esiste con il nuovo nome oppure di una regola v3 che non può essere analizzata. Verificare quindi dall'esterno, un hostname alla volta:
curl -sI https://app.example.com/api/v1/statusUn 200 o il normale redirect dell'applicazione indica che routing e TLS funzionano ancora. Un 404 da Traefik indica che il router non è stato avviato. Tornare al dashboard e leggere l'errore. Lasciare docker compose logs -f traefik aperto in un secondo terminale durante il lavoro, perché ogni errore di analisi viene registrato lì non appena un container viene riavviato.
Onestà del rollback
Conserva il file Compose v2, la relativa configurazione statica e il backup acme.json fino a quando tutti i servizi non saranno instradati su v3 e verificati in condizioni reali. Il rollback consiste nel ripristinare il commit precedente alla migrazione ed eseguire docker compose up -d. È necessario ripristinare l'intero file, non soltanto il tag dell'immagine, perché le label specifiche di v3 non sono valide in v2, esattamente come le label di v2 non erano valide in v3: ipallowlist non esiste in v2 e neppure un matcher PathRegexp può essere analizzato in quella versione. Se acme.json è stato perso o danneggiato durante la procedura, ripristina la copia di backup prima di avviare v2. In questo modo il rollback non consumerà il limite di frequenza di Let's Encrypt richiedendo nuovamente cinque certificati contemporaneamente.
FAQ
Devo riscrivere ogni regola del router per Traefik v3?
No. Una semplice regola Host(app.example.com) scritta con i backtick è valida in entrambe le versioni e copre la maggior parte delle configurazioni Compose. La riscrittura è necessaria solo quando una regola usa funzionalità disponibili esclusivamente in v2: espressioni regolari o segnaposto all'interno di Path e PathPrefix, più nomi host in un unico Host(), virgolette al posto dei backtick oppure i matcher rimossi Headers, HeadersRegexp e HostHeader.
Che cosa è successo a ipWhiteList in Traefik v3?
È stato rinominato in ipAllowList, senza modificare la configurazione interna. Pertanto, un'etichetta v2 come traefik.http.middlewares.office.ipwhitelist.sourcerange=10.0.0.0/24 diventa la stessa riga con ipallowlist al suo interno. Le versioni v3 attuali, inclusa la v3.5, accettano ancora il vecchio nome come alias deprecato. Un'etichetta non rinominata continua quindi ad applicare silenziosamente l'allowlist. Consideralo un periodo transitorio, non un motivo per evitare la rinomina: l'alias verrà rimosso e un nome di middleware che Traefik non riconosce realmente genera un errore esplicito, con un errore del router e una risposta 404. La dashboard mostra l'errore e le richieste a quel nome host restituiscono 404.
Traefik v3 riesce ancora a leggere la sintassi delle regole v2?
Sì. Imposta core.defaultRuleSyntax: v2 nella configurazione statica per mantenere la sintassi v2 come predefinita durante la migrazione e usa l'etichetta ruleSyntax=v2 a livello di singolo router per le eccezioni rimanenti dopo aver ripristinato l'impostazione predefinita. Entrambe sono soluzioni temporanee: Traefik le ha deprecate nella v3.4 e le rimuoverà nella prossima versione principale.
I certificati Let's Encrypt resteranno disponibili dopo l'aggiornamento?
Sì. Traefik v3 continua a leggere il file acme.json scritto da v2, quindi i certificati non vengono emessi nuovamente solo perché è cambiato il binario. Copia comunque il file in un luogo sicuro prima di iniziare. Un rollback o un volume eliminato che perda acme.json obbliga a emettere nuovamente tutti i certificati contemporaneamente. Let's Encrypt consente infatti soltanto cinque certificati duplicati alla settimana per lo stesso insieme di nomi host.
Perché Traefik v3 non si avvia dopo l'aggiornamento?
Quasi sempre perché la configurazione statica contiene ancora un'opzione rimossa in v3. Traefik rifiuta di avviarsi quando trova opzioni che non riconosce. Per le opzioni obsolete note (pilot, providers.docker.swarmMode, experimental.http3), il log riporta incompatible deprecated static option found e identifica la causa. Per qualsiasi opzione mai supportata da v3, come tls.caOptional, riporta field not found insieme al nodo. Elimina o sostituisci ogni opzione, quindi avvia nuovamente il container.