Preface
Previously, the applications I deployed in my home data center (including my blog) had a simple 4-tier network architecture: Cloudflare Tunnel -> SafeLine WAF Community Edition -> ZEVENET Load Balancer Community Edition -> Main Blog Site (Redundant Blog Site). Among them, the role of the ZEVENET load balancer was to monitor the health of the main blog site. If the main site went down, it would automatically forward requests to the redundant blog site in the home data center, thereby achieving high availability for the blog.
However, because the ZEVENET Community Edition seemed to have never been updated, which annoyed me, my original idea of writing a tutorial about ZEVENET was repeatedly put off. Additionally, some time ago, due to strengthening the security policies on the WAF, and because the stability of the main blog site stood the test, I simply removed ZEVENET, which actually felt quite good.
However, this single-point-of-failure structure always made me feel uneasy. After thinking it over, I felt that adding a load balancer was still the safest bet. But I really didn't want to use the ZEVENET Community Edition, which hadn't been upgraded in ages, and I also felt ZEVENET wasn't lightweight enough. Wanting to find a more lightweight solution, I had to start searching.
ZEVENET actually should be considered the load balancing solution that best met my requirements. Its web interface configuration logic and basic configuration elements are very similar to professional equipment like F5 and A10 (unfortunately, I couldn't get a long-term license for F5's BIGIP VE or A10's vThunder, otherwise why would I bother looking for alternatives~~). Although the features and monitoring content provided by the Community Edition are too minimal, they were barely enough. However, the Community Edition that absolutely refuses to upgrade (I guess they don't care about this segment at all, and their focus is still on the paid version) is really frustrating. Its image on Docker Hub hasn't been updated in 6 years:

