Kubernetes中的状态服务分片式负载平衡

时间:2019-11-02 22:55:55

标签: kubernetes azure-service-fabric partitioning sharding kubernetes-statefulset

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

到目前为止,我已经阅读了有关Kubernetes提供“服务”的信息,该服务可以为隐藏在其后的Pod进行负载平衡,但这只能以更简单的方式提供。

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

我有这个界面:

public interface IEndpointSelector
{
    int HashableIdentifier { get; }
}

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

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

现在,我将如何在Kubernetes中做到这一点?

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

在Kubernetes中是否还有一种服务发现的方法,可以在某些地方用来替换现有代码?

2 个答案:

答案 0 :(得分:2)

StatefulSet

StatefulSet构建块,可确保在Kubernetes上进行有状态的工作负载。

稳定且唯一的网络身份

  

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

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

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

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

您的广告连播名称为:

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

并且可以使用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服务被命名为sharded-svc,并且将其部署在命名空间your-namespace中。

共享或分区

  

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

您在这里描述的是您的有状态服务就是所谓的 sharded partitioned 。 Kubernetes并不是开箱即用的,但是您拥有了所有需要的构建基块来进行这种服务。 它可能存在于提供该功能的第三方服务中,您可以对其进行部署,也可以对其进行开发。

共享代理

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

此服务可实现您在分片中所需的逻辑,例如 account-nr 模数3被路由到相应的pod ordinal

更新:存在具有 sharding 功能的第三方代理,例如Weaver Proxy

  

基于标题/路径/正文字段的共享请求

推荐阅读:Weaver: Sharding with simplicity

使用分片服务

要使用您的分片服务,客户端会将请求发送到您的sharding-proxy,然后应用您的路由分片逻辑(例如,具有 account的请求-nr 模数3被路由到相应的Pod(标准),并将请求转发到与您的逻辑相符的sharded-svc副本

替代解决方案

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

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

答案 1 :(得分:0)

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

相关问题