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

Sos*_*der 5 partitioning sharding load-balancing kubernetes kubernetes-statefulset

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

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

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

我有这个界面:

public interface IEndpointSelector
{
    int HashableIdentifier { get; }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

Jon*_*nas 9

状态集

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

稳定独特的网络身份

StatefulSet Pods 有一个唯一的标识,它由一个序号、一个稳定的网络标识和一个稳定的存储组成。

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

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: sharded-svc
Run Code Online (Sandbox Code Playgroud)

并且您有例如 3 个副本,这些副本将以序号从 0 开始到副本 1 的<name>-<ordinal>位置命名。

您的 Pod 的名称将是:

sharded-svc-0
sharded-svc-1
sharded-svc-2
Run Code Online (Sandbox Code Playgroud)

并且可以使用 dns-name 访问这些 pod:

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
Run Code Online (Sandbox Code Playgroud)

鉴于您的Headless Service已命名sharded-svc并将其部署在 namespace 中your-namespace

分片或分区

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

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

分片代理

您可以创建一个sharding-proxy由多个 Pod 中的一个组成的服务(可能来自Deployment,因为它可以是无状态的)。这个程序需要观看豆荚/服务/端点在你sharded-svc知道它在哪里可以路由流量。这可以使用client-go或其他替代方法进行开发。

这个服务在你的分片中实现了你想要的逻辑,例如account-nr模数 3 被路由到相应的 pod ordinal

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

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

推荐阅读:Weaver:简单分片

使用分片服务

消耗你的分片的服务,客户端发送请求到你sharding-proxy那然后套用路由分片的逻辑(例如,与请求帐户-NR模3被路由到对应的荚),并转发该请求到副本sharded-svc符合自己的逻辑。

替代解决方案

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

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