GKE环境下Nginx Ingress配置X-Forwarded-For头的方法咨询
解决GKE上Nginx Ingress无法传递真实用户IP到Rails应用的问题
我之前在GKE上部署Nginx Ingress和带Rack Attack的Rails应用时,也碰到过完全一样的问题,咱们一步步拆解解决:
1. 修正Service的externalTrafficPolicy配置
你当前Service里的externalTrafficPolicy设为了Cluster,这是核心问题——GKE负载均衡会对入站流量做SNAT(源地址转换),导致Nginx Ingress拿到的请求源IP是集群内部节点IP,而非用户真实IP。
修改方法:
- 直接编辑现有Service:
kubectl edit service nginx-ingress-controller -n nginx-ingress - 把
spec.externalTrafficPolicy的值从Cluster改成Local - 保存退出,Kubernetes会自动更新配置,负载均衡会重新调整路由(这个过程可能有几秒短暂中断,建议低峰操作)
2. 配置Nginx Ingress的ConfigMap传递真实IP头
接下来要让Nginx把真实IP注入请求头,传递给后端Rails。如果是用官方chart安装的Ingress,默认已有一个同名ConfigMap,直接编辑:
kubectl edit configmap nginx-ingress-controller -n nginx-ingress
添加或修改以下配置项:
data: # 开启转发头支持 use-forwarded-headers: "true" # 设置信任的IP范围(生产环境建议填GKE节点CIDR,测试可先用0.0.0.0/0) proxy-real-ip-cidr: "0.0.0.0/0" # 自定义转发头,确保真实IP被正确传递 proxy-set-headers: | X-Real-IP $remote_addr X-Forwarded-For $proxy_add_x_forwarded_for X-Forwarded-Proto $scheme
保存后,Nginx Ingress Pod会自动重载配置,无需手动重启。
3. 配置Rails应用信任代理IP
最后要让Rails信任Nginx的IP,这样它才会把X-Forwarded-For里的内容当成真实用户IP。
编辑Rails生产环境配置文件config/environments/production.rb:
# 替换成你的集群CIDR或Nginx Ingress的IP范围 config.action_dispatch.trusted_proxies = [IPAddr.new("10.163.0.0/16")] # 开启转发头解析 config.action_dispatch.use_x_forwarded_host = true config.action_dispatch.use_x_forwarded_port = true config.action_dispatch.use_x_forwarded_proto = true
重新部署Rails应用后,request.remote_ip就能拿到用户真实IP,Rack Attack也会基于这个IP做访问限制了。
额外注意点
- 修改
externalTrafficPolicy: Local后,要确保Ingress Pod在每个节点都有副本(或通过节点亲和性让流量能到达有Pod的节点),否则部分节点的流量会被丢弃。如果用Deployment,可调整spec.replicas数量,或改用DaemonSet部署Ingress控制器。
内容的提问来源于stack exchange,提问作者Nathan McKaskle
相关产品推荐
相关产品推荐

