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.
你在这里描述的是你的有状态服务就是所谓的sharded或partitioned。这不是从 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)并将请求转发到 replica 个 sharded-svc
符合您的逻辑。
替代解决方案
目录服务:将sharded-proxy
实现为目录服务可能更容易,但这取决于您的要求。客户可以询问您的 目录服务 我应该向哪个 statefulSet 副本发送 account-nr X 以及您的服务回复,例如sharded-svc-2
客户端中的路由逻辑:可能最简单的解决方案是在客户端中包含您的路由逻辑,并让此逻辑计算向哪个 statefulSet 副本发送请求。
我目前正在从 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.
你在这里描述的是你的有状态服务就是所谓的sharded或partitioned。这不是从 Kubernetes 开箱即用的,但您拥有此类服务所需的所有 构建块。 可能存在提供此功能的第 3 方服务,您可以部署或开发它。
分片代理
您可以创建一个服务 sharding-proxy
,其中包含一个或多个 pods(可能来自 Deployment since it can be stateless). This app need to watch the pods/service/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)并将请求转发到 replica 个 sharded-svc
符合您的逻辑。
替代解决方案
目录服务:将sharded-proxy
实现为目录服务可能更容易,但这取决于您的要求。客户可以询问您的 目录服务 我应该向哪个 statefulSet 副本发送 account-nr X 以及您的服务回复,例如sharded-svc-2
客户端中的路由逻辑:可能最简单的解决方案是在客户端中包含您的路由逻辑,并让此逻辑计算向哪个 statefulSet 副本发送请求。