Traefik Ingress Controller
Deploy Traefik for simpler ingress before learning Gateway API complexity
- Status
- stable
- Trust
- unverified
- Approved
- ag-archive/0.1.0 ·
The previous lesson explained why Ingress has limitations—annotation chaos, vendor lock-in, no role separation. Gateway API solves these problems, but it introduces new abstractions: GatewayClass, Gateway, HTTPRoute, BackendTrafficPolicy. That's a lot to absorb before routing your first request.
What if you just want external traffic reaching your Task API in 5 minutes?
Traefik offers exactly that. It's a simpler ingress controller with its own CRDs (IngressRoute, Middleware) that are more intuitive than Ingress annotations. You'll understand traffic routing fundamentals faster with Traefik, which prepares you for Gateway API's more powerful—but more complex—model.
This lesson gets your Task API accessible from outside the cluster with rate limiting protection. Then you'll understand exactly what Gateway API improves upon.
Installing Traefik with Helm
Traefik publishes a Helm chart that handles all the complexity—Deployment, Service, ServiceAccount, RBAC, CRDs. You just run two commands.
Add the Traefik Helm repository:
helm repo add traefik https://traefik.github.io/chartsOutput:
"traefik" has been added to your repositoriesUpdate repository information:
helm repo updateOutput:
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "traefik" chart repository
Update Complete. ⎈Happy Helming!⎈Install Traefik in its own namespace:
helm install traefik traefik/traefik -n traefik --create-namespaceOutput:
NAME: traefik
LAST DEPLOYED: Mon Dec 30 10:15:00 2024
NAMESPACE: traefik
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Traefik Proxy v3.2.0 has been deployed successfully on traefik namespace!Verify the installation:
kubectl get pods -n traefikOutput:
NAME READY STATUS RESTARTS AGE
traefik-7d9c8f6c5b-xk2m9 1/1 Running 0 30sCheck the Service created by Traefik:
kubectl get svc -n traefikOutput:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
traefik LoadBalancer 10.96.45.123 localhost 80:31234/TCP,443:32456/TCP 45sOn Docker Desktop, localhost appears as the external IP. On a cloud provider, you'd see a real public IP. Either way, Traefik now accepts traffic on ports 80 (HTTP) and 443 (HTTPS).
Understanding Traefik Architecture
Before creating routes, understand how Traefik processes requests:
┌─────────────────────────────────────────────────────────────────────┐
│ Traefik Architecture │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ Internet Request │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ EntryPoints │ ← Ports Traefik listens on (80, 443) │
│ └──────┬──────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ Routers │ ← Match rules (Host, Path, Headers) │
│ └──────┬──────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ Middlewares │ ← Transformations (rate limit, auth, headers) │
│ └──────┬──────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ Services │ ← Backend targets (Kubernetes Services) │
│ └─────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘EntryPoints: Ports where Traefik accepts connections. The Helm chart creates web (port 80) and websecure (port 443) by default.
Routers: Rules that match incoming requests. When a request matches a Router's rule (e.g., Host('api.example.com') && PathPrefix('/tasks')), Traefik sends it to the associated Service.
Middlewares: Transformations applied before reaching the backend. Rate limiting, authentication, header manipulation, path stripping—all are Middlewares.
Services: Backend targets. In Kubernetes, these point to Kubernetes Services that forward to Pods.
This is similar to Gateway API's model (Gateway, HTTPRoute, BackendTrafficPolicy) but with different terminology and simpler CRDs.
Creating Your First IngressRoute
Traefik's IngressRoute CRD replaces Kubernetes' Ingress resource with a cleaner syntax. No annotations required.
First, ensure your Task API is running. If you've been following along, you have it deployed:
kubectl get svc task-api -n task-apiOutput:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
task-api ClusterIP 10.96.78.234 <none> 8000/TCP 2hNow create task-api-ingressroute.yaml that routes /api/v1/tasks to the Task API:
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: task-api-route
namespace: task-api
spec:
entryPoints:
- web # Listen on port 80
routes:
- match: PathPrefix(`/api/v1/tasks`)
kind: Rule
services:
- name: task-api
port: 8000Output:
(This is the manifest—we'll apply it next)
Apply the IngressRoute:
kubectl apply -f task-api-ingressroute.yamlOutput:
ingressroute.traefik.io/task-api-route createdTest the route:
curl http://localhost/api/v1/tasksOutput:
{"tasks": []}Your Task API is now accessible from outside the cluster through Traefik. The request flow:
- Request arrives at
localhost:80(Traefik'swebEntryPoint) - Traefik matches
PathPrefix('/api/v1/tasks')→task-api-route - Traefik forwards to
task-api:8000in thetask-apinamespace - Task API responds, Traefik returns the response
Compare this to the Ingress resource from Lesson 1. No annotations needed. The routing logic is in structured YAML fields, not string annotations.
Understanding the Match Rule Syntax
Traefik's match rules use a simple expression language:
| Expression | Meaning |
|---|---|
Host('api.example.com') | Match requests with this Host header |
PathPrefix('/api') | Match paths starting with /api |
Path('/health') | Match exactly /health |
Headers('X-Version', '2') | Match requests with this header value |
Method('POST') | Match only POST requests |
&& | AND - both conditions must match |
| ` |
Examples:
Route only POST requests to /tasks:
routes:
- match: PathPrefix(`/api/v1/tasks`) && Method(`POST`)
kind: Rule
services:
- name: task-api
port: 8000Route based on API version header:
routes:
- match: PathPrefix(`/api`) && Headers(`X-API-Version`, `v2`)
kind: Rule
services:
- name: task-api-v2
port: 8000This expressive matching is something standard Ingress cannot do without controller-specific annotations.
Adding Rate Limiting with Middleware
Your AI agent's Task API could be expensive to run. Without rate limiting, a single user could exhaust your compute budget. Traefik Middlewares handle this.
Create ratelimit-middleware.yaml:
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: rate-limit
namespace: task-api
spec:
rateLimit:
average: 10 # 10 requests per second average
burst: 20 # Allow bursts up to 20 requests
period: 1s # Time windowOutput:
(This is the manifest—we'll apply it next)
Apply the Middleware:
kubectl apply -f ratelimit-middleware.yamlOutput:
middleware.traefik.io/rate-limit createdNow attach the Middleware to your IngressRoute. Create task-api-ingressroute-ratelimited.yaml:
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: task-api-route
namespace: task-api
spec:
entryPoints:
- web
routes:
- match: PathPrefix(`/api/v1/tasks`)
kind: Rule
middlewares:
- name: rate-limit # Attach the Middleware
services:
- name: task-api
port: 8000Apply the updated IngressRoute:
kubectl apply -f task-api-ingressroute-ratelimited.yamlOutput:
ingressroute.traefik.io/task-api-route configuredTest the rate limit by sending many requests quickly:
for i in {1..25}; do
curl -s -o /dev/null -w "%{http_code}\n" http://localhost/api/v1/tasks
doneOutput:
200
200
200
200
200
200
200
200
200
200
200
200
200
200
200
200
200
200
200
200
429
429
429
429
429After approximately 20 requests (the burst limit), Traefik returns 429 Too Many Requests. The rate limiter is protecting your backend.
Path Manipulation with Middlewares
Sometimes your backend expects a different path than what external clients use. Middlewares can transform paths.
StripPrefix Middleware
Remove a path prefix before forwarding. Create strip-prefix-middleware.yaml:
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: strip-api-prefix
namespace: task-api
spec:
stripPrefix:
prefixes:
- /api/v1Output:
(Manifest only)
If a client requests /api/v1/tasks, Traefik forwards /tasks to the backend. Useful when your internal services don't expect version prefixes.
AddPrefix Middleware
Add a path prefix before forwarding. Create add-prefix-middleware.yaml:
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: add-internal-prefix
namespace: task-api
spec:
addPrefix:
prefix: /internalOutput:
(Manifest only)
A request to /tasks becomes /internal/tasks when reaching the backend.
Headers Middleware
Add or modify HTTP headers. Create headers-middleware.yaml:
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: custom-headers
namespace: task-api
spec:
headers:
customRequestHeaders:
X-Forwarded-By: "traefik"
X-Real-IP: "" # Empty string removes the header
customResponseHeaders:
X-Served-By: "task-api-cluster"Output:
(Manifest only)
Chaining Multiple Middlewares
Apply multiple Middlewares in sequence:
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: task-api-route
namespace: task-api
spec:
entryPoints:
- web
routes:
- match: PathPrefix(`/api/v1/tasks`)
kind: Rule
middlewares:
- name: rate-limit # Applied first
- name: strip-api-prefix # Applied second
- name: custom-headers # Applied third
services:
- name: task-api
port: 8000Middlewares execute in order. Rate limiting happens before path stripping, which happens before header modification.
Enabling the Traefik Dashboard
Traefik includes a web dashboard for monitoring routes, services, and middlewares. Enable it by upgrading the Helm release:
helm upgrade traefik traefik/traefik -n traefik \
--set dashboard.enabled=true \
--set ingressRoute.dashboard.enabled=trueOutput:
Release "traefik" has been upgraded. Happy Helming!
NAME: traefik
LAST DEPLOYED: Mon Dec 30 10:45:00 2024
NAMESPACE: traefik
STATUS: deployed
REVISION: 2Access the dashboard via port-forward:
kubectl port-forward -n traefik svc/traefik 9000:9000Output:
Forwarding from 127.0.0.1:9000 -> 9000
Forwarding from [::1]:9000 -> 9000Open http://localhost:9000/dashboard/ in your browser. You'll see:
- HTTP Routers: Your IngressRoutes and their status
- HTTP Services: Backend services Traefik knows about
- HTTP Middlewares: All Middleware resources
- EntryPoints: Ports Traefik is listening on
The dashboard updates in real-time. Create a new IngressRoute, and it appears within seconds. This visibility is valuable for debugging routing issues.
When to Use Traefik vs Gateway API
Both Traefik and Gateway API solve the same problem—routing external traffic to internal services. The choice depends on your situation.
Use Traefik When:
| Scenario | Why Traefik |
|---|---|
| Quick development/staging setup | Install → route in 5 minutes |
| Team already knows Traefik | Existing expertise reduces learning curve |
| Don't need cross-vendor portability | Traefik CRDs are Traefik-only |
| Simpler configuration preferred | IngressRoute is more intuitive than Gateway API |
| Need dashboard out of the box | Built-in visualization |
Use Gateway API When:
| Scenario | Why Gateway API |
|---|---|
| Production with potential vendor changes | GatewayClass swap without route rewrites |
| Need role separation (platform vs app team) | Gateway owned by platform, HTTPRoute by apps |
| Want CNCF-standard portability | Industry standard, multiple implementations |
| Need advanced traffic splitting, mirroring | Native support vs Traefik-specific CRDs |
| Enterprise compliance requirements | Standard API easier to audit |
Decision Table
| Question | Traefik | Gateway API |
|---|---|---|
| Time to first route? | Minutes | 30+ minutes (install controller + CRDs) |
| Vendor lock-in? | Yes (Traefik CRDs) | No (standard API) |
| Role separation? | Limited | Built-in (GatewayClass/Gateway/HTTPRoute) |
| Learning curve? | Lower | Higher |
| Advanced features? | Via Middlewares | Via BackendTrafficPolicy |
| Multi-cluster? | Possible | Better supported |
For this book's learning path: We teach Traefik first because it's faster to understand. Once you've internalized traffic routing concepts with Traefik, Gateway API's abstractions will make more sense. Lessons 3-11 will then teach Gateway API as your production solution.
Exercises
Exercise 1: Install Traefik and Access Dashboard
If you haven't already:
- Install Traefik with Helm
- Enable the dashboard
- Access the dashboard at
localhost:9000/dashboard/
Verify you can see EntryPoints, Routers, Services, and Middlewares sections.
Exercise 2: Create IngressRoute for Task API
Create an IngressRoute that:
- Listens on EntryPoint
web - Matches path
/api/v1/tasks - Routes to the
task-apiService on port 8000
Test with curl http://localhost/api/v1/tasks.
Exercise 3: Add Rate Limiting Middleware
- Create a Middleware with:
average: 5requests per secondburst: 10requests
- Attach it to your IngressRoute
- Test by sending 15 requests quickly
Verify you see 429 responses after the burst limit.
Exercise 4: Add StripPrefix Middleware
- Create a StripPrefix Middleware that removes
/api/v1 - Chain it with your rate limit Middleware
- Verify the order matters: rate limiting should happen first
Check the Traefik dashboard to see both Middlewares attached to your route.
Reflect on Your Skill
You built a traffic-engineer skill in Lesson 0. Test and improve it based on what you learned.
Update Your Skill's Decision Logic
Your skill should now include Traefik as an option:
When should your skill recommend Traefik?
- Development/staging environments needing quick setup
- Teams already using Traefik
- Simpler configuration requirements
- Need built-in dashboard for monitoring
When should your skill recommend Gateway API?
- Production environments requiring vendor portability
- Multi-team setups needing role separation
- Advanced traffic patterns (splitting, mirroring)
- CNCF compliance requirements
What Traefik Patterns Are Worth Encoding?
Consider adding these to your skill:
- Standard IngressRoute template with EntryPoints and match rules
- Rate limiting Middleware with configurable average/burst
- Middleware chaining pattern (rate limit → strip prefix → headers)
- Dashboard enablement for development clusters
Your skill should generate the appropriate CRDs based on whether Traefik or Gateway API is chosen.
Core Concept
Traefik provides a simpler ingress experience with IngressRoute CRDs and Middleware resources that replace Ingress annotations with structured YAML, offering fast time-to-first-route while preparing you for Gateway API's more powerful abstractions.
Key Mental Models
- EntryPoints -> Routers -> Middlewares -> Services: Request flow through Traefik's four components
- IngressRoute CRD: Cleaner syntax than Ingress annotations with explicit match rules and middleware chains
- Middleware Composition: Rate limiting, path stripping, and header modification as chainable components
- Traefik vs Gateway API Trade-off: Faster setup but vendor lock-in vs. portable configurations
Critical Patterns
- Install Traefik with Helm:
helm install traefik traefik/traefik -n traefik --create-namespace - Match rules use expression syntax:
PathPrefix('/api/v1/tasks') && Method('POST') - Middlewares attach to routes in order: rate-limit -> strip-prefix -> headers
- Enable dashboard for route debugging:
helm upgrade --set dashboard.enabled=true
AI Collaboration Keys
- Generate IngressRoute with specific match expressions
- Design Middleware chains for request transformation
- Compare Traefik configuration to equivalent Gateway API
Common Mistakes
- Using Traefik CRDs in production when Gateway API portability is needed
- Forgetting to chain Middlewares in correct order (rate limit before path strip)
- Not enabling dashboard for debugging routing issues
Connections
- Builds on: Lesson 1 (Ingress Fundamentals) understanding of routing concepts
- Leads to: Lesson 3 (Gateway API - The New Standard) for portable, role-separated routing