大家知道,我有一个用于查看 IPv4 和 IPv6 地址的站点 https://ip.bun.plus。
最近切换成 #K3s 后,发现获取到的 X-Forwarded-For
和 X-Real-Ip
都是集群内网的地址。在网上搜索后发现有很多人在问。
首先按 #traefik 文档 Forwarded Headers,配置 trafik 始终转发 Forwarded 头。编辑或新建 /var/lib/rancher/k3s/server/manifests/traefik-config.yaml
文件:
apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
name: traefik
namespace: kube-system
spec:
valuesContent: |-
additionalArguments:
- "--entryPoints.web.forwardedHeaders.insecure"
加入 --entryPoints.web.forwardedHeaders.insecure
后,等待 traefik 应用配置,也试了重启 k3s、重启宿主机,都没有效果。
然后经过了各种尝试(详见后文“大无语事件”部分)。
最后在 @Kevin 的帮助下,才发现应该为 traefik 设置 externalTrafficPolicy: Local
。仍然编辑 /var/lib/rancher/k3s/server/manifests/traefik-config.yaml
文件:
apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
name: traefik
namespace: kube-system
spec:
valuesContent: |-
additionalArguments:
- "--entryPoints.web.forwardedHeaders.insecure"
# 追加下面的内容
service:
spec:
externalTrafficPolicy: Local
k8s文档介绍了 externalTrafficPolicy: Local
的用途和弊端。
大无语事件
最早我将问题丢给了 AI 们,ChatGPT 给出了为 service 添加 externalTrafficPolicy: Local
的方案,但是他给的例子是错的,让我将它加到自己的 service 上,而非 traefik 上。
Warning
下面是错误的回答
在使用 Traefik 作为反向代理时,若您发现后端服务接收到的 X-Forwarded-For 和 X-Real-IP 头部包含的是内网 IP 地址,而非客户端的真实 IP 地址,可能的原因包括:
Kubernetes 服务的 externalTrafficPolicy 设置:在 Kubernetes 集群中,默认情况下,服务的 externalTrafficPolicy 被设置为 Cluster。这意味着外部流量可能会被路由到任意节点,导致后端服务看到的源 IP 地址是内部节点的 IP,而非客户端的真实 IP。将 externalTrafficPolicy 设置为 Local 可以确保流量仅在接收流量的节点上处理,从而保留客户端的真实 IP 地址。具体步骤如下:
apiVersion: v1 kind: Service metadata: name: your-service spec: externalTrafficPolicy: Local # 其他配置
我也有问 DeepSeek,但是 DeepSeek 深度思考比较慢,我都是先看 ChatGPT 的结论,结果 DeepSeek 给出了接近正确方案的答案:
三、设置 Service 的 externalTrafficPolicy 通过调整 Service 策略保留客户端 IP:
修改 Traefik Service:
kubectl edit svc traefik -n kube-system
添加 externalTrafficPolicy: Local 字段。
注意:此配置会使请求仅转发到运行 Traefik Pod 的节点,需确保负载均衡器与节点调度策略匹配。
但都是设置 externalTrafficPolicy: Local
,我也没仔细看,就跳过了……后来折腾来折腾去,AI 们又认为是 flannel 的问题,我就给换成 cilium 了,问题依旧。
看来问 AI,用英文的准确性会更高,交叉验证也还是必不可少的。
最后的最后,其实网上也能搜索到正确的解决方案《k3s Traefik 获取不到真实IP的解决方案【实测有效】》,但怎么说呢……这个排版,实在是没看懂要把 externalTrafficPolicy: Local
添加到 /var/lib/rancher/k3s/server/manifests/traefik-config.yaml
文件……
折腾了一整天,结果是很简单的配置就能解决的问题,太无语了。