Kubernetes 中有状态服务的分片负载均衡

Sharded load balancing for stateful services in Kubernetes

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

到目前为止,我已经了解了 Kubernetes 产品 "Services",它为隐藏在它们后面的 pods 进行负载平衡,但这只能以更简单的方式提供。

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

我有这个界面:

public interface IEndpointSelector
{
    int HashableIdentifier { get; }
}

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

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

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

正如我已经提到的,我发现了 "Services",但它们的负载平衡似乎不支持自定义逻辑,而且仅在使用无状态实例时才有用。

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

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

状态集

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

稳定且唯一的网络标识

StatefulSet Pods have a unique identity that is comprised of an ordinal, a stable network identity, and stable storage.

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

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

你有例如3 个副本,这些副本将由 <name>-<ordinal> 命名,其中 ordinal 从 0 开始到 replicas-1.

您的 pods 的名字将是:

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

那些 pods 可以通过 dns 名称访问:

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.

分片或分区

given multiple replicas of the target service of a frontend -> backend call, I can reliably route traffic for a certain account to a certain endpoint instance.

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

分片代理

您可以创建一个服务 sharding-proxy,其中包含一个或多个 pods(可能来自 Deployment since it can be stateless). This app need to watch the pods/service/ in your sharded-svc to know where it can route traffic. This can be developed using client-go 或其他替代方案。

此服务实现了您希望在分片中使用的逻辑,例如account-nr 取模3路由到对应的pod ordinal

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

Sharding request based on headers/path/body fields

推荐阅读:Weaver: Sharding with simplicity

正在使用分片服务

要使用您的分片服务,客户端会向您的 sharding-proxy 发送请求,然后应用您的 路由 分片逻辑 (例如,带有 account-nr 模数 3 的请求被路由到相应的 pod ordinal)并将请求转发到 replicasharded-svc 符合您的逻辑。

替代解决方案

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

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