共计 6898 个字符,预计需要花费 18 分钟才能阅读完成。
前言
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 转发的形式,防止KubeProxy
NAT 转发带来的问题。然而因为转发的随机性,一个节点上部署多个正本时会话放弃仍旧无奈反对。而且 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 在同步负载平衡时将采纳直连的形式配置拜访后端。
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 连贯集群。
➜ ~ 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
## 总结
与业界比照,- AWS 有相似计划,通过弹性网卡的形式实现了 Pod 直连。- GKE(Google Kubernetes Engine)也有相似计划。联合 CLB(Google Cloud Load Balancing)的 NEG(Network Endpoint Groups)个性实现接入层直连 Pod。当初腾讯云 TKE 也利用弹性网卡实现了 Pod 直连的网络模式,现已在腾讯云 TKE 上线。接下来,咱们还打算对这个个性进行更多优化,包含
1. 不依赖 VPC-ENI 的网络模式,实现一般容器网络下的 Pod 直连。2. 反对在 Pod 删除之前,摘除负载平衡后端。欢送大家一起来应用!## 相干参考
1. [Kubernetes Service 介绍](https://kubernetes.io/docs/concepts/services-networking/service)
2. [Kubernetes Ingress 介绍](https://kubernetes.io/docs/concepts/services-networking/ingress)
3. [Kubernetes Deployments 滚动更新策略](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy)
4. [Kubernetes Pods ReadinessGate 个性](https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-readiness-gate)
5. [Kubernetes 通过 Local 转发获取起源 IP](https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip)
6. [TKE 容器服务 网络模式选型](https://cloud.tencent.com/document/product/457/41636)
7. [TKE 容器服务 VPC-CNI 网络模式](https://cloud.tencent.com/document/product/457/34993)
8. [TKE 容器服务 配置 kubectl 并连贯集群](https://cloud.tencent.com/document/product/457/32191)
9. [AWS ALB Ingress Controller](https://aws.amazon.com/cn/blogs/opensource/kubernetes-ingress-aws-alb-ingress-controller/)
10. [GKE 通过独立 NEG 配置容器原生负载平衡](https://cloud.google.com/kubernetes-engine/docs/how-to/standalone-neg)
>【腾讯云原生】云说新品、云研新术、云游新活、云赏资讯,扫码关注同名公众号,及时获取更多干货!!