NodePort 与 ClusterIP 与 Kubernetes 上的 Headless Service 的性能考虑

Performance considerations for NodePort vs. ClusterIP vs. Headless Service on Kubernetes

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

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

如果我对网络的理解正确,Headless Service 似乎需要更少的跃点,因此会(稍微)更快? This article 然而,似乎表明直接调用 Headless Service 时无法正确地进行负载平衡。这个对吗?当通过外部(或内部)ALB 调用时,这是否仍然有效?

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

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

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

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

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

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

what is the most elegant/performant way of using internal services from outside of the cluster (where we don't have access to the Kubernetes DNS) but within the same VPC?

为了实现这一点,我认为您应该看一下服务网格。例如,Istio(https://istio.io). It handles your internal service calls manually so that the call doesn't have to go through Kubernetes DNS. Please have a look at Istio's docs (https://istio.io/docs) 了解更多信息。

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

我在下面的标题下提供了有关每种连接转发类型以及服务转发方式的更多详细信息,以供我回答的上下文。

If I understanding the networking correctly, it seems that a Headless Service requires less hops and would hence be (slightly) faster?

并没有快多少。 "extra hop" 是遍历本地查找表的数据包,它无论如何都会遍历,所以没有明显的区别。目标 pod 仍将与实际网络跳数相同。

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

Is < a headless service not load balanced > correct? And would this still hold when called through the external (or internal) ALB?

是的,它是正确的,客户端(或 ALB)需要在 Pod IP 之间实现负载平衡。

Is there any difference in performance for NodePort vs ClusterIP?

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

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

Finally, what is the most elegant/performant way of using internal services from outside of the cluster

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

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

Kubernetes 连接转发

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

Userspace proxy

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

iptables

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

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 基本相同,只是随着大型集群上规则数量的增加(即 pods/services/network 策略的数量),规则处理速度更快。

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

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

节点端口

ALB 路由到任何节点,node/nodeport 将连接转发到处理服务的 pod。这可能是一个远程 pod,它涉及通过 "wire".

发送回流量

ALB > wire > Node > Kernel Forward to SVC (> wire if remote node) > Pod

集群IP

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

ALB > wire > Node > Kernel Forward to SVC > Pod

可以使用 ALB 注释跳过 "Kernel Forward to SVC" 步骤,而无需使用无头服务。

无头服务

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

ALB > wire > Node > Pod

备注

如果将连接转发到 VPC 中的节点,我将在请求后加上后缀,这些请求可能会导致 < 1 毫秒的额外延迟。低端的增强网络实例。 availability-zone 间通讯可能比 intra-AZ 高一点。如果你碰巧有一个地理上分开的集群,它可能会增加控制流量的重要性。例如,拥有一个实际上跳过了许多真实网络的隧道 calico 网络。