启用NLB proxy protocol后Nginx Ingress Controller返回400 Bad Request错误求助
看起来你遇到的是典型的proxy protocol配置不匹配问题——Nginx期望收到带proxy protocol前缀的流量,但实际收到的是普通HTTP流量,或者反过来。我帮你梳理几个关键排查点和解决步骤:
一、先确认NLB与目标组的Proxy Protocol配置完全一致
这是最容易踩的坑:
- 登录AWS控制台,找到你的NLB,检查所有监听端口(80和443)对应的目标组,确保每个目标组的「属性」里都开启了「Proxy protocol v2」。不能只给HTTPS端口开,因为你的Nginx同时监听80和443的proxy protocol流量,只要有一个端口的目标组没开,访问这个端口就会返回400。
- 如果你是通过Ingress Controller的Service自动创建的NLB,记得给Service加注解
service.beta.kubernetes.io/aws-load-balancer-proxy-protocol: "*",这样AWS会自动给所有目标组开启proxy protocol,避免手动配置遗漏。
二、验证Nginx Ingress Controller的配置是否生效
- 先检查Ingress Controller的Pod日志,搜索关键词
proxy_protocol,确认日志里有「enabled proxy protocol for listener」之类的提示,说明配置已经加载。如果没有,重启Ingress Controller的Pod(kubectl rollout restart deployment <ingress-controller-deployment-name>),让ConfigMap的配置生效。 - 看你提供的Nginx配置,80和443端口都加了
proxy_protocol参数,这部分是对的,但要确认Ingress Controller的Service是否把外部端口(NLB的80/443)正确映射到了Nginx容器的80/443端口,避免端口映射错误导致流量没走到正确的监听端口。
三、排查健康检查的潜在冲突
如果目标组启用了proxy protocol,但Ingress Controller的健康检查端点(默认是/healthz,端口10254)没有监听proxy protocol,会导致健康检查失败,NLB可能把流量转发到不健康的节点,或者出现异常流量。你可以:
- 检查目标组的健康检查配置,确认健康检查的端口是Ingress Controller的健康端口(通常是10254),并且如果健康检查失败,尝试临时关闭目标组的proxy protocol,看健康检查是否恢复——如果恢复,说明需要给健康检查端口单独配置不使用proxy protocol(毕竟健康检查不需要客户端IP)。
四、调整配置中的冲突项(可选,但避免后续问题)
你的ConfigMap里设置了ssl-redirect: "false",但server-snippet里又写了if ( $server_port = 80 ) { return 308 https://$host$request_uri; },这两个配置是冲突的。建议保留其中一个逻辑:要么把ssl-redirect设为"true",删掉server-snippet里的跳转代码;要么保留server-snippet的跳转,把ssl-redirect设为"false",避免逻辑混乱。
五、抓包验证流量格式(终极排查)
如果上面的步骤都没解决问题,你可以在Ingress Controller的Pod里抓包,确认收到的流量是否带有Proxy Protocol v2的前缀:
# 进入Ingress Controller的Pod kubectl exec -it <ingress-controller-pod-name> -- /bin/bash # 安装tcpdump(如果Pod里没有的话) apt-get update && apt-get install -y tcpdump # 抓80端口的流量,查看是否有proxy protocol前缀 tcpdump -i any port 80 -X
如果抓包结果里看不到0x0D0A0D0A000D0A515549540A这个Proxy Protocol v2的固定前缀,说明NLB没有发送带proxy protocol的流量,回到第一步检查NLB和目标组的配置。
备注:内容来源于stack exchange,提问作者giorgiox1

