Kubernetes+Metallb+Traefik环境下如何获取真实客户端IP?
问题分析与解决方案
我来帮你理清楚为啥X-Real-IP显示的是10.5.64.0,以及怎么拿到真实的客户端IP 192.168.0.100。
为啥X-Real-IP不对?
咱们先搞清楚根源:这是Kubernetes LoadBalancer Service的默认SNAT行为导致的。
- 你用
LoadBalancer类型的Service暴露Traefik时,Kubernetes会自动对进入的请求做「源地址转换(SNAT)」——简单说就是把客户端的真实IP替换成集群内部的Node或者Service IP(也就是你看到的10.5.64.0这个段的IP)。 - 虽然你在Traefik的
traefik.toml里设置了trustedIPs = ["0.0.0.0/0"],但请求到达Traefik之前,源IP已经被SNAT修改了,Traefik根本拿不到真实的客户端IP,只能拿到被替换后的集群内部IP。
怎么拿到真实客户端IP?
要解决这个问题,核心是让Kubernetes别乱改源IP,同时确保Traefik能正确识别转发头。具体操作如下:
1. 修改Traefik Service,关闭SNAT
更新你的Traefik Service配置,添加externalTrafficPolicy: Local——这个配置会告诉Kubernetes保留客户端的真实IP,不再做SNAT:
kind: Service apiVersion: v1 metadata: name: traefik-ingress-service namespace: kube-system spec: selector: k8s-app: traefik-ingress-lb ports: - protocol: TCP port: 80 name: http - protocol: TCP port: 443 name: https type: LoadBalancer externalTrafficPolicy: Local # 关键:添加这一行
执行命令应用修改:
kubectl apply -f traefik-service.yaml -n kube-system
2. 确认Traefik的转发头配置没问题
你当前的traefik.toml里已经正确配置了forwardedHeaders的trustedIPs,在本地测试环境这个配置完全够用。如果是生产环境,建议把信任IP限制为你的负载均衡器或代理的IP段,防止恶意伪造转发头,但你的场景下不用调整。
3. 验证结果
从192.168.0.100的主机再跑一遍测试命令:
wget -qO - clusterip.staging
这次你应该能在返回结果里看到X-Real-IP是192.168.0.100了。
额外说明
externalTrafficPolicy: Local的作用是让Service只把流量转发到运行Traefik Pod的Node上,同时保留客户端源IP。如果你的Traefik Pod只在部分Node上运行,要确保LoadBalancer的流量能到达这些Node哦。- 要是你用的是云厂商的Kubernetes集群,有些服务商可能需要额外配置才能支持保留源IP,但本地环境(比如minikube、k3s)这个配置直接就能生效。
内容的提问来源于stack exchange,提问作者Andrey Perminov
相关产品推荐
相关产品推荐

