MENU

traefik获取真实ip

March 4, 2026 • 技术

K3s 混合云记录:Traefik 获取真实 IP 的一个坑

最近在学习 Kubernetes,用 K3s 搭了一个混合云集群

整体架构很简单:

  • Kubernetes:K3s
  • Ingress:Traefik
  • 跨云网络:WireGuard
  • 测试服务:whoami

原本只是想验证一下 Ingress 的访问链路,但很快发现一个问题:

Pod 一直获取不到客户端真实 IP。


问题现象

部署 whoami 后访问服务,返回结果类似:

RemoteAddr: 10.x.x.x
X-Forwarded-For: 10.x.x.x

看到的始终是 节点或集群内部 IP,而不是客户端公网 IP。


第一反应:externalTrafficPolicy

常见解决方案是给 Service 设置:

externalTrafficPolicy: Local

这样可以避免 kube-proxy 做 SNAT,从而保留客户端 IP。

但在我的环境里,即使设置了:

externalTrafficPolicy: Local

依然无法获取真实 IP。


K3s 文档里的一个 Known Issue

继续查资料时,在 K3s 文档中看到一条说明:

If external traffic reaches the node using a NAT (e.g. in public clouds) and you require externalTrafficPolicy=local for purposes such as client source IP preservation, please do not define the k3s config node-external-ip for any of the nodes.

简单来说:

如果节点是在 NAT 网络(公有云很常见) 中,并且你需要依赖
externalTrafficPolicy: Local 来保留客户端 IP,

不要配置 node-external-ip


但在混合云场景下问题更复杂

在真实的 混合云架构 中,即使不配置 node-external-ip,问题仍然可能存在。

因为典型链路往往是:

Client
  ↓
云厂商 NAT / 公网入口
  ↓
Node
  ↓
Traefik
  ↓
Pod

只要链路中存在 NAT,客户端 IP 就很可能已经被改写。

externalTrafficPolicy: Local 只能避免 Kubernetes 内部 SNAT
无法解决公网入口 NAT 的问题。


实际可行的方案

如果是在 混合云 + 公有云 NAT 的环境中,想稳定获取真实 IP,通常需要在入口层解决。

比较常见的方式有两种:

1. 前置 HAProxy / Nginx / L4 负载均衡

在 Kubernetes 之前放一层入口代理,例如:

Client
  ↓
HAProxy / Nginx
  ↓
K3s Node
  ↓
Traefik
  ↓
Pod

入口代理负责:

  • 保留客户端 IP
  • 添加 X-Forwarded-For / X-Real-IP
  • 再把流量转发给集群

2. 使用 CDN / 反向代理

例如:

  • Cloudflare
  • 其他 CDN / Edge 网络

链路变成:

Client
  ↓
CDN / Edge
  ↓
K3s Node
  ↓
Traefik
  ↓
Pod

CDN 会通过 Header 传递真实客户端 IP,例如:

CF-Connecting-IP
X-Forwarded-For

然后在 Traefik 中信任这些 Header 即可。


最终结论

K3s + 混合云 + 公有云 NAT 的环境里:

  • externalTrafficPolicy: Local 只能解决 Kubernetes 内部 SNAT
  • 无法解决 公网 NAT 导致的 IP 丢失
  • 如果想稳定获取真实 IP,需要在 集群入口层处理

通常的做法是:

  • 前置 HAProxy / Nginx
  • 或使用 Cloudflare / CDN

小结

这次踩坑最大的感受是:

很多 Kubernetes 的网络问题,其实 不在 Kubernetes 本身,而是在入口网络结构

特别是在 混合云环境 下:

网络链路远比单云复杂。