Kubernetes网络

2021-12-21  本文已影响0人  Tommy1989

kube-proxy

我们知道,Kubernetes中Pod的生命是短暂了,它随时可能被终止。即使使用了Deployment或者ReplicaSet保证Pod挂掉之后还会重启,但也没法保证重启后Pod的IP不变。从服务的高可用性与连续性的角度出发,我们不可能把Pod的IP直接暴露成service端口。因此我们需要一个更加可靠的“前端”去代理Pod,这就是k8s中的Service。引用官方文档的定义就是:

Service 定义了这样一种抽象:逻辑上的一组 Pod,一种可以访问它们的策略 —— 通常称为微服务。 这一组 Pod 能够被 Service 访问到。

也可以说,Service作为“前端”提供稳定的服务端口,Pod作为“后端”提供服务实现。Service会监控自己组内的Pod的运行状态,剔除终止的Pod,添加新增的Pod。配合k8s的服务发现机制,我们再也不用担心IP改变,Pod终止等问题了。kube-proxy则是实现Service的关键组件,到目前为止共有3种实现模式:userspaceiptables 或者 IPVS。其中userspace 模式非常陈旧、缓慢,已经不推荐使用。

IP Tables模式

iptables 是一个 Linux 内核功能,是一个高效的防火墙,并提供了大量的数据包处理和过滤方面的能力。它可以在核心数据包处理管线上用 Hook 挂接一系列的规则。在K8S中,kube-proxy 会把请求的代理转发规则全部写入iptable中,砍掉了kube-proxy转发的部分,整个过程发生在内核空间,提高了转发性能,但是iptable的规则是基于链表实现的,规则数量随着Service数量的增加线性增加,查找时间复杂度为O(n),也就是说,当Service数量到达一定量级时,CPU消耗和延迟将显著增加。

IP VS模式

IPVS 是一个用于负载均衡的 Linux 内核功能。IPVS 模式下,kube-proxy 使用 IPVS 负载均衡代替了 iptable。IPVS 的设计就是用来为大量服务进行负载均衡的,它有一套优化过的 API,使用优化的查找算法,而不是简单的从列表中查找规则。这样一来,kube-proxy 在 IPVS 模式下,其连接过程的复杂度为 O(1)。换句话说,多数情况下,他的连接处理效率是和集群规模无关的。另外作为一个独立的负载均衡器,IPVS 包含了多种不同的负载均衡算法,例如轮询、最短期望延迟、最少连接以及各种哈希方法等。而 iptables 就只有一种随机平等的选择算法。IPVS 的一个潜在缺点就是,IPVS 处理数据包的路径和通常情况下 iptables 过滤器的路径是不同的。

通过下图,可以简单的看出Client pod 、kube proxy 、Pod之间的关系。Service的虚拟Ip会写到ip tables/ip vs中,被转发到真正的Pod地址。

image.png

IP Tables & IP VS 网络扭转


image.png

流程简述如下:

  1. kube-proxy DNAT + SNAT 用自己的 IP 替换源 IP ,用 Pod IP 替换掉目的 IP
  2. 数据包转发到目标 Pod
  3. Pod 将 Ingress Node 视为源,并作出响应
  4. 源 / 目的地址在 Ingress Node 替换为客户端地址(目的) ,服务地址(Ingress Node)

性能对比

image.png
image.png

总结下IPVS & IPTables

1.在小规模的集群中,两者在CPU和响应时间上,差别不大,无论是keep alive 还是non keep alive 。

2.在大规模集群中,两者会慢慢在响应时间以及CPU上都会出现区别,不过在使用keep alive的情况下,区别还是主要来源于CPU的使用。

3.ipvs 基于散列表,复杂度 O(1),iptables 基于链表,复杂度 O(n)

4.ipvs 支持多种负载均衡调度算法;iptables 只有由 statistic 模块的 DNAT 支持概率轮询。

PS:要注意,在微服务的情况下,调用链会非常长,两者影响效果会更显著一些。

eBPF

什么是eBPF?

Linux内核一直是实现监视/可观察性,网络和安全性的理想场所。不幸的是,这通常是不切实际的,因为它需要更改内核源代码或加载内核模块,并导致彼此堆叠的抽象层。 eBPF是一项革命性的技术,可以在Linux内核中运行沙盒程序,而无需更改内核源代码或加载内核模块。通过使Linux内核可编程,基础架构软件可以利用现有的层,从而使它们更加智能和功能丰富,而无需继续为系统增加额外的复杂性层。

