Vấn đề thực tế gặp phải
Mình deploy Traefik làm reverse proxy cho khoảng 8 container trên một VPS. Mọi thứ chạy ổn trong 2 tuần đầu. Rồi một buổi sáng, user báo vào site bị chậm bất thường — container vẫn running, Traefik không có lỗi gì rõ ràng. SSH vào server, chạy docker stats, đọc log từng container một. Gần 30 phút sau mới tìm ra bottleneck ở một service xử lý request quá lâu.
Vấn đề không phải thiếu công cụ. Vấn đề là Traefik hoạt động như hộp đen: bạn biết nó đang chạy, nhưng không biết bao nhiêu request đang đi qua, bao nhiêu cái bị lỗi 5xx, hay latency trung bình đang là bao nhiêu millisecond. Thiếu số liệu đó thì debug chỉ là mò mẫm.
Traefik thiếu visibility gì?
Mặc định Traefik không expose metrics ra ngoài. Khi container healthy, bạn chỉ thấy log dạng text — không có số liệu để vẽ graph theo thời gian. Cụ thể những gì bị thiếu:
- Request Rate: Bao nhiêu request/giây đang đi qua từng entrypoint hay router?
- Error Rate: Tỉ lệ response 4xx/5xx là bao nhiêu? Service nào đang trả lỗi nhiều nhất?
- Latency phân vị: P50, P95, P99 latency cho từng backend service là bao nhiêu?
- Active connections: Có bao nhiêu TCP connection đang mở tại một thời điểm?
Traefik hỗ trợ export metrics sang Prometheus, Datadog, hoặc InfluxDB — nhưng mặc định tất cả đều tắt. Hai cách dưới đây đi từ nhanh gọn đến đầy đủ, tùy nhu cầu thực tế.
Các cách giải quyết
Cách 1: Bật access log và phân tích thủ công
Nhanh nhất để debug tức thời. Thêm vào traefik.yml:
accessLog:
filePath: "/var/log/traefik/access.log"
format: json
fields:
headers:
defaultMode: drop
Đếm error 5xx:
grep '"DownstreamStatus":5' /var/log/traefik/access.log | wc -l
Hữu ích khi cần tìm nhanh vấn đề. Nhưng không có dashboard, không có alert, không nhìn được trend theo thời gian — không phù hợp cho production lâu dài.
Cách 2: Prometheus metrics + Grafana
Traefik có sẵn endpoint /metrics theo Prometheus format — bật lên, cho Prometheus scrape, vẽ Grafana dashboard là xong. Setup mất khoảng 30 phút, dùng được mãi. Đây là cách mình đang chạy trên production.
Setup hoàn chỉnh với Docker Compose
Bước 1: Cấu hình Traefik expose Prometheus metrics
Thêm phần metrics vào traefik.yml. Lưu ý: addRoutersLabels và addServicesLabels là hai tùy chọn dễ bỏ quên nhất — thiếu chúng thì metrics chỉ aggregate theo entrypoint, không breakdown được theo từng service:
# traefik.yml
api:
dashboard: true
insecure: true
entryPoints:
web:
address: ":80"
websecure:
address: ":443"
metrics:
address: ":8082"
metrics:
prometheus:
entryPoint: metrics
addEntryPointsLabels: true
addRoutersLabels: true
addServicesLabels: true
buckets:
- 0.1
- 0.3
- 1.2
- 5.0
providers:
docker:
exposedByDefault: false
Bước 2: Docker Compose cho toàn bộ stack
File docker-compose.yml cho Traefik + Prometheus + Grafana:
version: '3.8'
networks:
proxy:
external: true
monitoring:
internal: true
volumes:
prometheus_data:
grafana_data:
services:
traefik:
image: traefik:v3.0
container_name: traefik
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "8080:8080" # dashboard
- "8082:8082" # metrics
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./traefik.yml:/traefik.yml:ro
networks:
- proxy
- monitoring
prometheus:
image: prom/prometheus:v2.51.0
container_name: prometheus
restart: unless-stopped
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.retention.time=15d'
networks:
- monitoring
grafana:
image: grafana/grafana:10.4.0
container_name: grafana
restart: unless-stopped
environment:
- GF_SECURITY_ADMIN_PASSWORD=your_strong_password
- GF_USERS_ALLOW_SIGN_UP=false
volumes:
- grafana_data:/var/lib/grafana
networks:
- monitoring
- proxy
labels:
- "traefik.enable=true"
- "traefik.http.routers.grafana.rule=Host(`grafana.yourdomain.com`)"
- "traefik.http.routers.grafana.entrypoints=websecure"
Bước 3: Cấu hình Prometheus scrape Traefik
File prometheus.yml. Vì Traefik và Prometheus cùng network monitoring, dùng tên service thay vì IP — không cần hardcode địa chỉ:
global:
scrape_interval: 15s
evaluation_interval: 15s
rule_files:
- "traefik_alerts.yml"
scrape_configs:
- job_name: 'traefik'
static_configs:
- targets: ['traefik:8082']
metrics_path: /metrics
Kiểm tra Traefik đã expose metrics chưa:
curl http://localhost:8082/metrics | grep traefik_entrypoint
Output dạng:
traefik_entrypoint_requests_total{code="200",entrypoint="websecure",method="GET",protocol="http"} 1523
traefik_entrypoint_requests_total{code="404",entrypoint="websecure",method="GET",protocol="http"} 42
traefik_entrypoint_request_duration_seconds_bucket{entrypoint="websecure",le="0.1"} 1401
Bước 4: PromQL queries cho Grafana dashboard
Add Prometheus datasource vào Grafana (http://prometheus:9090), rồi tạo dashboard với các panel sau:
Request Rate — tổng request/giây theo entrypoint:
sum(rate(traefik_entrypoint_requests_total[2m])) by (entrypoint)
Error Rate — phần trăm request lỗi 5xx theo service:
100 * sum(rate(traefik_service_requests_total{code=~"5.."}[2m])) by (service)
/
sum(rate(traefik_service_requests_total[2m])) by (service)
P95 Latency — latency phân vị 95% theo service:
histogram_quantile(0.95,
sum(rate(traefik_service_request_duration_seconds_bucket[5m])) by (le, service)
)
Active connections theo entrypoint:
traefik_entrypoint_open_connections{entrypoint="websecure"}
Không muốn tự build từ đầu? Import Grafana dashboard ID 17346 — official Traefik dashboard, dùng được ngay, chỉnh thêm sau.
Bước 5: Alert rules để cảnh báo tự động
Tạo file traefik_alerts.yml cùng thư mục với prometheus.yml:
groups:
- name: traefik_alerts
rules:
- alert: TraefikHighErrorRate
expr: |
100 * sum(rate(traefik_service_requests_total{code=~"5.."}[5m])) by (service)
/
sum(rate(traefik_service_requests_total[5m])) by (service)
> 5
for: 2m
labels:
severity: warning
annotations:
summary: "Service {{ $labels.service }} có error rate vượt 5%"
description: "Error rate hiện tại: {{ $value | printf \"%.1f\" }}%"
- alert: TraefikHighLatency
expr: |
histogram_quantile(0.95,
sum(rate(traefik_service_request_duration_seconds_bucket[5m])) by (le, service)
) > 2
for: 5m
labels:
severity: warning
annotations:
summary: "P95 latency của {{ $labels.service }} vượt 2 giây"
Kết quả thực tế
Dashboard lên rồi thì mọi thứ thay đổi khá rõ. Request rate theo từng service, error rate khi có container backend crash, latency breakdown theo P50/P95/P99 — tất cả hiện real-time trên một màn hình. Không cần SSH vào server nữa. Mình hay mở dashboard ngay trên điện thoại khi đang ở ngoài, phát hiện vấn đề trước cả khi user kịp báo.
Một điểm cần nhớ: metrics traefik_service_* chỉ xuất hiện sau khi có ít nhất 1 request thật đi qua service đó. Panel Grafana báo “No data” ngay sau khi setup là bình thường — thử gửi vài request test trước:
curl -s https://yourdomain.com/healthz
# Chờ 15-30 giây, rồi kiểm tra lại trong Grafana
Về tài nguyên: Prometheus + Grafana ăn khoảng 300MB RAM — ổn với VPS 2GB. --storage.tsdb.retention.time=15d giữ 15 ngày data, đủ để nhìn trend và trace lại sự cố xảy ra vào cuối tuần mà không ai để ý kịp.

