将externalTrafficPolicy设为Local时Traefik Ingress无法获取客户端公网IP
Traefik EKS环境下无法获取客户端公网IP的解决方法
问题背景
我们在EKS集群通过Helm部署了Traefik v25.0.0,需要配置Ingress IP白名单,因此得正确获取客户端公网IP。在Nginx Ingress里,只要把externalTrafficPolicy设为Local就能实现,但同样配置下Traefik却无法生效,即便升级到最新版本问题仍存在,当前Helm配置如下:
logs: general: format: json access: enabled: true format: json metrics: prometheus: service: enabled: true labels: {} annotations: {} serviceMonitor: jobLabel: traefik interval: 30s honorLabels: true additionalLabels: instance: primary deployment: kind: DaemonSet podAnnotations: reloader.stakater.com/auto: "true" ports: web: nodePort: 32080 service: spec: externalTrafficPolicy: Local annotations: service.beta.kubernetes.io/aws-load-balancer-type: nlb service.beta.kubernetes.io/aws-load-balancer-subnets: ${lb_subnet_ids} service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing enabled: true single: true type: LoadBalancer providers: # Enable cross namespace references kubernetesCRD: enabled: true allowCrossNamespace: true # Enable published service kubernetesIngress: publishedService: enabled: true
问题原因
Traefik在DaemonSet模式结合NLB使用externalTrafficPolicy: Local时,仅靠该配置不足以确保客户端IP正确传递,还需配置信任NLB的IP段、调整网络模式,同时配合NLB的目标组属性才能生效。
解决方案
1. 配置Traefik信任NLB网段
在Helm values中添加forwardedHeaders配置,让Traefik信任NLB所在的VPC网段,确保能从请求头中提取真实客户端IP:
forwardedHeaders: trustedIPs: - 10.0.0.0/8 # 替换为你的EKS集群VPC CIDR - 172.16.0.0/12 - 192.168.0.0/16 insecure: false
2. 开启DaemonSet的hostNetwork
让Traefik Pod直接使用节点网络,避免SNAT导致客户端IP被替换:
deployment: kind: DaemonSet hostNetwork: true podAnnotations: reloader.stakater.com/auto: "true"
注意:开启后要确保Traefik使用的端口(如32080)未被节点上其他服务占用。
3. 配置NLB保留客户端IP
在Service注解中添加NLB目标组属性,强制保留客户端源IP:
service: annotations: service.beta.kubernetes.io/aws-load-balancer-target-group-attributes: preserve_client_ip.enabled=true
4. 验证IP白名单配置
通过Traefik的Middleware配置IP白名单,确保规则匹配真实客户端IP:
示例Middleware:
apiVersion: traefik.containo.us/v1alpha1 kind: Middleware metadata: name: ip-whitelist spec: ipWhiteList: sourceRange: - 1.2.3.4/32 # 替换为允许访问的公网IP段 - 5.6.7.0/24
在Ingress中引用该Middleware:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: example-ingress annotations: traefik.ingress.kubernetes.io/router.middlewares: default-ip-whitelist@kubernetescrd spec: rules: - host: example.com http: paths: - path: / pathType: Prefix backend: service: name: example-service port: number: 80
验证方法
部署修改后的配置后,查看Traefik的访问日志,确认clientIp字段显示的是客户端公网IP而非NLB或节点IP:
kubectl logs -n traefik -l app.kubernetes.io/name=traefik -f
内容的提问来源于stack exchange,提问作者user2534560
相关产品推荐
相关产品推荐

