TKE基于弹性网卡直连Pod的网络负载均衡是怎样的

85次阅读
没有评论

共计 5858 个字符,预计需要花费 15 分钟才能阅读完成。

今天就跟大家聊聊有关 TKE 基于弹性网卡直连 Pod 的网络负载均衡是怎样的,可能很多人都不太了解,为了让大家更加了解,丸趣 TV 小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。

前言

Kubernetes 在集群接入层设计并提供了两种原生资源 Service 和 Ingress,分别负责四层和七层的网络接入层配置。

传统的做法是创建 Ingress 或 LoadBalancer 类型的 Service 来绑定腾讯云的负载均衡将服务对外暴露。这种做法将用户流量负载到用户节点的 NodePort 上,通过 KubeProxy 组件转发到容器网络中,但这种方案在业务的性能和能力支持会有所局限。

为了解决这个问题,TKE 容器团队为在腾讯云上使用独立或托管集群的用户提供了一种新的网络模式,利用弹性网卡直连 Pod 的方案很大的增强了性能和业务能力的支持。

本文将会从传统的模式的问题入手,比较新旧模式的区别,并在最后提供新直连模式的使用指引。

传统模式面临的问题与挑战性能与特性

KubeProxy 在集群中会将用户 NodePort 的流量通过 NAT 的方式转发到集群网络中。这个 NAT 转发带来了以下一些问题。

NAT 转发导致请求在性能上有一定的损失。

进行 NAT 操作本身会带来性能上的损失。

NAT 转发的目的地址可能会使得流量在容器网络内跨节点转发。

NAT 转发导致请求的来源 IP 被修改了,客户端无法获取来源 IP。

当负载均衡的流量集中到几个 NodePort 时。过于集中的流量会导致 NodePort 的 SNAT 转发过多,使得源端口耗尽流量异常。还可能导致 conntrack 插入冲突导致丢包,影响性能。

KubeProxy 的转发具有随机性,无法支持会话保持。

KubeProxy 的每个 NodePort 其实也起到独立的负载均衡作用,由于负载均衡无法收敛到一个地方,所以难以达到全局的负载均衡。

为了解决以上问题,我们以前给用户提供的技术建议主要是通过 Local 转发的方式,避免 KubeProxyNAT 转发带来的问题。但是因为转发的随机性,一个节点上部署多个副本时会话保持依旧无法支持。而且 Local 转发在滚动更新时,容易出现服务的闪断,对业务的滚动更新策略以及优雅停机提出了更高的要求。我们有理由去寻找更好的方案解决这个问题。

业务可用性

通过 NodePort 接入服务时,NodePort 的设计存在极大的容错性。负载均衡会绑定集群所有节点的 NodePort 作为后端。集群任意一个节点的访问服务时,流量将随机分配到集群的工作负载中。这就意味着部分 NodePort 的不可用,或者是 Pod 的不可用都不会影响服务的流量接入。

和 Local 访问一样,直接将负载均衡后端连接到用户 Pod 的情况下,当业务在滚动更新时,如果负载均衡不能够及时绑定上新的 Pod,业务的快速滚动可能导致业务入口的负载均衡后端数量严重不足甚至被清空。因此,业务滚动更新的时候,接入层的负载均衡的状态良好,方能保证滚动更新的安全平稳。

负载均衡的控制面性能

负载均衡的控制面接口。包括创建删除修改四层、七层监听器,创建删除七层规则,绑定各个监听器或者规则的后端。这些接口大部分是异步接口,需要轮询请求结果,接口的调用时间相对较长。当用户集群规模较大时,大量的接入层资源同步会导致组件存在很大的时延上的压力。

新旧模式对比性能对比

Pod 直连模式已经在腾讯 TKE 上线,是对负载均衡的控制面优化。针对整个同步流程,重点优化了批量调用和后端实例查询两个远程调用比较频繁的地方。** 优化完成后,Ingress 典型场景下的控制面性能较优化前版本有了 95%-97% 左右的性能提升。** 目前同步的耗时主要集中在异步接口的等待上。

后端节点突增 (应对集群扩容的场景)

七层规则突增(应对业务第一次上线部署到集群的场景)

