- HTML 94.9%
- Makefile 4.8%
- Dockerfile 0.3%
| manifests | ||
| pages | ||
| .gitignore | ||
| Dockerfile | ||
| Makefile | ||
| nginx.conf | ||
| README.md | ||
| README.zh-cn.md | ||
Traefik "No Available Server" Custom Error Page
Replace Traefik's default "no available server" response with a beautiful, i18n error page that auto-retries until the service is ready.
Problem
When Traefik believes a pod behind an IngressRoute is not ready (during rollouts, restarts, or readiness probe gaps), it returns a bare 503 Service Unavailable with the message "no available server". This is confusing to end users. This project replaces it with a polished page that:
- Auto-refreshes every 5 seconds until the service recovers
- Detects the user's browser language (15 languages supported)
- Can be applied globally at the Traefik entryPoint level -- no per-route changes needed
Architecture
User Request --> Traefik entryPoint (global middleware)
|
+-- Pod ready -------> Normal response
|
+-- "no available server" (502/503)
|
1. Retry Middleware (4 attempts, exponential backoff)
|
2. Errors Middleware --> error-pages service
|
v
Beautiful i18n page
(auto-retries every 5s)
Prerequisites
- Kubernetes cluster (minikube, k3s, EKS, GKE, etc.)
- Traefik v2.x / v3.x with CRD support (
IngressRoute,Middleware) kubectl,docker
Quick Start
# 1. Build & push the error-pages image
make build IMAGE_NAME=your-registry/traefik-error-pages
make push IMAGE_NAME=your-registry/traefik-error-pages
# 2. Update the image in manifests/base/error-pages-deployment.yaml
# 3. Deploy error-pages service + middlewares
make deploy
# 4. Configure Traefik to use the middleware globally (see below)
# 5. Verify
make status
Deployment Guide
1. Build and push the error-pages image
make build IMAGE_NAME=your-registry/traefik-error-pages
make push IMAGE_NAME=your-registry/traefik-error-pages
Update the image in manifests/base/error-pages-deployment.yaml to match.
To preview the page locally before deploying:
make build
make dev
# Open http://localhost:8080/503.html
2. Deploy error-pages and middlewares
make deploy
make status
This creates the following resources in the traefik namespace:
error-pagesDeployment (2 replicas) and Service (ClusterIP:8080)retry,custom-errors,error-handlingMiddlewares- A low-priority catchall IngressRoute for the error-pages service
3. Configure Traefik to use the middleware globally
This project only deploys the error-pages service and middlewares. You need to configure your Traefik installation separately to apply them globally.
Add the following to your Traefik startup arguments (via Helm values, static config, or CLI flags):
--entrypoints.web.http.middlewares=traefik-error-handling@kubernetescrd
--entrypoints.websecure.http.middlewares=traefik-error-handling@kubernetescrd
The middleware reference format is {namespace}-{name}@kubernetescrd.
Helm example:
# your-traefik-values.yaml
additionalArguments:
- "--entrypoints.web.http.middlewares=traefik-error-handling@kubernetescrd"
- "--entrypoints.websecure.http.middlewares=traefik-error-handling@kubernetescrd"
helm upgrade traefik traefik/traefik -n traefik -f your-traefik-values.yaml
After this, all routes on web and websecure entrypoints will use the error-handling middleware automatically. No need to modify individual IngressRoutes.
4. Test with the example overlay
The example overlay deploys a test app (nginx:alpine) with a plain IngressRoute (no middleware reference needed since it's global):
# Deploy the test app
make deploy-example
# Scale to 0 to simulate "no available server"
kubectl scale deployment test-app -n traefik --replicas=0
# Set up local access (minikube)
echo "127.0.0.1 test-app.local" | sudo tee -a /etc/hosts
kubectl port-forward svc/traefik 9080:80 -n traefik &
# Open in browser -- you should see the custom error page
open http://test-app.local:9080
Scale back up to verify auto-recovery:
kubectl scale deployment test-app -n traefik --replicas=1
The error page auto-refreshes and the user lands on the real nginx welcome page within seconds.
Configuration
Namespace
The default namespace is traefik. To change it:
cd manifests/base && kustomize edit set namespace my-namespace
Also update the middleware reference in your Traefik config to match (format: {namespace}-{name}@kubernetescrd).
Image
Edit manifests/base/error-pages-deployment.yaml directly, or use Kustomize images in an overlay:
images:
- name: davidliyutong/traefik-error-pages
newName: ghcr.io/yourorg/traefik-error-pages
newTag: v1.0.0
Retry behavior
Edit manifests/base/middleware-retry.yaml:
attempts-- max retries before giving up (default: 4)initialInterval-- first retry delay (default: 500ms), subsequent retries use exponential backoff
Error page content
Edit pages/503.html and pages/502.html, then rebuild the image. The pages are self-contained HTML with inline CSS/JS -- no build tools needed.
Supported Languages
English, Chinese (Simplified / Traditional), Japanese, Korean, French, German, Spanish, Portuguese, Russian, Italian, Arabic (RTL), Turkish, Vietnamese, Thai
Project Structure
.
├── Dockerfile # nginx:alpine serving custom pages
├── nginx.conf # nginx config (port 8080, /healthz)
├── pages/
│ ├── 502.html # Bad gateway error page
│ └── 503.html # Service unavailable error page
├── manifests/
│ ├── base/ # Core resources
│ │ ├── kustomization.yaml
│ │ ├── error-pages-deployment.yaml # 2-replica nginx deployment
│ │ ├── error-pages-service.yaml # ClusterIP on port 8080
│ │ ├── middleware-retry.yaml # Retry 4x with backoff
│ │ ├── middleware-errors.yaml # Catch 502-503 -> error-pages
│ │ ├── middleware-chain.yaml # Chain: retry -> custom-errors
│ │ └── ingressroute-error-pages.yaml # Low-priority catchall
│ └── overlays/
│ └── example/ # Test overlay
│ ├── kustomization.yaml
│ ├── test-app.yaml # Test app Deployment + Service
│ └── ingressroute-app.yaml # Test app IngressRoute
├── Makefile
└── README.md
Make Targets
| Target | Description |
|---|---|
build |
Build the Docker image |
push |
Push image to registry |
dev |
Run locally for preview (port 8080) |
deploy |
Deploy error-pages + middlewares |
undeploy |
Remove all deployed resources |
deploy-example |
Deploy test app and IngressRoute |
undeploy-example |
Remove example overlay |
status |
Check pods, middlewares, IngressRoutes |
logs |
Tail error-pages pod logs |
dry-run |
Preview rendered manifests |
Notes
- This project deploys only the error-pages service and Traefik middlewares. Traefik itself must be configured separately to use them (see step 3).
- The error-pages Deployment runs 2 replicas by default for high availability.
- Manifests use
traefik.io/v1alpha1(Traefik v2/v3). For older Traefik versions, change totraefik.containo.us/v1alpha1. - The catchall IngressRoute (
priority: 1) ensures the error-pages service itself is always reachable by the errors middleware.
License
MIT