Traefik: canary deployments by using weighted load balancing
In the ever-evolving landscape of web services, the need for efficient load balancing and service discovery becomes paramount, especially when dealing with dynamic and scalable environments. While Nginx and HAProxy have been the go-to choices for many, Traefik emerges as a compelling alternative that excels in automatic and dynamic configurability. Here's how it stands out.
Why Traefik for Small-Scale Deployments?
Traefik shines in scenarios where deploying a full-fledged orchestrator like Kubernetes might be overkill due to resource requirements and complexity. When combined with Docker, even on a single machine, Traefik provides an ideal solution that aligns with modern development best practices. It simplifies canary deployments, allowing for safe and incremental updates, by leveraging weighted load balancing.
Canary Deployments Simplified
Consider a basic setup with one machine hosting a Docker daemon and a Traefik container managing incoming requests. Implementing a canary deployment model becomes a breeze. By adjusting the weights assigned to your containers, you can control the traffic flow between your stable and new service versions.
Example: Weighted Load Balancing with Traefik v1
In Traefik v1, setting up weighted load balancing was straightforward. You'd start your Traefik container and use labels to define the weight of your service containers.
For instance:
# Launch Traefik v1.7 as the reverse proxy
docker run -d \
--name my_traefik \
-p 8080:80 \
-v /var/run/docker.sock:/var/run/docker.sock \
traefik:v1.7 \
--docker \
--docker.exposedbydefault=false
# Start your application containers with new weight distributions
docker run -d --name app_v1 \
--label "traefik.enable=true" \
--label "traefik.backend=myapp" \
--label "traefik.frontend.rule=Host:myapp.local" \
--label "traefik.weight=30" \
nginx:stable
docker run -d --name app_v2 \
--label "traefik.enable=true" \
--label "traefik.backend=myapp" \
--label "traefik.frontend.rule=Host:myapp.local" \
--label "traefik.weight=70" \
nginx:stable-alpine
Transitioning to Traefik v2
With the introduction of Traefik v2, the landscape changed. The shift from the frontend-backend paradigm to routers and services, along with explicit middleware layers, meant rethinking the configuration approach. Traefik v2 eliminated the weight directive but introduced the Weighted Round Robin Service (WRR), albeit with limitations.
Setting up Weighted Load Balancing in Traefik v2
WRR required a combination of file and Docker providers to implement. For example, a file provider configuration might look like this:
# dynamic_config.yml
http:
routers:
myapp-router:
rule: "Host(`myapp.local`)"
service: myapp-service
services:
myapp-service:
weighted:
services:
- name: app-v1-service@docker
weight: 3
- name: app-v2-service@docker
weight: 7
Now, fire up the containers with adjusted labels to align with the services defined:
Start Traefik first:
docker run -d --rm --name traefik-v2.5 \
-p 9999:80 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v `pwd`:/etc/traefik_providers \
traefik:v2.5 \
--providers.docker \
--providers.docker.exposedbydefault=false \
--providers.file.filename=/etc/traefik_providers/file_provider.yml
Then start your apps:
# Starting containers with Traefik v2 labels
docker run -d --name app_v1 \
--label "traefik.enable=true" \
--label "traefik.http.services.app-v1-service.loadbalancer.server.port=80" \
nginx:stable
docker run -d --name app_v2 \
--label "traefik.enable=true" \
--label "traefik.http.services.app-v2-service.loadbalancer.server.port=80" \
nginx:stable-alpine
Observations and Adjustments
You can modify weights or toggle the canary service simply by altering the file provider's YAML config. Traefik's dynamic response to changes ensures a smooth transition.
To verify your load distribution, the following command can be run:
for i in {1..50}; do curl -s -o /dev/null -D - -H "Host:myapp.local" localhost:8080 | grep X-Powered-By; done | sort | uniq -c
This test helps you to ascertain that your setup is working correctly, distributing the load according to the specified weights.
Conclusion
Even with the steeper learning curve of Traefik v2, the benefits of automatic service discovery and ease of load balancing in a dynamic environment are undeniably valuable.