除去控制面性能优化这样的硬核优化,负载均衡能够直接访问容器网络的 Pod 就是组件业务能力最重要的组成部分了,其不仅避免了 NAT 转发性能上的损失,同时避免了 NAT 转发带来的各种对集群内业务功能影响。但是在启动该项目时这一块还没有特别好的访问容器网络的支持。所以一期考虑集群 CNI 网络模式下 Pod 有弹性网卡入口,这个入口可以直接接入到负载均衡以达到直接访问的目的。负载均衡直接后端访问到容器网络,目前已经有通过云联网解决的方案,后续也会继续跟进这种更贴近集群网络的直连方案。

接下来能够直接访问了,如何保证滚动更新时的可用性保证呢?我们找到了官方提供的一个特性 ReadinessGate。这个特性在 1.12 正式提供出来,主要是用来控制 Pod 的状态。默认情况下,Pod 有以下 Condition:PodScheduled、Initialized、ContainersReady,当这几个状态都 Ready 的时候,Pod Ready 的 Condition 就通过了。但是在云原生的场景下面,Pod 的状态是非常有可能需要参考其他状态的。ReadinessGate 提供了这样一个机制,允许为 Pod 的状态判断添加一个栅栏,由第三方来进行判断与控制。这样 Pod 的状态就和第三方关联起来了。

负载均衡流量对比传统 NodePort 模式

请求细节过程

请求流量进入负载均衡

请求被负载均衡转发到某一个节点的 NodePort

KubeProxy 将来自 NodePort 的流量进行 NAT 转发,目的地址是随机的一个 Pod。

请求进入容器网络,并根据 Pod 地址转发到对应节点。

请求来到 Pod 所属节点,转发到 Pod。

新的 Pod 直连模式

请求细节过程

请求流量进入负载均衡

请求被负载均衡转发到某一个 Pod 的 ENI 弹性网卡

直连与 Local 访问的区别

看起来这两种访问方式的效果是一样的,但是在细节上还是存在一些差别。

从性能上区别不大,开启 Local 访问时,流量不会进行 NAT 操作也不会进行跨节点转发,所以仅仅多了一个到容器网络的路由。

没有进行 NAT 操作,来源 IP 就能够正确获取了。会话保持功能可能会有以下问题,当一个节点上存在多个 Pod 时,流量到哪一个 Pod 是随机的,这个机制可能会使话保持出现问题。

ReadinessGate 的引入

前面有两个细节,可以在这里得到解答。

为什么要求集群版本高于 1.12

为什么 kubectl get pod -o wide 的结果中 READINESS GATES 列有内容。

这里涉及到一个滚动更新相关的问题 当用户开始为应用做滚动更新的时候,Kubernetes 会根据更新策略进行滚动更新。但是其判断一批 Pod 启动的标识仅包括 Pod 自身的状态,并不会考虑这个 Pod 在负载均衡上是否已经进行配置健康检查是否通过。有的时候当接入层组件高负载,不能及时对这些 Pod 进行及时调度的话,这些滚动更新成功的 Pod 可能并没有正在对外提供服务,从而导致服务的中断。为了将滚动更新和负载均衡的后端状态关联起来,TKE 接入层组件引入了 Kubernetes 1.12 中引入的新特性 ReadinessGate。TKE 接入层组件只有在确认后端绑定成功并且健康检查通过时,通过配置 ReadinessGate 的状态来使 Pod 达到 Ready 的状态,从而推动整个工作负载的滚动更新。

在集群中使用 ReadinessGate 的细节 Kubernetes 集群提供的是一个服务注册的机制,你只需要将你的服务以 MutatingWebhookConfigurations 资源的形式注册到集群中就可以了。集群会在 Pod 创建的时候按照你的配置的回调路径通知你,这个时候就可以对 Pod 做一些创建前的操作,在这个 Case 里面就是给 Pod 加上 ReadinessGate。唯一需要注意的就是这个回调过程必须是 Https 的,所以标配需要在 MutatingWebhookConfigurations 中配置签发请求的 CA,并在服务端配置该 CA 签发的证书。

ReadinessGate 机制的灾难恢复 用户集群中的服务注册或是证书有可能被用户删除,虽然这些系统组件资源不应该被用户修改或破坏。但在用户对集群的探索或是误操作下,这类问题会不可避免的出现。所以接入层组件在启动时会检查以上资源的完整性,在完整性受到破坏时会重建以上资源,加强系统的鲁棒性。

QPS 和网络时延对比

