
1. 从一次线上 502 说起Traefik 可观测性到底要看什么Traefik 是云原生场景里最常见的反向代理与入口网关之一它能把 Docker 容器、Kubernetes Service 自动发现成路由规则省掉手写 Nginx upstream 的麻烦。但很多人上线后才发现路由是通了可一旦出现 502、504 或者偶发慢请求手里几乎没有可用的数据。访问日志没开、指标没暴露、追踪没接排查全靠猜。这篇聚焦 Traefik 的可观测性落地把三类数据一次讲清访问日志谁在什么时候请求了哪个路由、状态码和耗时是多少、指标Prometheus 能抓到的请求数、延迟直方图、连接数、追踪一个请求穿过 Traefik 到后端服务的完整链路。适合正在用 Docker Compose 或 K8s 跑 Traefik、想补齐监控的运维和后端同学。下面给出的静态配置和动态配置骨架都可以直接复制最后用 curl 和 Grafana 验证三类数据是否真的产出了。2. 前置准备TaoToken 与实验环境在开始配置之前先把实验环境和一个辅助工具准备好。我平时调试模型相关的接口和 Agent 工作流时会用 TaoToken 来统一管理 API Key 和调用入口它的控制台可以集中查看调用情况配合 Traefik 的访问日志能更快定位是网关层还是上游服务的问题。官网入口是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 地址是 https://taotoken.net/api 不加 UTM。如果你只是做 Traefik 本身的监控实验TaoToken 不是必需的但如果你要验证追踪链路里带真实上游请求可以用它作为后端服务之一。需要 Key 的时候去控制台创建https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 密钥管理页在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 。想先看看模型对话效果可以直接用 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 。实验环境建议这样搭一台装了 Docker 和 Docker Compose 的机器Traefik 用 v3.x 镜像后端放一个 whoami 容器做被代理服务再加 Prometheus、Grafana、Jaeger 各一个容器。所有容器放在同一个自定义网络里Traefik 通过 Docker provider 自动发现 whoami。这样你不需要 K8s 也能把三类可观测性数据跑通后面再迁移到 K8s 只是 provider 配置的差异。3. 访问日志字段、格式与过滤配置访问日志是排查问题的第一手材料。Traefik 的访问日志分两种格式commonCLF 风格紧凑但字段固定和 json结构化字段可增删。生产环境建议用 json方便后面接 ELK 或 Loki。静态配置里开启访问日志写入文件并指定 json 格式# traefik.yml静态配置 accessLog: filePath: /var/log/traefik/access.log format: json bufferingSize: 100 fields: defaultMode: keep names: ClientUsername: drop ClientHost: keep RequestMethod: keep RequestPath: keep RequestProtocol: keep StartUTC: keep Duration: keep DownstreamStatus: keep DownstreamContentSize: keep OriginStatus: keep OriginDuration: keep RetryAttempts: keep headers: defaultMode: drop names: User-Agent: keep Content-Type: keep Authorization: drop Cookie: drop这里有几个关键点。defaultMode: keep表示默认保留所有字段然后对个别字段 drop如果你反过来用defaultMode: drop就要显式 keep 你需要的字段日志体积会小很多。headers部分一定要把 Authorization 和 Cookie 丢掉否则访问日志里会明文出现凭证这是很常见的安全疏漏。过滤能显著降低日志量。比如只记录 4xx 和 5xx以及耗时超过 100ms 的请求accessLog: filePath: /var/log/traefik/access.log format: json filters: statusCodes: - 400-599 minDuration: 100ms retryAttempts: truestatusCodes支持区间写法minDuration只保留慢请求retryAttempts: true表示发生过重试的请求也记下来。实测下来加上这两个过滤后正常流量下的日志量能降一个数量级但排障需要的信息一个不少。如果你用 Docker Compose 启动也可以全部走命令行参数services: traefik: image: traefik:v3.6 command: - --accesslogtrue - --accesslog.filepath/var/log/traefik/access.log - --accesslog.formatjson - --accesslog.filters.statuscodes400-599 - --accesslog.filters.minduration100ms volumes: - ./logs:/var/log/traefik启动后随便发几个请求然后tail -f ./logs/access.log你应该能看到一行行 JSON里面RequestPath、DownstreamStatus、Duration、OriginDuration都在。Duration是 Traefik 视角的总耗时OriginDuration是后端服务耗时两者差值就是网关自身开销这个差值突然变大通常意味着 Traefik 本身有瓶颈。4. 指标暴露Prometheus 抓取配置与关键指标指标是趋势分析的基础。Traefik 内置 Prometheus 支持只需要在静态配置里开一个 metrics 入口点并让 Prometheus 去抓。# traefik.yml entryPoints: web: address: :80 metrics: address: :9100 metrics: prometheus: entryPoint: metrics addEntryPointsLabels: true addServicesLabels: true addRoutersLabels: true buckets: - 0.005 - 0.01 - 0.025 - 0.05 - 0.1 - 0.25 - 0.5 - 1 - 2.5 - 5addEntryPointsLabels、addServicesLabels、addRoutersLabels这三个开关决定指标里带不带对应的维度标签。全开之后你可以按入口点、按服务、按路由分别聚合排查时能快速定位是哪个路由在拖后腿。buckets是延迟直方图的分桶边界默认桶对 Web 场景偏粗建议按上面这样细化到 5ms 起步。Prometheus 侧的抓取配置# prometheus.yml global: scrape_interval: 15s scrape_configs: - job_name: traefik static_configs: - targets: [traefik:9100]几个必须关注的指标traefik_entrypoint_requests_total按状态码统计请求数traefik_entrypoint_request_duration_seconds_bucket是延迟直方图traefik_open_connections是当前连接数traefik_entrypoint_requests_tls_total统计 TLS 握手。用下面这条 PromQL 算 P95 延迟histogram_quantile(0.95, sum(rate(traefik_entrypoint_request_duration_seconds_bucket[5m])) by (le, entrypoint) )错误率用这条sum(rate(traefik_entrypoint_requests_total{code~5..}[5m])) / sum(rate(traefik_entrypoint_requests_total[5m]))如果这个比值持续超过 0.05就该告警了。注意code标签在 v3 里是字符串正则匹配要写code~5..。5. 追踪串联OpenTelemetry 接入与采样指标告诉你慢了多少追踪告诉你慢在哪一段。Traefik 支持 OTLP 和 Jaeger 两种追踪导出方式新项目建议直接用 OTLP兼容性更好。# traefik.yml tracing: otlp: grpc: endpoint: jaeger:4317 insecure: true samplingRatio: 0.5samplingRatio是采样率1.0 是全采生产环境建议 0.1 到 0.5 之间否则追踪后端压力会很大。insecure: true只在实验环境用生产要走 TLS。如果你还在用 Jaeger 原生协议tracing: jaeger: localAgentHostPort: jaeger:6831 samplingServerURL: http://jaeger:5778/sampling gen128Bit: true propagation: jaeger追踪要真正串起来后端服务也得注入 trace context。Traefik 会把traceparent头透传给上游你的服务只要用 OpenTelemetry SDK 读取这个头并继续传播就能在 Jaeger 里看到从 Traefik 到后端的完整 span。如果后端没接 SDK你至少能在 Jaeger 里看到 Traefik 自己产生的入口 span包含路由匹配、转发耗时等信息。一个容易踩的坑samplingRatio设成 0 会导致完全没有追踪数据但配置不报错排查时容易误以为接入失败。另外 OTLP 的 gRPC 端口默认是 4317HTTP 是 4318别填错。6. 验证三类数据curl 与 Grafana 实操配置写完怎么确认数据真的产出了分三步验证。第一步验证访问日志。发一个会返回 404 的请求curl -s -o /dev/null -w %{http_code}\n http://localhost/not-exist然后看日志tail -n 1 ./logs/access.log | jq .你应该看到DownstreamStatus: 404、RequestPath: /not-exist。如果日志里没有这一行检查filters.statusCodes是否把 404 排除了。第二步验证指标。直接抓 Traefik 的 metrics 端点curl -s http://localhost:9100/metrics | grep traefik_entrypoint_requests_total正常会输出带entrypointweb、code404等标签的计数行。如果返回空检查 metrics 入口点是否真的监听在 9100以及 Prometheus 的 target 是否 UP。第三步验证追踪。在 Jaeger UI默认 16686 端口里选 servicetraefik点 Find Traces应该能看到刚才那次 404 请求的 trace。点进去看 span 的 duration 和 tags确认路由名、状态码都在。Grafana 里建面板时数据源选 Prometheus然后贴前面给的 P95 和错误率 PromQL。一个实用的面板组合是顶部放请求速率和错误率两个 stat中间放 P95/P99 延迟曲线底部放按路由分组的请求数 top10。这样一眼就能看出是整体流量涨了还是某个路由出问题。7. 常见报错与排查清单日志文件不生成最常见原因是容器内路径没挂载出来。Traefik 容器里写/var/log/traefik/access.log宿主机要挂./logs:/var/log/traefik否则日志写在容器层容器一删就没了。另外检查目录权限Traefik 进程要有写权限。metrics 端点 404metrics.prometheus.entryPoint指定的入口点名必须和entryPoints里定义的名称完全一致。写成metrics但入口点定义成traefik-metrics就会 404。Prometheus target DOWN如果 Prometheus 和 Traefik 不在同一网络traefik:9100解析不了。用docker network inspect确认两者在同一自定义网络或者改用宿主机 IP。追踪数据为空先确认samplingRatio不为 0再确认 OTLP endpoint 的端口和协议匹配gRPC 4317 / HTTP 4318。如果 Jaeger 容器没开 OTLP 接收需要在启动参数里加--collector.otlp.enabledtrue。访问日志里出现敏感头检查fields.headers.names是否显式 drop 了 Authorization、Cookie、X-Api-Key。默认defaultMode: keep会把所有头都记下来这是很危险的默认行为。延迟指标和访问日志对不上Duration是 Traefik 总耗时指标里的request_duration_seconds也是总耗时两者应该接近。如果差很多检查是否有中间件如 rate limit、auth在指标统计之后才执行。8. 把可观测性接进你的日常流程三类数据配好只是起点真正有价值的是把它们接进日常。我的做法是访问日志用 Promtail 推到 LokiGrafana 里和 Prometheus 指标放同一个 dashboard这样看到延迟尖刺时能直接下钻到对应时间段的原始日志。追踪则按需开启平时采样率 0.1出问题时临时调到 1.0 复现。如果你在搭 Agent 或编码类工作流需要长期稳定的模型调用入口可以了解下 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 配合 Traefik 的访问日志能清楚看到每次调用的耗时和状态。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite Claude Code 相关配置参考 https://taotoken.net/claudecode?utm_sourcetaotoken_aicg_blog_endutm_contentclaudecodeutm_campaignrewrite 。把这些入口的调用纳入同一套监控排查跨服务问题时就不用东拼西凑了。