This is not something an upgrade fanatic like me, who wants to upgrade at every turn, can accept, so in the end, I had to reluctantly give it up.
But which one to choose? Actually, before professional load balancing hardware became popular, the most famous load balancing software on Linux systems was LVS (which is still used in many companies' production environments today). In terms of functionality, it was completely sufficient for me. Nginx with the stream module can also perform Layer 7 load balancing (which is also used in many production environments today and has very strong performance). However, these two most common software solutions both have one major issue by default: they lack a convenient Web UI (as someone used to F5, not having a convenient Web UI is truly unbearable~).
LVS does provide a default web interface, but unfortunately, you can only view some basic parameters. In the past, there were many open-source Web UI projects for LVS on the internet, but unfortunately, most of them have disappeared now (probably because fewer people use LVS). There are still some left, such as roxy-wi, but its official site doesn't seem to provide a Docker deployment method (GitHub homepage:https://github.com/roxy-wi/roxy-wi), and I really didn't want to go through source code deployment just for a UI. There are some unofficial ones on Docker Hub, but they basically haven't been updated for over a year, so I had to give up.
Nginx does have quite a few Web UI projects supporting it, but unfortunately, they are all targeted at Nginx's overall functionality and are not specifically optimized for load balancing. Since I only need the load balancing feature, this was quite frustrating—it felt like using a cannon to shoot a mosquito, and not even hitting it. Of course, the biggest advantage of Nginx for Layer 7 load balancing is its strong performance, but my blog's traffic is basically just origin-pull requests sent from Cloudflare (normal visits access cached content on Cloudflare, and only a few actually need to pull from the origin), so there are virtually no performance requirements~. Thus, I eventually gave up on it as well.
At this point, a new option was discovered: Traefik.
What is Traefik?
Introduction to Traefik
Traefik is a modern reverse proxy and load balancer designed specifically for microservices and containerized environments. It can dynamically manage backend service routing, making it an ideal choice for automated cloud-native environments.
The main features of Traefik are as follows:
- Dynamic Configuration
• Traefik supports multiple configuration methods, including files, APIs, Docker labels, and Kubernetes CRDs, enabling real-time response to changes in service topology.
- Automatic Service Discovery
• Traefik can automatically discover services registered through platforms like Docker and Kubernetes, and automatically update routing rules without manual intervention.
- Built-in HTTPS Support
• Supports automatic application and management of Let’s Encrypt SSL/TLS certificates, providing secure HTTPS communication.
- Multi-protocol Support
• In addition to HTTP and HTTPS, Traefik also supports multiple protocols such as TCP, UDP, and WebSocket.
- Middleware Support
• Provides flexible middleware functionality, allowing operations such as authentication, rewriting, and rate limiting on requests.
- Visual Interface
• Provides an intuitive dashboard for monitoring service and routing status.
- High Performance
• Traefik is developed in Go, offering excellent performance and supporting high-concurrency request processing.
Competitive Analysis of Traefik, Nginx, and HAProxy
Comparison of Load Balancing Features among Traefik, Nginx, and HAProxy:
| Feature | Traefik | Nginx | HAProxy |
|---|---|---|---|
| Architecture & Deployment | |||
| Positioning | Focuses on cloud-native reverse proxy and load balancing | General-purpose reverse proxy server, supporting load balancing | High-performance load balancer with extremely high stability |
| Dynamic Configuration | Natively supports dynamic configuration (updated via API or files) | Requiresreloadto reload configuration files |
Partially supports dynamic configuration using the Runtime API |
| Integration capabilities | Built-in service discovery support for Kubernetes, Docker, etc. | Partial integration capabilities can be achieved through plugins or manual configuration | No native support, requires manual configuration or reliance on other tools |
| Performance | |||
| Throughput | Slightly lower than Nginx and HAProxy, suitable for small to medium traffic | High performance, suitable for medium loads | Optimal performance, suitable for high concurrency and low latency requirements |
| Concurrency handling capability | Medium, depending on the number and complexity of backend services | Efficiently handles a large number of concurrent requests | Extremely high, specifically designed for high concurrency |
| Resource usage | Relatively high (due to Go language runtime overhead) | Moderate resource usage, even lower after configuration optimization | Extremely low resource usage, especially suitable for resource-constrained environments |
| Features and characteristics | |||
| Load balancing algorithms | Supports multiple algorithms (round-robin, random, etc.), relatively flexible | Provides multiple algorithms such as round-robin and least connections | Provides more advanced load balancing strategies and algorithm support |
| SSL support | Automatic configuration and updates (Let’s Encrypt integration) | Manual configuration of certificates, powerful support | Manual configuration of certificates, highly flexible |
| Health Checks | Built-in support, simple configuration | Manual setup, extending features through plugins | Powerful health check features, suitable for complex scenarios |
| Connection rate limiting and security | Provides basic rate limiting features | Supports rate limiting and complex security configurations | Provides fine-grained rate limiting and security control |
| Web UI support | |||
| Supported or not | Native support, with an intuitive dashboard | Not provided, requires third-party tools or plugins | Not provided, requires external tools |
| Web UI features | Real-time viewing of routing status, load balancing status, etc. | No native support, high cost of manual setup | No native support, high cost of manual setup |
As can be seen from the comparison above, Traefik has more powerful features and built-in support for Web UI. Although its throughput is slightly lower than Nginx and HAProxy, I don't care about throughput at all~ So after a comprehensive comparison, Traefik is indeed more suitable for me to do load balancing.
Applicable Scenarios for Traefik
Traefik's applicable scenarios cover traditional and modern application deployment needs. Whether it is a containerized microservices architecture or diverse enterprise application scenarios, Traefik is an efficient, flexible, and feature-rich solution:
| Application Scenarios | Scenario Description | Features | Example |
|---|---|---|---|
| Containerized Environments | Environments using container orchestration tools such as Docker Compose, Docker Swarm, and Kubernetes | – Automatic Service Discovery: Automatically configures routing based on Docker labels or Kubernetes CRDs – Dynamic Load Balancing: Adjusts traffic in real-time as containers start, stop, or scale – Built-in HTTPS Support: Automatically requests and manages TLS/SSL certificates |
– Dynamically route and balance service traffic in Docker Swarm – Manage traffic as an Ingress Controller in Kubernetes |
| Non-containerized environments | Applications hosted on traditional virtual machines or physical servers | – Set up routing via static configuration files or REST API – Provide load balancing, health checks, and automatic retry functions – Support multiple protocols (HTTP, HTTPS, TCP, UDP) |
– Provide load balancing for multiple independently running application instances – Provide dynamic routing management for non-containerized enterprise applications |
| Container orchestration environments (Kubernetes) | Applications using Kubernetes in microservices architectures | – Act as a Kubernetes Ingress Controller, supporting dynamic configuration and automatic service discovery – Provide functions such as traffic distribution, session persistence, and weight allocation |
– Dynamically allocate service traffic within Kubernetes clusters – Use canary releases and blue-green deployments to improve system stability |
| Edge computing and IoT environments | Data traffic distribution for IoT gateways or edge nodes | – Support multi-protocol (TCP, UDP, HTTP/HTTPS) handling of traffic from different devices and nodes – Middleware features enable rate limiting and authentication |
– Real-time data stream routing and load sharing on edge computing platforms – Traffic optimization for communication between IoT devices |
| Hybrid cloud and multi-cloud environments | Services deployed across multiple cloud service platforms or cross-cloud environments | – Multi-entry point support, easily integrating traffic from different cloud platforms – Provide unified traffic management and cross-region load balancing |
– Coordinate service traffic between AWS and Azure in hybrid clouds – Traffic distribution and access control between different regions |
| Enterprise intranet environments | Unified management of internal enterprise applications | – Provide reverse proxy and load balancing functions, supporting path or subdomain routing – Work with middleware to achieve authentication, traffic limiting, and other functions |
– Provide a single entry point for multiple internal applications (such as CRM, ERP systems) – Provide high availability and secure access for intranet services |
| Cross-regional distributed services | Distributed applications targeting global users | – Support weight-based traffic allocation and health checks – Can be combined with GeoDNS to achieve geo-aware traffic routing |
– Distribute traffic across multiple data centers – Optimize latency for global user access |
| Development and testing environments | Developers need to quickly deploy and debug services | – Quickly set up a local testing environment with HTTPS support – Dynamically adjust routing to simulate multi-version release strategies (such as blue-green deployment) |
– Build a rapid debugging environment for development teams – Test load balancing strategies and routing rules |
As can be seen from the table above, in my home data center, the load balancing of deployed applications is suitable for the second scenario: non-containerized environments.
Note: My main blog site and redundant site are on two separate physical machines (don't put all your eggs in one basket, otherwise redundancy is meaningless). If they were both deployed via Docker on the same physical machine, it would be suitable for load balancing within a containerized environment.
Traefik Hands-on Practice
Common Scenarios
Docker Scenario
Suitable for services whose target is running in Docker containers, dynamically managing services and routing rules through Docker labels.
• Advantages: High degree of automation, seamless integration with container orchestration (such as Docker Compose, Swarm).
• Scenario: Microservice architecture, containerized deployment.
Non-Docker Scenario
Suitable for scenarios such as intranet physical machines or virtual machines. By manually configuring entry points and service load balancing, dynamic configuration can come from various providers, such as files, APIs, or service discovery tools like Consul.
• Advantages: Supports multiple service discovery methods, suitable for traditional architectures.
• Scenario: Intranet application load balancing, virtual machine cluster traffic distribution.
Dynamic File Configuration Scenario (A specific implementation of the non-Docker scenario)
Completely based on files to achieve the separation of static and dynamic configuration. Dynamic configuration files define routing rules and service load balancing without requiring other external services.
• Advantages: Simple configuration, suitable for resource-limited or testing environments.
• Scenario: Small-scale intranet load balancing, development and testing environments.
Kubernetes Scenario
Integrated through the Kubernetes provider, dynamically obtaining routing and service configurations directly from Ingress resources.
• Advantages: Best practice for cloud-native scenarios, supporting auto-scaling and service discovery.
• Scenario: Container orchestration platforms based on Kubernetes.
| Scenario | Configuration Source | Applicable Environment | Dynamism |
|---|---|---|---|
| Docker Environment | Docker Labels | Containerized Services | High, real-time discovery and updates |
| Non-Docker Environment | Multiple sources (files, etc.) | Intranet, physical machines, virtual machine clusters | Medium, depends on configuration method |
| Dynamic File Configuration | Configuration File | Small-scale intranet, development and testing | Medium, requires reload upon modification |
| Kubernetes Environment | Kubernetes Ingress | Cloud-native, container orchestration platforms | High, dynamic discovery and updates |
“Dynamic file configuration” is essentially just an implementation form of the ”non-Docker environment”, and there was originally no need to separate it into a specific scenario. The reason it is singled out is that in practical use,Dynamic File Configuration it has some unique use scenarios and characteristics that make it seem “special”:
Independence of Dynamic File Configuration
Dynamic file configuration does not depend on any external services (such as Docker, Kubernetes, or Consul), completely separating static configuration and dynamic configuration through files.
• Non-Docker Environment Other forms within it may require additional services to provide dynamic configuration, such as Consul, Etcd, etc.;
• Dynamic File Configuration Only manual management of configuration files is required, suitable for some simple or resource-constrained environments.
Typical Application Scenarios of Dynamic File Configuration
Dynamic file configuration is often used for:
• Development or testing environments: Quickly build a simple load balancing or routing system without additional dependencies.
• Small-scale production environments: No complex service discovery requirements, only needing to statically define a few backend services.
These scenarios and those requiring service discovery Non-Docker Environment(such as dynamically scaled virtual machine clusters) are somewhat different.
Simplified Deployment Method
The implementation of dynamic file configuration is more user-friendly:
• Only two files are needed (traefik.yml and the dynamic configuration file), which can be reloaded after modification without complex configuration;
• Easy to understand and deploy for novice users and resource-limited environments.
Based on the above 3 reasons, I treat ”file dynamic configuration” as a separate category, but it still belongs to the ”non-Docker scenario”. The deployment later in this article will adopt the ”file dynamic configuration” method.
Static Configuration File: traefik.yml
Traefik officially recommends deploying via Docker, whether using the ”docker run” method or the docker-compose method. However, regardless of the method, a static configuration file named ”traefik.yml” is required.
“traefik.yml” is mainly used to define Traefik's global settings and entry point configurations. Static configuration is loaded when Traefik starts, unlike dynamic configuration (used to define specific routes and services), which is typically loaded via files, Docker labels, Kubernetes, etc.
The following is a classified explanation and detailed breakdown of the traefik.yml file content based on different scenarios:
Docker Environment
In a Docker environment, the traefik.yml file mainly configures Traefik's global behavior and its integration with Docker. The example file is as follows:
entryPoints:
web:
address: ":80"
websecure:
address: ":443"
api:
dashboard: true
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
log:
level: "INFO"
accessLog: {}
certificatesResolvers:
myresolver:
acme:
email: "[email protected]"
storage: "acme.json"
httpChallenge:
entryPoint: "web"
Explanation of the above content:
- entryPoints
Defines Traefik's entry points (ports and protocols).
• web is used for HTTP traffic, listening on port 80.
• websecure is used for HTTPS traffic, listening on port 443.
- api
Enables Traefik's Web admin dashboard. Accessed via /dashboard.
- providers.docker
Configures Traefik as a service discovery tool for Docker containers.
• endpoint: Specifies the Docker API address, typically unix:///var/run/docker.sock.
• exposedByDefault: Set to false, meaning only explicitly labeled containers will be exposed to Traefik.
- log 和 accessLog
• log: Defines the log level (INFO, DEBUG, ERROR).
• accessLog: Enables access logs to record client requests.
- certificatesResolvers
Configures automatic acquisition of HTTPS certificates (Let’s Encrypt).
• Uses httpChallenge verification, handling certificate requests through the web entry point.
• Certificate information is stored in the acme.json file.
Non-Docker Environment (e.g., Intranet Application Load Balancing)
In this scenario, Traefik's static configuration is mainly used to define the load balancing logic and entry points for backend services. The example file is as follows:
entryPoints:
web:
address: ":80"
providers:
file:
filename: "dynamic.yml"
log:
level: "DEBUG"
accessLog: {}
api:
dashboard: true
And the corresponding dynamic configuration file dynamic.yml might look like this:
http:
routers:
my-router:
rule: "Host(`example.com`)"
service: my-service
entryPoints:
- web
services:
my-service:
loadBalancer:
servers:
- url: "http://192.168.1.101:8080"
- url: "http://192.168.1.102:8080"
Content Explanation
- entryPoints
Defines the listening entry point, for example, :80 to handle HTTP requests.
- providers.file
• Specifies the file path of the dynamic configuration source, such as dynamic.yml.
• Dynamic configuration defines specific routing rules and load balancing backends.
- http.routers(Dynamic Configuration)
Defines routing rules:
• rule: Specifies the matching rule for requests (such as domain matching).
• entryPoints: Binds to the entry points in the static configuration.
- http.services(Dynamic Configuration)
Defines services and their load balancing strategies:
• loadBalancer: Contains the addresses of multiple backend servers, and Traefik will automatically distribute traffic.
File Dynamic Configuration (A Specific Implementation of Non-Docker Environment)
The configuration is very similar to the non-Docker environment (since it inherently belongs to the non-Docker environment~), especially when not relying on other providers, the separation of static and dynamic configurations can be fully achieved through files. For example:
entryPoints:
web:
address: ":8080"
providers:
file:
directory: "/etc/traefik/dynamic/"
Example of a dynamic configuration file:
http:
routers:
static-router:
rule: "Path(`/static`)"
service: static-service
services:
static-service:
loadBalancer:
servers:
- url: "http://localhost:3000"
Traefik configures two routers by default:
- api router: Responsible for handling requests to Traefik's API interface. Through this router, users can access Traefik's API to perform operations such as monitoring and management. Usually, its address will be something like http://
:8080/api format. -
dashboard router: Responsible for handling requests to the Traefik Web Dashboard. Traefik's Web Dashboard provides a graphical interface to monitor and manage Traefik's status and configuration. By default, the Dashboard address is usually http://
:8080/dashboard, but this address can be modified through configuration.
These two routers are usually enabled by default when Traefik starts, and can be adjusted via configuration files or command-line options. By default, both the API and Dashboard are bound to port 8080. You can modify their ports, access methods (such as enabling TLS), etc., as needed.
Therefore, assuming you configure 1 router yourself in dynamic.yml (as above), the total number of routers would be 3.
Kubernetes Ingress Controller
When acting as a Kubernetes Ingress controller, the traefik.yml file needs to be configured to obtain dynamic configuration from the Kubernetes API:
entryPoints:
web:
address: ":80"
websecure:
address: ":443"
providers:
kubernetesIngress: {}
certificatesResolvers:
myresolver:
acme:
email: "[email protected]"
storage: "acme.json"
httpChallenge:
entryPoint: "web"
Content Explanation
- providers.kubernetesIngress
Tells Traefik to extract routing rules and service configurations from Kubernetes Ingress resources.
- certificatesResolvers
Same as the Docker environment, enabling automatic HTTPS certificate retrieval.
Traefik Deployment
docker run Method
Preparation
Assuming I need to load balance port 80 of 3 different hosts on the intranet, and the IP addresses of these 3 hosts are 192.168.0.1, 192.168.0.2, and 192.168.0.3, the operation steps are as follows:
Create a new working directory:
mkdir -p /docker/traefik
Create a new static configuration file:
touch /docker/traefik/traefik.yml
Paste the following content into it and save:
entryPoints:
web:
address: ":80" # 为 HTTP 添加 entry point
websecure:
address: ":443" # 为 HTTPS 添加 entry point
traefik:
address: ":8080" # 显式绑定 Dashboard 到 8080 端口
providers:
file:
filename: "/etc/traefik/dynamic.yml" # 指定动态配置文件在traefik容器"内部"的路径
watch: true
log:
level: "INFO"
accessLog: {}
api:
dashboard: true
insecure: true # 启用不安全模式,仅用于测试环境,这条很重要,否则默认不能使用http的8080端口进行管理
certificatesResolvers:
myresolver:
acme: # 启用本地acme进行ssl证书的自动更新
email: "[email protected]" # 替换为你的邮箱
storage: "/etc/traefik/acme.json" # 指定容器内部acme配置文件
httpChallenge:
entryPoint: web # 使用 HTTP-01 验证
Create a new dynamic configuration file:
touch /docker/traefik/dynamic.yml
Then paste the following content into it and save:
http:
routers:
blog-router:
rule: "Host(`your-domain.com`)"
entryPoints:
- web
service: blog-service
tls:
certResolver: myresolver
services:
blog-service:
loadBalancer:
servers:
- url: "http://192.168.0.1"
- url: "http://192.168.0.2"
- url: "http://192.168.0.3"
healthCheck:
path: "/healthcheck" # 对指定路径健康检查,这里假设是"/healthcheck"
interval: "10s" # 检查间隔
timeout: "5s" # 检查超时时间
passHostHeader: true
Create a new acme configuration file:
touch /docker/traefik/acme.json
chmod 600 /docker/traefik/acme.json
The acme.json file only needs to be created as a blank file when used for the first time. Traefik will automatically store ACME (Let's Encrypt) certificates and related data in this file at runtime, which is why appropriate write permissions need to be configured.
If you do not need to load balance ports of the HTTPS protocol, simply delete the relevant content in traefik.yml and dynamic.yml, for example:
traefik.yml
entryPoints:
web:
address: ":80" # 为 HTTP 添加 entry point
traefik:
address: ":8080" # 显式绑定 Dashboard 到 8080 端口
providers:
file:
filename: "/etc/traefik/dynamic.yml" # 指定动态配置文件在traefik容器"内部"的路径
watch: true #对动态配置文件进行实时监控,如果配置有改动,立即载入新配置
log:
level: "INFO"
accessLog: {}
api:
dashboard: true
insecure: true # 启用不安全模式,一般用于测试环境,这条配置很重要,否则默认不能使用http的8080端口进行管理
dynamic.yml
http:
routers:
blog-router:
rule: "Host(`your-domain.com`)"
entryPoints:
- web
service: blog-service
services:
blog-service:
loadBalancer:
servers:
- url: "http://192.168.0.1"
- url: "http://192.168.0.2"
- url: "http://192.168.0.3"
healthCheck:
path: "/healthcheck" # 对指定路径健康检查,这里假设是"/healthcheck"
interval: "10s" # 检查间隔
timeout: "5s" # 检查超时时间
passHostHeader: true
Deployment
The docker run command format is as follows:
docker run -d --name traefik --restart=always --net=public-net \
-p 80:80 \
-p 443:443 \
-p 8080:8080 \
-v /docker/traefik/traefik.yml:/etc/traefik/traefik.yml \
-v /docker/traefik/dynamic.yml:/etc/traefik/dynamic.yml \
-v /docker/traefik/acme.json:/etc/traefik/acme.json \
traefik:v2.11
Note 1: If you do not need to load balance the HTTPS protocol port, delete-p 443:443 \and-v /docker/traefik/acme.json:/etc/traefik/acme.json \these two lines.
Note 2: --net=public-netIt is not mandatory in ”non-Docker scenarios”, but in a ”Docker scenario” (when load balancing certain Docker containers on the same host), Traefik and these Docker containers must be in the same bridge network.
Deployment via docker-compose
In fact, it is just converting the command in docker run format into a docker-compose.yml file:
version: '3.8'
services:
traefik:
image: traefik:v2.11
container_name: traefik
restart: always
networks:
- public-net
ports:
- "80:80"
- "443:443"
- "8080:8080"
volumes:
- /docker/traefik/traefik.yml:/etc/traefik/traefik.yml
- /docker/traefik/dynamic.yml:/etc/traefik/dynamic.yml
- /docker/traefik/acme.json:/etc/traefik/acme.json
networks:
public-net:
external: true
Description:
- services: Defines the service traefik.
-
networks: Specifies the use of the external network public-net, ensuring that this network has been created via docker network create public-net (not mandatory here).
-
volumes: Mounts the host files into the container.
-
ports: Maps container ports to the host.
After saving this content as a docker-compose.yml file, enter the same directory and start it with the following command:
docker-compose up -d
Advanced Configuration: Priority-Based Configuration Concept
Multi-Priority Configuration Demonstration
The previous section only used Traefik to complete the most basic and simple load balancing configuration, but Traefik can also implement more complex logic, such as services implementing hot standby based on ”priority”. For example: for access to any domain name, the service at 192.168.0.1:80 has the highest priority, the service at 192.168.0.2:80 has medium priority, and the service at 192.168.0.3:80 has the lowest priority. As long as the 192.168.0.1:80 service is normal, all access requests to any domain name will only be sent to it; if the 192.168.0.1:80 service goes down, the requests will be sent to the 192.168.0.2:80 service; if the 192.168.0.2:80 service also goes down, the requests will be sent to the 192.168.0.3:80 service. To achieve this function, the content of dynamic.yml can be set as follows:
http:
routers:
blog-router:
rule: "HostRegexp(`{host:.+}`)" # 匹配所有域名
entryPoints:
- web
service: high-priority-service # 默认使用高优先级服务
middlewares:
- strip-prefix # 中间件示例(可按需调整)
services:
high-priority-service:
loadBalancer:
servers:
- url: "http://192.168.0.1" # 高优先级服务地址
healthCheck:
path: "/healthcheck" # 健康检查路径
interval: "10s" # 健康检查间隔
timeout: "5s" # 健康检查超时时间
passHostHeader: true # 传递原始 Host Header
medium-priority-service:
loadBalancer:
servers:
- url: "http://192.168.0.2" # 中等优先级服务地址
healthCheck:
path: "/healthcheck" # 健康检查路径
interval: "10s" # 健康检查间隔
timeout: "5s" # 健康检查超时时间
passHostHeader: true # 传递原始 Host Header
low-priority-service:
loadBalancer:
servers:
- url: "http://192.168.0.3" # 最低优先级服务地址
healthCheck:
path: "/healthcheck" # 健康检查路径
interval: "10s" # 健康检查间隔
timeout: "5s" # 健康检查超时时间
passHostHeader: true # 传递原始 Host Header
middlewares:
strip-prefix:
stripPrefix:
prefixes:
- "/api" # 示例:如果请求包含 "/api",会移除此前缀
routers:
- blog-router:services):
rule: "HostRegexp(`{host:.+}`)" # Match all domains
• medium-priority: Medium priority, enabled only when high priority is unavailable.
• low-priority: Lowest priority, enabled only when the first two are both unavailable.
- Health Check (healthCheck):
• Health check path /healthcheck, required to be provided by each server.
• If the health check fails, Traefik will mark the service as unavailable.
- Routers (routers):
• blog-router points to the high-priority service by default.
- Middleware (middlewares):
• retry-medium: Attempts to send traffic to high-priority, and switches to medium-priority if it fails.
• retry-low: Switches to low-priority when medium-priority is also unavailable.
Multiple services corresponding to different priorities
Traefik uses high, medium, and low service configurations to correspond to different priorities in order to achieve more efficient control in load balancing and traffic scheduling, especially to immediately redirect access requests to lower-priority services when high-priority services fail, thereby achieving a ”hot standby” effect.
Clear Traffic Priority Control
Necessity of Priority Control:
• In a multi-service environment, there may be a primary service (high-priority service) responsible for handling the most important or the majority of requests; at the same time, there may be backup services (medium and low-priority services) that act as redundancy when the primary service is unavailable.
• In this case, simply using the load balancing weight configuration (e.g., setting weight ratios) cannot effectively achieve priority control, because weight merely distributes traffic proportionally without considering the relative importance and availability of the services.
• For example, if weight is used, traffic will be distributed according to the weights, which may cause low-priority services to bear a portion of the traffic even when high-priority services have not failed, thereby affecting performance or resource allocation.
Use of High, Medium, and Low Priorities:
• The high-priority service is set as the default service, meaning it should carry most of the traffic under normal circumstances.
• Medium and low-priority services are backup or failover services; traffic will only transfer to these services when there is an issue with the high-priority service.
• This approach ensures system stability and high availability under different circumstances through simple priority control and traffic routing rules (such as health checks).
Requirements for Health Checks and Failover
Health Check Mechanism: Traefik's built-in health check mechanism can monitor service availability in real time. If a service fails the health check, Traefik will automatically redirect traffic to healthy services. In this scenario, priority configuration becomes particularly important.
• High-Priority Service: Prioritizes handling normal requests, and only downgrades to medium or low-priority services when it cannot function properly.
• Medium and Low-Priority Services: These services are only enabled when high-priority services fail or become unavailable. Therefore, they will only receive traffic when health checks fail.
Through this priority strategy, the system can automatically switch to backup services when a service failure occurs, avoiding reliance on weight to distribute traffic, thereby reducing issues caused by inaccurate weights or inappropriate proportional distribution.
Simplifying Configuration and Logic
Reducing Configuration Complexity: Configuring high, medium, and low-priority services is simpler than distributing traffic through weight. With clear priority division, administrators can clearly know which services are critical and which are backups, without needing to adjust weight configurations, relying solely on the health status of services to determine traffic forwarding.
More Intuitive Failover: In priority configuration, traffic forwarding decisions do not depend on weights, but are determined by the health status and priority of the services. This allows for more direct traffic scheduling, simplifying configuration and decision-making for operations personnel.
Flexible Traffic Management
Through clear priority configuration, Traefik can dynamically adjust traffic forwarding based on the health status and importance of services. Unlike weight, priority configuration ensures that traffic switching between services is based on actual availability and business needs, rather than just static traffic distribution ratios.
Traefik supports the weight feature; however, weight mainly controls the amount of load traffic for different services, which is different from the concept of priority:
• `weight` cannot explicitly define priority: In Traefik, `weight` is mainly used to control the proportional distribution of traffic (for example: 80% traffic to Service A, 20% traffic to Service B). However, it does not set an explicit priority for each service, but is just a simple traffic distribution ratio.
• Avoid traffic misdirection: In some scenarios, using `weight` may cause traffic to be incorrectly distributed to services that should not bear traffic, especially when system failures or load surges occur. Using high, medium, and low priority configurations ensures that traffic only switches to low-priority services under specific conditions.
• Flexibility in control and monitoring: By using services with different priorities, the system is more flexible in control and monitoring. When traffic switches from a high-priority service to a low-priority service, it can be easily identified through logs or monitoring and adjusted in time. The `weight` configuration may obscure this monitoring, making it difficult to identify whether traffic is distributed according to the expected priority.
Actually, the main reason is that Traefik does not directly support the ”priority” mechanism of traditional load balancing devices: setting different priority numbers for different services, where load balancing is only performed among services with the same priority number; otherwise, requests are only sent to services with higher priority numbers. If this feature were supported, there would be no need for so much hassle.
Introduction to serversTransports
`serversTransports` is a key parameter in Traefik configuration, used to define communication parameters with upstream servers, especially in terms of HTTP and HTTPS transport settings. It allows you to configure specific network transport options for Traefik's load balancer, such as TLS configuration, request header settings, maximum connections, etc. Through this configuration, you can optimize the communication between Traefik and backend servers, improving performance, stability, and security. A sample configuration is as follows:
http:
serversTransports:
my-transport:
lifeCycle:
requestAcceptGraceTimeout: 30s # 请求接受的优雅关闭超时
forwardProxy:
address: "http://proxy.example.com:3128" # 上游代理地址
responses:
headers:
customHeader: "X-Custom-Header-Value" # 自定义请求头
tls:
minVersion: VersionTLS13 # 最低 TLS 版本
cipherSuites:
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 # 支持的加密套件
maxIdleConnsPerHost: 10 # 每个主机最大空闲连接数
idleTimeout: 5m # 空闲连接超时时间
disableHTTPKeepAlive: true # 禁用 HTTP Keep-Alive
maxConns: 50 # Traefik 与后端服务的最大连接数
The parameters involved in the sample configuration are introduced as follows:**
- tls
Used to set the TLS configuration, specifying the minimum TLS version and cipher suites used when communicating with backend servers. For example, strong encryption algorithms can be enabled through this configuration to ensure the security of data transmission.
• minVersion: Minimum TLS version (e.g., VersionTLS13).
• cipherSuites: List of supported cipher suites.
- lifeCycle.requestAcceptGraceTimeout
Sets the graceful shutdown timeout for request acceptance. During this period, Traefik will wait for requests on existing connections to complete before closing, ensuring that client requests are processed normally before the connection is closed.
- forwardProxy
If you need to access backend services through an upstream proxy, you can use this parameter to specify the address of the proxy server.
- responses.headers
Sets custom response headers. Specific request headers can be attached when Traefik sends requests to upstream servers.
- maxIdleConnsPerHost
Sets the maximum number of idle connections per host. Idle connections are connections that have been established but are not being used. This parameter helps prevent idle connections from consuming too many resources, optimizing system performance. The default value is 2.
- maxConns
Sets the maximum number of concurrent connections between Traefik and backend services. For example, setting it to 50 means the total number of connections between Traefik and all backend services will not exceed 50. This setting helps limit system load and avoids establishing too many connections with backend services during peak traffic.
- idleTimeout
Sets the idle connection timeout, meaning if a connection is not used within the specified time, it will be closed. This helps release connections that are no longer needed, preventing too many idle connections from accumulating in the connection pool. The default value is 0, indicating no timeout.
- disableHTTPKeepAlive
If set to true, HTTP Keep-Alive is disabled. HTTP Keep-Alive allows clients to maintain persistent connections with the server, avoiding the need to re-establish a connection for every request. Disabling Keep-Alive will cause a new connection to be established for each request, but it can prevent the connection pool from being occupied for a long time. The default value is false, meaning Keep-Alive is enabled.
For example, to implement connection reuse (Connection Reuse) function, you only need the following configuration:
maxIdleConnsPerHost: 10 # 每个主机最大空闲连接数,根据实际环境设置
idleTimeout: 5m # 空闲连接超时时间,根据实际环境设置
disableHTTPKeepAlive: true # 禁用 HTTP Keep-Alive
maxConns: 50 # Traefik 与后端服务的最大连接数,根据实际环境设置
Traefik Web Dashboard
The Dashboard provided by Traefik (accessed via port 8080) allows you to view some simple content. For details, please refer to the graphic introduction below:





Overall, the default web dashboard provided by Traefik is too simple (a bit disappointing) and does not show specific access data (such as traffic, request count, response time, etc.). To view these specific access data, the official recommendation is to usePrometheus + Grafanaa combination of these two tools:
Traefik Metrics (Prometheus)
Traefik can integrate with Prometheus to collect and display detailed load balancing data through Prometheus, including request count, traffic, response time, etc.
• Enable Prometheus: You need to enable the Prometheus exporter in the Traefik configuration, usually through a configuration file or command-line arguments.
Add the following content to traefik.yml or during command-line startup:
metrics:
prometheus:
entryPoint: "metrics" # 设置Prometheus的端点
buckets:
- 0.1
- 0.3
- 0.5
- 1
- 2.5
- 5
- 10
• Access Prometheus Data: Traefik provides metric data in Prometheus format, which can usually be accessed via http://
Grafana Dashboard
Use Grafana can very conveniently display Traefik's real-time monitoring data. You can set up a Grafana dashboard to view the Traefik metric data collected by Prometheus, which includes specific data items such as:
• Requests
• Response Time
• Traffic
• Health status of backend services, etc.
You can obtain a ready-made panel from the official Traefik Grafana Dashboard (usually imported via Grafana Dashboard ID). If you are interested, you can research this on your own, I won't go into detail here. The final effect is as follows:

Honestly, it's pretty cool~.
Summary
To be honest, I'm a bit unused to using Traefik for load balancing because it was originally designed specifically for microservices and containerized environments. Therefore, its configuration concepts (static configuration files, dynamic service discovery, etc.) do not correspond very well with the basic elements of traditional load balancing (VIP, service-group, server, etc.). Moreover, I am using an uncommon ”file dynamic configuration” method to achieve an uncommon ”hot standby” requirement, which made me a bit dizzy at first. However, once I got used to it, it was fine. Not to mention, using this thing as a k8s Ingress Controller is indeed extremely convenient—you just need to set the k8s API address in the dynamic configuration file. Doing this with traditional load balancing in the past was a real hassle~.
However, Traefik still has disadvantages compared to traditional load balancing solutions, such as deficiencies in load balancing algorithms and custom health check methods (implementing a priority takes ages, whereas on traditional load balancing it's just a few mouse clicks~). Although I am using it now, I am still hesitating. Should I play around with HAProxy again? After all, HAProxy is the solution that best fits my needs.
Note 1: Generally, after the initial configuration of traefik.yml, you don't need to touch it. However, when configuring dynamic.yml later, you must be very careful. Parameter setting issues and formatting issues (spaces, indentation) can cause custom services in Traefik to disappear (a disadvantage of the file dynamic configuration method). I have suffered a lot from this (which is also one of the reasons I want to switch to HAProxy). If you encounter this situation, don't panic, just calm down and troubleshoot slowly.
Note 2: This article does not cover the scenarios where Traefik can truly show its strength (microservices, container environments, k8s), which is a pity. I will write another article to talk about it when I have the opportunity next time. However, there are many tutorials on this topic on the Internet, so if you need them, you can also directly refer to other people's articles.