在一次 SSO 对接过程中,我发现服务获取不到客户端的真实 IP。为弄清楚其中原委,我对 k3s 中 LoadBalancer 类型服务的流量路径做了一次详细测试。
🧪 测试目标:搞清楚 LB 流量的路径
在 k3s 中,使用 svclb 实现 LoadBalancer 类型的服务时,它到底是如何转发流量的?
跨节点和同节点流量路径会有什么不同?客户端的真实 IP 地址还能保留吗?
这次的测试,正是为了回答这些问题。
🧰 测试场景一:跨节点访问
场景说明
svclbPod 仅部署在test-1节点NGINX 控制器 仅部署在
test-2节点
也就是说,流量先由客户端打到 test-1 节点的 svclb,再被转发至集群内的 test-2 上的 NGINX。
测试示意图
日志观测结果
NGINX 记录的
remote_addr是svclbPod 的 IP,而不是客户端的真实 IP。跨节点后,客户端真实地址丢失。
🟢 测试场景二:同节点访问
场景说明
svclb和 NGINX 控制器 都部署在test-1节点
也就是说,流量不跨节点,直接在同一个节点内部路由。
测试示意图
日志观测结果
此时,NGINX 能正确记录客户端的真实 IP。
没有经过 cluster 网络,IP 未被篡改。
🧠 最终结论
✅ 跨节点流量经过 svclb 后,remote_addr 被替换为 svclb 的 IP ✅ 同节点访问时,客户端 IP 能被正确记录 ✅ 建议:
若依赖真实 IP,避免跨节点或改用 MetalLB
通过 header 透传真实 IP(如 X-Real-IP, X-Forwarded-For)
📝 彩蛋小故事
k3s 自带的 LoadBalancer就是个klipper-lb cosplay 的‘假LB’,于是耿某抱着满腔热血,开始频频向组内涛某“游说“:咱们的基建要上真家伙MetalLB!,涛某一边喝着咖啡一边回应:”你就说能不能用吧,能跑就行🐸“。劝说未果!!!
“有些 LB,生来就注定不能暴露公网;
有些人,生来就不愿折腾 MetalLB。”
📚 延伸阅读推荐
k3s 中的 Service LoadBalancer 原理 [1]
MetalLB [2]
如果你也在使用 k3s,遇到过类似问题,欢迎留言讨论!👍
引用链接
[1] k3s 中的 Service LoadBalancer 原理: https://rancher.com/docs/k3s/latest/en/networking/#load-balancer[2] MetalLB: https://metallb.io/