K3s 中 Traefik 获取真实 IP 避坑指南

大家知道,我有一个用于查看 IPv4 和 IPv6 地址的站点 https://ip.bun.plus

最近切换成 #K3s 后,发现获取到的 X-Forwarded-ForX-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 文件……

折腾了一整天,结果是很简单的配置就能解决的问题,太无语了。

发表于

2025-04-01 15:54

最后修改于

2025-04-14 04:13

Tags
An unhandled error has occurred. Reload 🗙