1

我们在 AWS EKS 上运行两种类型的服务:

  • 我们使用 aws-alb-ingress-controller 通过应用程序级负载均衡器公开的面向外部的服务
  • 我们直接通过服务名称(对于 EKS 应用程序)和通过内部应用程序级负载均衡器使用的面向内部的服务,也使用 aws-alb-ingress-controller(对于非 EKS 应用程序)

我想了解为外部和内部服务选择 Nodeport、ClusterIP 或无头服务对性能的影响。我的设置适用于所有三个选项。

如果我正确理解网络,似乎无头服务需要更少的跃点,因此会(稍微)更快?然而,这篇文章似乎表明直接调用无头服务时不会正确地进行负载平衡。它是否正确?当通过外部(或内部)ALB 调用时,这是否仍然有效?

NodePort 与 ClusterIP 的性能有什么不同吗?

最后,从集群外部(我们无法访问 Kubernetes DNS)但在同一个 VPC 中使用内部服务的最优雅/高性能的方式是什么?是否会使用 ClusterIp 并在服务定义中指定 IP 地址以使其保持稳定?还是有更好的选择?

4

3 回答 3

5

我已经在下面的标题下提供了有关每种连接转发类型以及如何向下转发服务的更详细信息,以获得我的答案的上下文。

如果我正确理解网络,似乎无头服务需要更少的跃点,因此会(稍微)更快?

没有明显更快。“额外跳”是遍历本地查找表的数据包,无论如何它都会遍历,因此没有明显的区别。目标 pod 仍然与实际网络跳数相同。

如果您有 1000 个服务在单个 pod 上运行并且可能是无头的,那么您可以使用它来限制 iptables NAT 规则的数量并加快规则处理速度(请参阅下面的 iptables v ipvs)。

<无头服务未负载平衡>正确吗?当通过外部(或内部)ALB 调用时,这是否仍然有效?

是的,这是正确的,客户端(或 ALB)需要跨 Pod IP 实现负载平衡。

NodePort 与 ClusterIP 的性能有什么不同吗?

NodePort 从入口节点到运行 pod 的节点可能有一个额外的网络跃点。假设 ClusterIP 范围被路由到正确的节点(并且完全路由)

如果您碰巧正在使用服务类型:可以通过将 [ 设置为][ https://kubernetes.io/docs/concepts/services-networking/service/#aws-nlb-support]LoadBalancer来更改此行为,这意味着流量只会被定向到本地吊舱。.spec.externalTrafficPolicyLocal

最后,从集群外部使用内部服务的最优雅/高性能的方式是什么

我会说使用带有注释的AWS ALB 入口控制器。alb.ingress.kubernetes.io/target-type: ip集群中的 k8s 配置将通过入口控制器和地址 pod 直接推送到 ALB,而无需遍历任何连接转发或额外的跃点。所有集群重新配置将自动推出。

与集群重新配置相比,配置到达 ALB 有一点延迟kube-proxy。滚动部署之类的东西可能不像 pod 消失后更新到达那样无缝。最终,ALB 有能力自行处理中断。

Kubernetes 连接转发

每个节点上都有一个kube-proxy进程运行,它管理连接的转发方式和位置。kube-proxy如何做到这一点有 3 个选项:用户空间代理、iptables 或 IPVS。大多数集群将在 iptables 上,这将满足绝大多数用例。

用户空间代理

转发是通过在用户空间中运行以终止和转发连接的进程。它很慢。你不太可能使用它,不要使用它。

iptables

iptables 通过 NAT 转发内核中的连接,速度很快。这是最常见的设置,将涵盖 90% 的用例。新连接在所有运行 Pod 服务的节点之间平均共享。

IPVS

在内核中运行,它快速且可扩展。如果您将流量转移到大量应用程序,这可能会提高转发性能。它还支持不同的服务负载均衡模式:

- rr: round-robin
- lc: least connection (smallest number of open connections)
- dh: destination hashing
- sh: source hashing
- sed: shortest expected delay
- nq: never queue

访问服务

我的解释是基于 iptables 的,因为我还没有对 ipvs 集群做太多详细的工作。我将放弃 ipvs 的复杂性,并说它与 iptables 基本相同,只是随着大型集群上规则数量的增加(即 Pod/服务/网络策略的数量)的增加,规则处理速度更快。

我也忽略了描述中的用户空间代理,因为开销只是不要使用它。

要理解的基本内容是“Service ClusterIP”是集群中的一个虚拟构造,仅作为流量应该去向的规则而存在。每个节点都维护所有 ClusterIP/port 到 PodIP/port 的规则映射(通过kube-proxy

节点端口

ALB 路由到任何节点,节点/节点端口将连接转发到处理服务的 pod。这可能是一个远程 pod,它将涉及通过“电线”将流量发送回。

ALB > 线 > 节点 > 内核转发到 SVC(> 线如果远程节点) > Pod

集群IP

使用 ClusterIP 进行直接访问取决于路由到正确节点的服务集群 IP 范围。有时它们根本没有路由。

ALB > 电线 > 节点 > 内核转发到 SVC > Pod

可以使用 ALB 注释跳过“内核转发到 SVC”步骤,而无需使用无头服务。

无头服务

同样,根据网络设置,Pod IP 并不总是可以从集群外部寻址。你在 EKS 上应该没问题。

ALB > 电线 > 节点 > Pod

笔记

如果连接被转发到 VPC 中的节点,我将在请求后缀为可能会查看 < 1 毫秒的额外延迟。低端的增强网络实例。可用区域间的通信可能比 AZ 内的通信要高一点。如果你碰巧有一个地理上分离的集群,它可能会增加控制流量的重要性。例如,拥有一个实际上跳过多个真实网络的隧道印花布网络。

于 2020-01-19T09:53:27.947 回答
1

Headless 服务在 L4 层不会有任何负载平衡,但如果您在 ALB 后面使用它,您将在 L7 层获得负载平衡。

Nodeport 在内部使用集群 IP,但是因为您的请求可能会随机路由到另一台主机上的 pod,而它本来可以路由到同一主机上的 pod,从而避免了额外的跳出网络。Nodeport 对于生产使用来说通常是个坏主意。

恕我直言,从集群外部访问内部服务的最佳方法是使用ingress

您可以使用 nginx 作为入口控制器,您可以在集群上部署 nginx 入口控制器,并使用 ALB 通过 LoadBalancer 类型的服务公开它。然后,您可以使用入口 api 配置基于路径或主机的路由,以在后端 kubernetes 服务之间路由流量。

于 2020-01-19T05:43:38.503 回答
1

从集群外部(我们无法访问 Kubernetes DNS)但在同一个 VPC 中使用内部服务的最优雅/高性能的方式是什么?

为此,我认为您应该看一下 Service Mesh。例如,Istio ( https://istio.io )。它手动处理您的内部服务调用,因此调用不必通过 Kubernetes DNS。请查看 Istio 的文档 ( https://istio.io/docs ) 了解更多信息。

此外,您可以查看 EKS 的 Istio ( https://aws.amazon.com/blogs/opensource/getting-started-istio-eks )

于 2020-01-19T05:52:08.370 回答