我有一个小型 Kubernetes on prem 集群 (Rancher 2.3.6),由三个节点组成。 集群内的部署由外部应用程序动态配置,并且始终将其副本计数设置为 1,因为这些是有状态应用程序,不需要高可用性。
应用程序通过 NodePort 服务向互联网公开,其中具有随机端口,并且外部流量策略设置为集群。因此,如果用户请求三个节点之一,k8s 代理将通过应用程序 pod 将请求路由和 s-NAT 到正确的节点。
到目前为止,一切正常。
当我们添加依赖请求源 IP 的应用程序时,问题就开始了。由于 s-NAT 将请求 IP 替换为内部 IP,因此该应用程序无法正常工作。
我知道,将服务ExternalTrafficPolicy设置为本地将禁用s-natting。但这也会破坏架构,因为并非每个 Pod 都有一个正在运行的应用程序实例。
有没有办法保留原始客户端IP并仍然使用内部路由,这样我就不必担心请求将到达哪个节点?
最佳答案
这取决于流量如何进入您的集群。但让我们稍微分解一下:
一般来说,处理源IP保留的策略有两种:
- SNAT(数据包 IP)
- 代理/ header (在附加 header 中传递原始 IP)
1) SNAT
默认情况下,发往NodePort和LoadBalancer的数据包均经过SourceNAT(发往接收请求的节点的IP),而数据包则发送至ClusterIP> 未进行 SourceNAT。
正如您已经提到的,有一种方法可以通过设置 service.spec.externalTrafficPolicy: Local
来关闭 NodePort 和 LoadBalancer 服务的 SNAT它保留了原始源 IP 地址,但会产生不良影响:kube-proxy 仅将代理请求代理到本地端点,而不将流量转发到其他节点。
2) header +代理IP保存
a) Nginx Ingress Controller 和 L7 LoadBalancer
- 当使用发送
X-Forwarded-For
的 L7 LoadBalancers 时 header ,如果我们在proxy-real-ip-cidr
中设置了 LB CIDR/地址,Nginx 默认情况下会评估包含源 IP 的 header 。 - 您可能需要设置
use-forwarded-headers
明确让nginx转发头信息 - 此外,您可能需要启用
enable-real-ip
所以realip_module替换了X-Forwarded-For
中设置的真实ip由proxy-real-ip-cidr
中指定的可信 LB 提供的 header .
b) 代理协议(protocol)和 L4 LoadBalancer
- 启用
use-proxy-protocol: "true"
不评估 header ,并且在转发 TCP 实际连接之前将发送连接详细信息。 LB 必须支持这一点。
关于docker - Kubernetes Nodeport 保留源 IP,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61210920/