前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Kubernetes无痛作gRPC负载平衡

Kubernetes无痛作gRPC负载平衡

作者头像
CNCF
发布2019-12-05 13:00:26
1.4K0
发布2019-12-05 13:00:26
举报
文章被收录于专栏:CNCF

作者:William Morgan (Buoyant)

许多gRPC的新用户惊讶地发现,Kubernetes的默认负载平衡常常无法在gRPC上正常工作。例如,下面是一个简单的gRPC Node.js微服务应用,部署在Kubernetes:

虽然这里显示的voting服务有几个pod,但从Kubernetes的CPU图中可以清楚地看到,实际上只有一个pod在工作,因为只有一个pod在接收流量。为什么?

在这篇博客文章中,我们描述了为什么会发生这种情况,以及如何通过使用Linkerd(CNCF的服务网格和服务sidecar)在任何Kubernetes应用程序中添加gRPC负载平衡来轻松修复它。

为什么gRPC需要特殊的负载均衡?

首先,让我们理解为什么我们需要为gRPC做一些特别的事情。

gRPC是应用程序开发者越来越普遍的选择。与JSON-over-HTTP等替代协议相比,gRPC可以提供一些显著的好处,包括显著降低(反)序列化成本、自动类型检查、形式化API和更少的TCP管理开销。

然而,gRPC也打破了标准的连接级负载平衡,包括Kubernetes提供的负载平衡。这是因为gRPC是构建在HTTP/2上的,而HTTP/2被设计为具有一个长时间的TCP连接,在这个连接上所有请求都是多路的——这意味着多个请求可以在同一连接上任意时刻处于活动状态。通常,这很好,因为它减少了连接管理的开销。然而,这也意味着(正如你可能想象的那样)连接级别的平衡不是很有用。一旦建立了连接,就不再需要进行平衡了。所有的请求将被固定在一个目标pod,如下所示:

为什么这不会影响HTTP/1.1?

这个问题在HTTP/1.1中没有出现的原因是HTTP/1.1有几个特性,这些特性自然会导致TCP连接的循环。因此,连接级别的平衡“足够好”,对于大多数HTTP/1.1应用程序,我们不需要做更多的事情。

为了理解原因,让我们深入了解一下HTTP/1.1。与HTTP/2相反,HTTP/1.1不能多路请求。每个TCP连接一次只能激活一个HTTP请求。客户端发出请求,例如GET /foo,然后等待直到服务器响应。当请求响应周期发生时,不能在该连接上发出其他请求。

通常,我们希望大量请求同时发生。因此,要获得并发的HTTP/1.1请求,我们需要建立多个HTTP/1.1连接,并跨所有连接发出请求。此外,长寿命HTTP/1.1连接通常在一段时间后过期,并被客户机(或服务器)关闭。这两个因素结合起来意味着HTTP/1.1请求通常在多个TCP连接之间循环,因此连接级别的平衡工作有效。

那么我们如何平衡gRPC的负载呢?

现在回到gRPC。由于我们无法在连接级别进行平衡,所以为了实现gRPC负载平衡,我们需要从连接平衡切换到请求平衡。换句话说,我们需要打开到每个目的地的HTTP/2连接,并在这些连接之间平衡请求,如下所示:

在网络层面,这意味着我们需要在L5/L7而不是L3/L4作出决定,也就是说,我们需要理解通过TCP连接发送的协议。

我们如何做到这一点?有几个选择。首先,我们的应用程序代码可以手动维护它自己的目的地负载平衡池,我们可以配置我们的gRPC客户机来使用这个负载平衡池。这种方法给了我们最大的控制权,但是在Kubernetes这样的环境中,当Kubernetes重新安排pod时,池会随着时间的推移而变化,这种方法可能非常复杂。我们的应用程序必须监视Kubernetes API,并与pod保持同步。

另有方法,在Kubernetes,我们可以将我们的应用程序部署为无头服务。在本例中,Kubernetes将在服务的DNS条目中创建多个A记录。如果我们的gRPC客户端足够先进,它可以从这些DNS条目中自动维护负载平衡池。但是这种方法限制了我们使用特定的gRPC客户端,并且很少可能单靠使用无头服务。

最后,我们可以采用第三种方法:使用轻量级代理。

使用Linkerd在Kubernetes作gRPC负载平衡

Linkerd是一个CNCF托管的Kubernetes服务网络。与我们的目的最相关的是,Linkerd还充当服务sidecar,它可以应用于单个服务,即使没有集群范围的权限。这意味着,当我们将Linkerd添加到我们的服务中时,它会向每个pod添加一个微型、超快的代理,这些代理会监视Kubernetes API并自动执行gRPC负载平衡。我们的部署如下:

使用Linkerd有几个优点。首先,它可以使用任何语言编写的服务、任何gRPC客户机和任何部署模型(不管是否headless)。因为Linkerd的代理是完全透明的,它们自动检测HTTP/2和HTTP/1和执行L7负载平衡,它们以纯TCP的形式通过所有其他通信。这意味着一切都会正常运转。

其次,Linkerd的负载平衡非常丰富。Linkerd不仅在Kubernetes API上维护了一个监视,并且在pod重新调度时自动更新负载平衡池,Linkerd还使用指数加权的响应延迟移动平均值来自动向最快的pod发送请求。如果一个pod减速,即使是短暂的减速,Linkerd也会让交通远离它。这可以减少端到端尾延迟。

最后,Linkerd基于Rust的代理非常快而且非常小。它们引入小于1ms的p99延迟,每个pod需要小于10mb的RSS,这意味着对系统性能的影响可以忽略不计。

60秒作gRPC负载平衡

Linkerd很容易尝试。只需按照Linkerd入门指南中的步骤——在笔记本电脑上安装CLI,在集群上安装控制平面,并“网格化”服务(将代理注入每个pod)。你将很快让Linkerd在你的服务上运行,并且应该立即看到正确的gRPC平衡。

让我们再来看看我们的voting服务示例,这次是在安装Linkerd之后:

正如我们所看到的,所有pod的CPU图都是活动的,这表明所有pod现在都在处理流量——无需更改一行代码。瞧,gRPC负载平衡就像魔法一样!

Linkerd还为我们提供了内置的流量级指示板,所以我们甚至不再需要从CPU图表中猜测发生了什么。下面是链接图,它显示了每个pod的成功率、请求量和延迟百分比:

我们可以看到每个pod大约有5个RPS。我们还可以看到,虽然我们已经解决了负载平衡问题,但是我们仍然需要对这个服务的成功率做一些工作。(这个演示应用程序是在故意失败的情况下构建的——作为读者的练习,看看你能否通过使用Linkerd仪表盘找到答案!)

总结一下

如果你对将gRPC负载均衡添加到Kubernetes服务的一种非常简单的方法感兴趣,那么不管它是用什么语言编写的,使用什么gRPC客户机,或者它是如何部署的,你都可以使用Linkerd在几个命令中添加gRPC负载均衡。

Linkerd还有很多功能,包括安全性、可靠性、调试和诊断功能,但这些都是未来博客文章的主题。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-11-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 CNCF 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档