【问题标题】:Sharded load balancing for stateful services in KubernetesKubernetes 中状态服务的分片负载均衡
【发布时间】:2019-11-02 22:55:55
【问题描述】:

我目前正在从 Service Fabric 切换到 Kubernetes,并且想知道如何进行自定义和更复杂的负载平衡。

到目前为止,我已经阅读了 Kubernetes 提供的“服务”,它为隐藏在它们后面的 pod 进行负载平衡,但这只能以更简单的方式使用。

我现在要重写的内容在 Service Fabric 中如下所示:

我有这个界面:

public interface IEndpointSelector
{
    int HashableIdentifier { get; }
}

在我的 ASP.Net 应用程序中跟踪帐户的上下文,例如继承了这个。然后,我编写了一些代码,这些代码现在将通过服务结构集群 API 进行服务发现并跟踪所有服务,并在任何实例死亡或重新生成时更新它们。

然后,基于此标识符的确定性(由于上下文被缓存等)并给定前端 -> 后端调用的目标服务的多个副本,我可以可靠地将某个帐户的流量路由到一个某个端点实例。

现在,我将如何在 Kubernetes 中执行此操作?

正如我已经提到的,我找到了“服务”,但它们的负载平衡似乎不支持自定义逻辑,并且仅在使用无状态实例时才有用。

还有一种方法可以在 Kubernetes 中进行服务发现,我可以在这里使用它来替换我现有的代码吗?

【问题讨论】:

    标签: kubernetes load-balancing partitioning sharding kubernetes-statefulset


    【解决方案1】:

    有状态集

    StatefulSet 是 Kubernetes 上的有状态工作负载的构建块,具有一定的保证。

    稳定且唯一的网络身份

    StatefulSet Pod 具有由序数、稳定的网络身份和稳定的存储组成的唯一身份。

    例如,如果您的 StatefulSet 的名称为 sharded-svc

    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      name: sharded-svc
    

    你有例如3 个副本,它们将由 <name>-<ordinal> 命名,其中 ordinal 从 0 开始直到 replicas-1。

    您的 pod 的名称将是:

    sharded-svc-0
    sharded-svc-1
    sharded-svc-2
    

    这些 pod 可以通过 dns-name 访问:

    sharded-svc-0.sharded-svc.your-namespace.svc.cluster.local
    sharded-svc-1.sharded-svc.your-namespace.svc.cluster.local
    sharded-svc-2.sharded-svc.your-namespace.svc.cluster.local
    

    假设您的 Headless Service 被命名为 sharded-svc 并且您将其部署在命名空间 your-namespace 中。

    分片或分区

    鉴于前端 -> 后端调用的目标服务的多个副本,我可以可靠地将某个帐户的流量路由到某个端点实例。

    您在这里描述的是您的有状态服务是所谓的 shardedpartitioned。这不是 Kubernetes 开箱即用的,但您拥有此类服务所需的所有构建块它可能存在提供此功能的第 3 方服务,您可以部署或开发它。

    分片代理

    您可以创建一个由多个 pod 之一组成的服务 sharding-proxy(可能来自 Deployment,因为它可以是无状态的)。此应用需要查看您的sharded-svc 中的 pods/service/endpoints 以了解它可以将流量路由到哪里。这可以使用client-go 或其他替代方法开发。

    此服务实现了您想要在分片中使用的逻辑,例如account-nr 模数3被路由到对应的podordinal

    更新:有具有分片功能的 3rd 方代理,例如Weaver Proxy

    基于 headers/path/body 字段的分片请求

    推荐阅读:Weaver: Sharding with simplicity

    使用分片服务

    为了使用您的分片服务,客户端向您的 sharding-proxy 发送请求,然后应用您的 路由分片逻辑(例如,使用 account-nr 请求 模数 3 被路由到相应的 pod ordinal)并将请求转发到与您的逻辑匹配的sharded-svc副本

    替代解决方案

    目录服务:sharded-proxy 实现为目录服务 可能更容易,但这取决于您的要求。客户可以询问您的 目录服务 我应该发送什么 statefulSet 副本 account-nr X 以及您的服务回复,例如sharded-svc-2

    客户端中的路由逻辑:可能最简单的解决方案是让您的路由逻辑在客户端中,并让此逻辑计算向哪个 statefulSet 副本发送请求.

    【讨论】:

    • @Sossenbinder 我最后更新了一个更简单的解决方案(在客户端路由),但这取决于您的要求。
    • 我想现在我会简单地将我现有的逻辑重写为 kubernetes 服务发现,但是一旦我有时间,我肯定会看看其他解决方案
    • 我刚刚提出的快速问题 - 当我执行手动路由逻辑时,我是否仍将我的 pod 隐藏在服务后面?我可以以某种方式调用我想要访问的 pod 的特定 ID 的服务吗?还是我的客户明确地跟踪 pod?
    • @Sossenbinder 使用该服务! Pod 是一次性的,来来去去(例如节点故障或升级),但服务是一致的。
    • 谢谢你,你帮了大忙!
    【解决方案2】:

    出于性能原因,服务通常在内核空间中运行代理,因此编写自定义代码很困难。 Cillium 确实允许为某些网络功能编写 eBPF 程序,但我不认为服务路由是其中之一。所以这几乎意味着使用用户空间代理。如果您的服务是基于 HTTP 的,您可以查看一些现有的 Ingress 控制器,看看是否有足够接近的控制器或允许您编写自己的自定义会话路由逻辑。否则你将不得不自己编写一个守护进程来处理它。

    【讨论】:

      猜你喜欢
      • 2022-10-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-17
      • 1970-01-01
      • 1970-01-01
      • 2016-06-23
      • 1970-01-01
      相关资源
      最近更新 更多