traefik: fix update order for host-mode/VRRP services (start-first -> stop-first)

reverse-proxy publishes host-mode ports (80/443/1883/5201/5431) — start-first
can never bind while the old task holds the ports, deadlocking every rolling
update. keepalived master/backup run VRRP on the host network — concurrent
old+new speakers with the same router-id risk VIP flapping. Both now use
stop-first (global mode + parallelism=1 + VIP failover keeps ingress up).
Stateless helpers (whoami, speedtest, iperf3, certs-dumper) keep start-first.

Step 1 of Tier 0/1 pipeline inclusion (prep for removing traefik/woodpecker
from the bootstrap manual-deploy guard).
This commit is contained in:
2026-07-16 23:04:00 -07:00
parent 5a24c162cc
commit 5a5718a2d3
+13 -6
View File
@@ -20,16 +20,18 @@ services:
labels: [traefik.enable=false] labels: [traefik.enable=false]
resources: resources:
limits: {cpus: '1', memory: 128M} limits: {cpus: '1', memory: 128M}
# stop-first: host network + VRRP — two concurrent keepalived speakers with the
# same router-id would fight over the VIP. Never run old+new simultaneously.
update_config: update_config:
parallelism: 1 parallelism: 1
delay: 30s delay: 30s
failure_action: rollback failure_action: rollback
monitor: 15s monitor: 15s
order: start-first order: stop-first
rollback_config: rollback_config:
parallelism: 1 parallelism: 1
failure_action: pause failure_action: pause
order: start-first order: stop-first
keepalived-backup: keepalived-backup:
environment: environment:
@@ -51,16 +53,17 @@ services:
labels: [traefik.enable=false] labels: [traefik.enable=false]
resources: resources:
limits: {cpus: '1', memory: 128M} limits: {cpus: '1', memory: 128M}
# stop-first: host network + VRRP (see keepalived-master)
update_config: update_config:
parallelism: 1 parallelism: 1
delay: 30s delay: 30s
failure_action: rollback failure_action: rollback
monitor: 15s monitor: 15s
order: start-first order: stop-first
rollback_config: rollback_config:
parallelism: 1 parallelism: 1
failure_action: pause failure_action: pause
order: start-first order: stop-first
reverse-proxy: reverse-proxy:
image: public.ecr.aws/docker/library/traefik:latest image: public.ecr.aws/docker/library/traefik:latest
@@ -128,16 +131,20 @@ services:
- traefik.http.routers.traefik.middlewares=forwardAuth-authentik@file, crowdsec@file - traefik.http.routers.traefik.middlewares=forwardAuth-authentik@file, crowdsec@file
resources: resources:
limits: {cpus: '4', memory: 512M} limits: {cpus: '4', memory: 512M}
# stop-first: host-mode published ports (80/443/1883/5201/5431) — a start-first
# replacement task can never bind while the old task holds the ports, so
# start-first would deadlock/rollback every update. Global mode + parallelism 1
# means only one node is briefly down; keepalived VIP + remaining nodes cover it.
update_config: update_config:
parallelism: 1 parallelism: 1
delay: 30s delay: 30s
failure_action: rollback failure_action: rollback
monitor: 15s monitor: 15s
order: start-first order: stop-first
rollback_config: rollback_config:
parallelism: 1 parallelism: 1
failure_action: pause failure_action: pause
order: start-first order: stop-first
traefik-certs-dumper: traefik-certs-dumper:
image: ghcr.io/ldez/traefik-certs-dumper:v2.10.0 image: ghcr.io/ldez/traefik-certs-dumper:v2.10.0