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

发布时间:2021-12-23 18:39:52 作者:柒染
来源:亿速云 阅读:161

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

前言

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

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

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

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

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

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

性能与特性

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

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


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

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

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

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

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

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

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

业务可用性

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

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

负载均衡的控制面性能

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

新旧模式对比

性能对比

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

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

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

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

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

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

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

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

负载均衡流量对比

传统NodePort模式

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

请求细节过程
  1. 请求流量进入负载均衡

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

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

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

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

新的Pod直连模式

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

请求细节过程
  1. 请求流量进入负载均衡

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

直连与Local访问的区别

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

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

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

ReadinessGate的引入

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

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

  2. 为什么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的对比测试。

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

KubeProxy的一些设计思考

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

新模式使用指引

前置要求

  1. Kubernetes集群版本需要高于 1.12。

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

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

控制台操作指引

  1. 登录 容器服务控制台。

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

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

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

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

Kubectl操作指引


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的网络负载均衡是怎样的有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注亿速云行业资讯频道,感谢大家的支持。

推荐阅读:
  1. vconfig命令打通直连网络
  2. 通过DescribeNetworkInterfaces怎么查看弹性网卡ENI列表

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

tke pod

上一篇:如何在go-zero中使用jwt-token鉴权实践

下一篇:linux中如何删除用户组

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》