Docker Desktop Kubernetes中Nginx-Ingress无法传递客户端真实IP至Keycloak
你的问题核心在于Docker Desktop的网络转发机制:在M1 Mac上,Docker Desktop运行在一个Linux虚拟机(IP为192.168.65.3)中,所有外部流量到达Mac主机后,会被转发到这个VM,VM会对流量做SNAT(源地址转换),将客户端真实IP替换为VM自身的集群IP。这就导致nginx-ingress接收到的请求源IP都是192.168.65.3,而非真实客户端IP。
流量完整路径:
外部客户端 → 路由器 → Mac主机物理网卡 → Docker Desktop Linux VM(192.168.65.3)→ NodePort Service → nginx-ingress Pod → Keycloak Pod
1. 修改Nginx-Ingress Controller配置,启用真实IP解析
需要在Controller的启动参数中添加真实IP相关配置,告诉nginx信任Docker VM的子网,从请求头中提取真实IP。
修改你的Controller Deployment的args部分:
args: [ "/nginx-ingress-controller", "--default-backend-service={{.Values.namespace}}/default-http-backend-2", "--enable-ssl-passthrough", "--enable-real-ip", # 启用真实IP解析 "--real-ip-header=X-Forwarded-For", # 指定从哪个头获取真实IP "--set-real-ip-from=192.168.65.0/24", # 信任Docker VM所在子网 "--set-real-ip-from=你的Mac主机IP段", # 比如你的Mac在192.168.1.0/24就填这个 "--set-real-ip-from=你的路由器IP段", # 比如路由器网关是192.168.1.1,填192.168.1.0/24 "--log-format-upstream='{\"time\": \"$time_local\", \"remote_addr\": \"$remote_addr\", \"x-forwarded-for\": \"$http_x_forwarded_for\", \"x-real-ip\": \"$http_x_real_ip\"}'", # 自定义日志格式,方便排查 ]
2. 优化Ingress资源的Annotations
添加配置片段,强制nginx传递正确的转发头到Keycloak:
metadata: annotations: # 保留原有annotations,新增以下内容 nginx.ingress.kubernetes.io/configuration-snippet: | proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; nginx.ingress.kubernetes.io/proxy-connect-timeout: "60" nginx.ingress.kubernetes.io/proxy-send-timeout: "60" nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
3. 配置路由器传递真实IP
如果你的路由器支持,需要在端口转发规则中开启X-Forwarded-For头注入,将客户端的真实IP添加到请求头中。这一步很关键,因为如果路由器不传递这个头,nginx拿到的源IP还是Docker VM的IP,无法提取真实客户端IP。
4. 验证配置效果
- 重新部署nginx-ingress Controller和Ingress资源:
kubectl apply -f your-ingress-controller-deployment.yaml kubectl apply -f your-ingress-resource.yaml - 查看nginx-ingress Pod的日志,检查
x-forwarded-for字段是否包含真实客户端IP:kubectl logs -n <你的命名空间> <nginx-ingress-pod-name> - 登录Keycloak后台,查看用户登录记录的IP字段,确认是否已显示真实IP。
额外说明:docker-compose场景的问题
单独用docker-compose启动Keycloak时,同样因为Docker Desktop的网络转发,流量从Mac主机进入容器时源IP被替换为Docker网桥的IP。解决方法是:
- 在docker-compose.yml中为Keycloak容器添加
network_mode: host(不推荐,可能有端口冲突); - 或者使用nginx反向代理前置Keycloak,在nginx中配置
real_ip_header X-Forwarded-For和set_real_ip_from信任Docker网桥的IP段,同时确保路由器传递X-Forwarded-For头。
内容的提问来源于stack exchange,提问作者Duane Allman