直连与 NodePort 是服务应用的接入层方案,其实最终参与工作的还是用户部署的工作负载,用户工作负载的能力直接决定了业务的 QPS 等指标。所以我们针对这两种接入层方案,在工作负载压力较低的情况下,重点针对网络链路的时延进行了一些对比测试。直连在接入层的网络链路上能够优化 10% 左右的时间。同时测试中的监控也发现,直连模式减少了大量 VPC 网络内的流量。测试场景,从 20 节点到 80 节点,逐步增大集群规模,通过 wrk 工具对集群进行网络延时的测试。针对 QPS 和网络时延,下图给出了直连场景与 NodePort 的对比测试。

KubeProxy 的一些设计思考

KubeProxy 的缺点也在前文中提到的一样明显。但是基于云上负载均衡、VPC 网络的各种特性,我们能给出各种其他更加本地化的接入层方案。但这并不意味着 KubeProxy 的设计不好或是作用不大。其对集群接入层的设计极具普适性、容错性,基本适用于所有业务场景下的集群,作为一个官方提供的组件这个设计是非常合适的。

新模式使用指引前置要求

Kubernetes 集群版本需要高于 1.12。

集群网络模式必须开启 VPC-CNI 弹性网卡模式。

直连模式 Service 使用的工作负载需使用 VPC-CNI 弹性网卡模式。

控制台操作指引

登录 容器服务控制台。

参考控制台 创建 Service 步骤,进入“新建 Service”页面,根据实际需求设置 Service 参数。

其中,部分关键参数信息需进行如下设置,如下图所示:

服务访问方式:选择为【提供公网访问】或【VPC 内网访问】。

网络模式:勾选【采用负载均衡直连 Pod 模式】。

Workload 绑定:选择【引用 Worklocad】,并在弹出窗口中选择 VPC-CNI 模式的后端工作负载。

单击【创建服务】,完成创建。

Kubectl 操作指引

Workload 示例:nginx-deployment-eni.yaml

注意 spec.template.metadata.annotations 中声明了 tke.cloud.tencent.com/networks: tke-route-eni,在工作负载使用 VPC-CNI 弹性网卡模式。

apiVersion: apps/v1 kind: Deployment metadata: labels: app: nginx name: nginx-deployment-eni spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: annotations: tke.cloud.tencent.com/networks: tke-route-eni labels: app: nginx spec: containers: – image: nginx:1.7.9 name: nginx ports: – containerPort: 80 protocol: TCP

- Service 示例:nginx-service-eni.yaml
   注意:`metadata.annotations` 中声明了 `service.cloud.tencent.com/direct-access:  true `,Service 在同步负载均衡时将采用直连的方式配置访问后端。 ```yaml
apiVersion: v1
kind: Service
metadata:
annotations:
 service.cloud.tencent.com/direct-access:  true 
labels:
 app: nginx
name: nginx-service-eni
spec:
externalTrafficPolicy: Cluster
ports:
 - name: 80-80-no
 port: 80
 protocol: TCP
 targetPort: 80
selector:
 app: nginx
sessionAffinity: None
type: LoadBalancer
 ```
-  部署以上内容到集群
   注意:在你的环境你首先需要连接到集群(没有集群的需要先创建集群),可以参考文章尾部的帮助文档配置 kubectl 连接集群。 ```shell
➜ ~ kubectl apply -f nginx-deployment-eni.yaml
deployment.apps/nginx-deployment-eni created
➜ ~ kubectl apply -f nginx-service-eni.yaml
service/nginx-service-eni configured
➜ ~ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deployment-eni-bb7544db8-6ljkm 1/1 Running 0 24s 172.17.160.191 172.17.0.3  none  1/1
nginx-deployment-eni-bb7544db8-xqqtv 1/1 Running 0 24s 172.17.160.190 172.17.0.46  none  1/1
nginx-deployment-eni-bb7544db8-zk2cx 1/1 Running 0 24s 172.17.160.189 172.17.0.9  none  1/1
➜ ~ kubectl get service -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kubernetes ClusterIP 10.187.252.1  none  443/TCP 6d4h  none 
nginx-service-eni LoadBalancer 10.187.254.62 150.158.221.31 80:32693/TCP 6d1h app=nginx
 ```

看完上述内容,你们对 TKE 基于弹性网卡直连 Pod 的网络负载均衡是怎样的有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注丸趣 TV 行业资讯频道,感谢大家的支持。

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-08-16发表,共计5858字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)