1

我有一个小型 Kubernetes on prem 集群(Rancher 2.3.6),由三个节点组成。集群内的部署由外部应用程序动态配置,并且始终将其副本计数设置为 1,因为这些是有状态的应用程序,不需要高可用性。

应用程序通过 NodePort 服务公开到 Internet,其中随机端口和 ExternalTrafficPolicy 设置为 Cluster。因此,如果用户请求三个节点之一,k8s 代理会将请求路由并 s-NAT 到具有应用程序 pod 的正确节点。

至此,一切正常。

当我们添加依赖于请求源 IP 的应用程序时,问题就开始了。由于 s-NAT 将请求 IP 替换为内部 IP,因此此应用程序无法正常工作。

我知道,将服务 ExternalTrafficPolicy 设置为本地将禁用 s-natting。但这也会破坏架构,因为并非每个 pod 都有一个正在运行的应用程序实例。

有没有办法保留原始客户端 IP 并仍然使用内部路由,所以我不必担心请求将落在哪个节点上?

4

3 回答 3

2

这取决于流量如何进入您的集群。但让我们稍微分解一下:

一般有两种处理源ip保存的策略:

  • SNAT(数据包 IP)
  • 代理/标头(在附加标头中传递原始 IP)

1) SNAT

默认情况下,发送到NodePortLoadBalancer的数据包经过 SourceNAT(发送到接收请求的节点 IP),而发送到ClusterIP的数据包经过 SourceNAT。

正如您已经提到的,有一种方法可以通过设置保留原始源 IP 地址来关闭NodePortLoadBalancerservice.spec.externalTrafficPolicy: Local服务的 SNAT ,但会产生不希望的效果,即 kube-proxy 仅将代理请求代理到本地端点,并且不转发流量到其他节点。

2) Header + Proxy IP 保存

a) Nginx Ingress Controller 和 L7 LoadBalancer

  • 当使用发送X-Forwarded-For标头的 L7 LoadBalancers 时,如果我们在proxy-real-ip-cidr
  • 您可能需要use-forwarded-headers显式设置以使 nginx 转发标头信息
  • 此外,您可能想要启用enable-real-ip,以便 realip_module 替换已X-Forwarded-Forproxy-real-ip-cidr.

b) 代理协议和 L4 LoadBalancer

  • 启用后,不会use-proxy-protocol: "true"评估标头,并且将在转发 TCP 实际连接之前发送连接详细信息。LB 必须支持这一点。
于 2021-08-31T14:31:30.810 回答
0

您可以在 layer2 模式下设置 MetalLB LoadBalancer,并使用ExternalTrafficPolicy: Local.

metalLB 文档中,您可以阅读:

在 layer2 模式下发布时,集群中的一个节点将吸引服务 IP 的流量。从那里开始,行为取决于所选的流量策略。

在这种模式下,只有具有服务端点(Pod 副本 > 0)的节点才会为传入流量提供服务;当然,在这种模式下,客户端 SourceIP 会被保留。

于 2020-04-20T15:28:03.583 回答
0

Web 应用程序可以使用 Ingress 而不是 NodePorts 暴露在集群外部。Ingress 对象可以使用介于两者之间的 Service 指向应用部署,您可以在其中配置service.spec.externalTrafficPolicy: Local以保留源 IP 地址。您可以有一个外部负载均衡器指向集群的节点,其中入口控制器 pod 用于流量路由目的。

参考:https ://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/

于 2020-04-15T07:17:00.513 回答