eBPF导致了网络,安全性,应用程序配置/跟踪和性能故障排除等领域的新一代工具的开发,这些工具不再依赖现有的内核功能,而是在不影响执行效率或安全性的情况下主动重新编程运行时行为。对于云原生领域,Cilium 已经使用eBPF 实现了无kube-proxy的容器网络。利用eBPF解决iptables带来的性能问题。

通过的 eBPF 实现,可以保留原始源 IP,并且可以选择执行直接服务器返回 (DSR)。即返回流量可以选择最优路径,而无需通过原始入口节点环回,如下图:


image.png

简述流程如下:

  1. BPF program 将数据发送给 K8s service; 做负载均衡决策并将数据包发送给目的 pod 节点
  2. BPF program 程序将 DNAT 转换成 Pod 的IP
  3. Pod 看到客户端真正的 IP
  4. Pod 做出响应; BPF 反向 DNAT
  5. 如果网络准许,数据包直接返回。否则将通过 Ingress Node (ingress controller Pod 所在服务器)

性能

网络吞吐

测试环境:两台物理节点,一个发包,一个收包,收到的包做 Service loadbalancing 转发给后端 Pods。


image.png

可以看出:

  1. Cilium XDP eBPF 模式能处理接收到的全部 10Mpps(packets per second)。
  2. Cilium tc eBPF 模式能处理 3.5Mpps。
  3. kube-proxy iptables 只能处理 2.3Mpps,因为它的 hook 点在收发包路径上更后面的位置。
  4. kube-proxy ipvs 模式这里表现更差,它相比 iptables 的优势要在 backend 数量很多的时候才能体现出来

CPU 利用率

测试生成了 1Mpps、2Mpps 和 4Mpps 流量,空闲 CPU 占比(可以被应用使用的 CPU)结果如下:


image.png

结论与上面吞吐类似。

eBPF简化服务网格

首先看下Service Mesh

image.png

这是一张经典的service mesh图,在eBPF之前,kubernetes服务网格解决方案是要求我们在每一个应用pod上添加一个代理Sidecar容器,如:Envoy/Linkerd-proxy。

:即使在一个非常小的环境中,比如说有20个服务,每个服务运行5个pod,分在3个节点上,你也有100个代理容器。无论代理的实现多么小和有效,这种纯粹的重复都会浪费资源。每个代理使用的内存与它需要能够通信的服务数量有关。

问题:

为什么我们需要所有这些 sidecar?这种模式允许代理容器与 pod 中的应用容器共享一个网络命名空间。网络命名空间是 Linux 内核的结构,它允许容器和 pod 拥有自己独立的网络堆栈,将容器化的应用程序相互隔离。这使得应用之间互不相干,这就是为什么你可以让尽可能多的 pod 在 80 端口上运行一个 web 应用 —— 网络命名空间意味着它们各自拥有自己的 80 端口。代理必须共享相同的网络命名空间,这样它就可以拦截和处理进出应用容器的流量。

eBPF的sidecar less proxy model

基于eBPF的Cilium项目,最近将这种“无 sidecar”模式带到了服务网格的世界。除了传统的 sidecar 模型,Cilium 还支持每个节点使用一个 Envoy 代理实例运行服务网格的数据平面。使用上面的例子,这就把代理实例的数量从 100 个减少到只有 3 个

image.png

支持eBPF的网络允许数据包走捷径,绕过内核部分网络对战,这可以使kubernetes网络的性能得到更加显著的改善,如下图:


image.png

在服务网格的情况,代理在传统网络中作为sidecar运行,数据包到达应用程序的路径相当曲折:入栈数据包必须穿越主机TPC/IP栈,通过虚拟以太网连接到达pod的网络命名空间。从那里,数据包必须穿过pod的网络对战到达代理,代理讲数据包通过回环接口转发到应用程序,考虑到流量必须在连接的两端流经代理,于非服务网格流量相比,这将导致延迟的显著增加。

而基于eBPF的kubernetes CNI实现,如Cilium,可以使用eBPF程序,明智的勾住内核中的特定点,沿着更加直接的路线重定向数据包。因为Cilium知道所有的kubernetes断点和服务的身份。当数据包到达主机时,Cilium 可以将其直接分配到它所要去的代理或 Pod 端点。

总结

通过以上的内容,我想大家对kube-proxy和基于eBPF的CNI插件Cilium已经有了一些了解。可以看到在云原生领域,Cilium 已经使用eBPF 实现了无kube-proxy的容器网络。利用eBPF解决iptables带来的性能问题。另外以上也只是介绍了eBPF的网络方面,其实eBPF在跟踪、安全、负载均衡、故障分析等领域都是eBPF的主战场,而且还有更多更多的可能性正在被发掘。

上一篇下一篇

猜你喜欢

热点阅读