
Kubernetes Calico VPP软协议栈
VPP简介
VPP(Vector Packet Processor)是一个高性能、开源的用户空间网络数据平面,用C语言编写,在 fd.io 旗下开发。它支持许多标准网络功能(L2、L3路由、NAT、封装),并且可以使用插件轻松扩展。VPP数据平面使用插件来有效地实现Kubernetes服务负载平衡和Calico策略。
简单来说,它就是个跑在用户空间的TCP/IP协议栈,不需要进入内核。那么它的实现就如下图所示:
安装VPP
安装前提
首先我们需要一个空白的集群环境,也就是相当执行kubeadm init
后没有安装CNI的其他插件。
第二就是内核版本需要很高。
HugePages概述
HugePages是集成到Linux内核2.6中的一项特性。启用HugePages使操作系统可以支持的内存页大于默认值(通常为4 KB)。使用非常大的页面大小可以通过减少访问page table entries所需的系统资源量来提高系统性能。HugePages对32位和64位配置都很有用。HugePage大小从2 MB到256 MB不等,具体取决于内核版本和硬件架构。对于Oracle数据库,使用HugePages可以减少page states的操作系统维护,并提高转换后备缓冲区(Translation Lookaside Buffer ,TLB)命中率。
更多请参考:https://www.cnblogs.com/plluoye/p/10836322.html
配置HugePages
通过以下hugepages配置可能使VPP能够使用更高效的驱动程序:
至少512 x 2MB hugepage可用(grep hugepages_Free/proc/meminfo
)
加载vfio_pci
(centos上的vfio_pci
)或uio_pci_generic
内核模块。例如:
echo "vfio-pci" > /etc/modules-load.d/95-vpp.conf
modprobe vfio-pci
echo "vm.nr_hugepages = 512" >> /etc/sysctl.conf
# 生效
sysctl -p
# 重新启动kubelet以将更改考虑在内
# 根据kubelet的安装方式,您可能需要使用不同的命令
systemctl restart kubelet
安装Calico与配置VPP
安装Calico与VPP
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.24.5/manifests/tigera-operator.yaml
kubectl apply -f https://raw.githubusercontent.com/projectcalico/vpp-dataplane/v3.24.0/yaml/calico/installation-default.yaml
然后我们等待一下Pod的安装。
安装VPP数据平面组件
首先获取VPP数据平面资源的适当yaml清单:
# 如果设置了hugepages
curl -o calico-vpp.yaml https://raw.githubusercontent.com/projectcalico/vpp-dataplane/v3.24.0/yaml/generated/calico-vpp.yaml
# 没有设置,或不确定使用
curl -o calico-vpp.yaml https://raw.githubusercontent.com/projectcalico/vpp-dataplane/v3.24.0/yaml/generated/calico-vpp-nohuge.yaml
这里我们选者后者的下载。
VPP快的原因除了不走内核,还有就是CPU是专用的。vpp_dataplane_interface
是vpp将使用的主要接口。它必须是Linux接口的名称,并使用地址进行配置。此接口上配置的地址必须是Kubernetes中的节点地址。
# 查看我们的网络接口
ifconfig
# 查看虚拟网口的速度
ethtool ens33
vim calico-vpp
# 修改vpp_dataplane_interface: ens33
我们知道VPP可以进行各种各样的包数据进行处理,但是它发出去的时候是通过uplink_interface进行发出去的,vpp_uplink_driver
这个参数可以设置具体应该设置什么来快速处理包发出去。举例:dpdk。
这里我们就选默认的即可(模式是af_packet
: 使用af_packet套接字驱动接口(未优化,但在任何地方都有效))。
更多请参考:
接下来我们还需要设置Kubernetes中Service的网段也就是service_prefix
参数。(可通过如下命令进行查看)
kubectl cluster-info dump | grep -m 1 service-cluster-ip-range
最后Apply一下,完成VPP的安装。
kubectl apply -f calico-vpp.yaml
物理网卡变了?
我们通过ethtool ens33
查询发现它的速度从千兆网速度变成了10MB/s
,并且物理网卡变成了一个TAP设备。
到这里你可能会问了为什么会这样?
由于我们VPP是用户态的,所以通过TAP/TUN
来连接处理数据包。
更多大家可以参考我以往的文章:http://tnblog.net/hb/article/details/7233#TAP%E4%B8%8ETUN%E8%AE%BE%E5%A4%87
简单来讲就是一端连在我们的协议栈一端连接在我们的IP层。
那既然这样包都出不去,我们的ens33物理端口被谁拿走了呢?
答案是被VPP拿走了。我们可以安装calicovpctl
来进行查看。
安装calivpctl
calivpctl是vpp容器映像附带的一个助手bash脚本。它可以通过以下方法安装到主机上,并有助于收集日志和调试安装了VPP数据平面的正在运行的集群。
curl https://raw.githubusercontent.com/projectcalico/vpp-dataplane/v3.24.0/test/scripts/vppdev.sh \
| tee /usr/bin/calivppctl
chmod +x /usr/bin/calivppctl
VPP处理过程
然后我们进入到VPP中。
calivppctl
# 这里的bpf1是通过查看安装好的VPP控制Pod的后缀名称获取到的
calivppctl vppctl bpf1
我们知道VPP是用户态的协议栈,内核协议栈能够处理的它同样能够处理,所以我们把它ens33的主机网卡拿走了我们同样可以处理。不然拿走了我们的ssh就连接不上主机了。
这里我们来查看一下接口处理情况。
show interfaces
我们还可以通过查看物理网卡对接的情况来看。host-ens33
就是对接的我们的物理网卡ens33,并且连物理mac地址都没有变化。
show hardware-interfaces
再来我们在查看接口中有ipip0和ipip1,那么是不是有tunnl呢?
通过查看网卡并没有发现tunnel相关的网卡。
我们可以通过查看Tunnl的方式来查看相关信息。
show ipip tunnel
我们发现这里写好了从源ip地址和目标地址,意思就是现在ipip由vpp来进行处理。
在来我们这里有tap0设备,它是一个vpp的tap文件但这把它当成一个网卡,那么其他pod的另一端在哪儿呢?
我们首先尝试创建几个pod。
kubectl apply -f cni.yaml
# 运行起来后查看pod的接口
kubectl get pod
kubectl exec -it cni-kpfnz -- bash
ifconfig
ip tuntap list
可以看到这个eth0它是没有mac地址的,卧槽为什么没有地址啊?因为它是点对点(P-t-P
)的设备一个tun设备,就像两头直接连着线的所以不需要MAC地址,就IP地址就可以了。
我们在VPP中也是可以找到的,我们可以看到有很多tun
设备就是它们连接的vpp这一端。
show interfaces
show interfaces address
刚刚我们连接的容器就是tun5的10.244.11.75
。
所以整个创建的流程是这样:
当在主机上调度Pod时,kubelet服务将为新Pod创建网络名称空间,然后使用CNI请求Calico在此名称空间中配置接口。Calico将首先计算主机的IP配置(地址和路由),然后将其传递给VPP代理。然后,VPP将在所需的容器名称空间中创建tun接口,并使用所需的地址和路由对其进行配置。这使得所有的集装箱流量都通过VPP。
我们可以看到路由表都是直接走eth0,然后交给VPP协议栈处理,看看其他的tun对应的ip在哪儿。
# 一个pod中ping
ping xxxxx
# vpp中抓包
pcap trace rx tx max 30000 intfc any
pcap trace off
这里抓的包在calico vpp的 pod里面,所以我们可以复制拿出来,当然也可以从节点中直接获取到。
find / -name rxtx.pcap
然后直接拿下来进行分析,我们发现它直接实现了ipip。
Vxlan模式能否实现?
首先我们改成Vxlan的配置。
然后我们在来看看接口。
calivppctl
calivppctl vppctl bpf1
show interfaces
我们发现IPIP的没了,现在是vxlan的tunnel。
show vxlan tunnel
我们发现源ip,目的ip,源端口4789,目标端口4789,vni为4096。
接下来我们再抓个包看看。
虽然有相关vxlan信息但是解不开数据。
当我们向外发包的时候,它会修改外部Mac地址为VPP的MAC地址,可以通过show tap
来进行查看。
总结
欢迎加群讨论技术,1群:677373950(满了,可以加,但通过不了),2群:656732739

