【问题标题】:Performance considerations for NodePort vs. ClusterIP vs. Headless Service on KubernetesNodePort 与 ClusterIP 与 Kubernetes 上的无头服务的性能注意事项
【发布时间】:2020-01-19 05:30:37
【问题描述】:

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

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

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

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

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

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

【问题讨论】:

    标签: kubernetes kubernetes-networking


    【解决方案1】:

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

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

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

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

    正确吗?当通过外部(或内部)ALB 调用时,这是否仍然有效?

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

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

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

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

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

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

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

    Kubernetes 连接转发

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

    Userspace proxy

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

    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 中的节点,我将在请求后缀上可能会考虑

    【讨论】:

      【解决方案2】:

      从集群外部(我们无法访问 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)

      【讨论】:

        【解决方案3】:

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

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

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

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

        【讨论】:

          猜你喜欢
          • 2018-10-29
          • 2010-11-01
          • 2012-08-22
          • 1970-01-01
          • 1970-01-01
          • 2017-11-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多