k8s网络之Calico
Calico简介
Calico组件是Tigera公司以Apache 2.0开源协议开源的网络和网络解决方案组件,可用于容器、虚拟机、原生宿主机侧负载。Calico CNI插件在 CNI(Container Network Interface) 框架内封装了Calico的功能,以对k8s环境做支持。
虽然Flannel被公认为是最简单的选择,但Calico以其性能、灵活性而闻名。Calico的功能更为全面,不仅提供主机和pod之间的网络连接,还涉及网络安全和管理。从Calico 3.x开始,默认配置使用的是IPIP模式这种Overlay的传输方案而非BGP。
Calico架构
Calico组件主要架构由Felix、Confd、BIRD组成:
- Felix是负责Calico Node运行并作为每个节点Endpoint端点的守护程序,它负责管理当前主机中的Pod信息,与集群etcd服务交换集群Pod信息,并组合路由信息和ACL策略。
- Confd是负责存储集群etcd生成的Calico配置信息,提供给BIRD层运行时使用。
- BIRD(BIRD Internet Routing Daemon)是核心组件,Calico中的BIRD特指BIRD Client和BIRD Route Reflector,负责主动读取Felix在本机上设置的路由信息,并通过BGP广播协议在数据中心中进行分发路由。
此外,etcd组件是Calico组件运行的依赖组件,需事先在集群中部署etcd服务,或复用Kubernetes的etcd;Calico官方也提供了calicoctl管理工具,用于与Calico Node进行状态确认、状态配置等操作。
Calico之IPIP模式
IPIP模式基于linux kernel的ipip隧道技术实现,即IP报文外面又封装了一层IP报文。内层的IP报文为原报文,外层报文的源IP和目的IP,即是隧道两端的IP。也就是说,应用想要通过隧道在源IP报文外再封装一层IP报文,从而使得原报文能够通过隧道路由到对端。对端的IPIP隧道模块,把原来的外层IP拆解掉,从而还原出原来的IP报文。
IPIP主要做的就是封包,解包的过程。通过IPIP封解包,原始IP报文能够在外层IP的托运下,通过路由穿过隧道,抵达隧道的对端,并且还原出原来的IP报文。这就是IPIP隧道的核心思想。
在使用ipip模式之后,每个node上会自动添加一个tunl0网卡,用于IPIP协议的支持。
IPIP协议格式
pod跨node通信
pod和node网络状况
我们使用两个处于不同node的pod:
# kubectl get pods -o widepod1 1/1 Running 17 12d 10.101.26.40 work4 <none> <none>pod2 1/1 Running 17 12d 10.99.1.167 work1 <none> <none>
登陆work1和work4查看pod的ip和node物理网络的关系,我们可以发现pod内部的网卡在node上会有映射一个虚拟网卡,这一对网卡是一个虚拟机网卡对,一对虚拟网卡就像一跟数据线一遍发送数据另一边就能接收到且数据流向相同。并且,每个node会有tunl0网卡,主要用户隧道封包和解封包:
[root@work1 ~]# route -n|grep 10.99.1.16710.99.1.167 0.0.0.0 255.255.255.255 UH 0 0 0 cali2703ae2f129[root@work1 ~]# ifconfig cali2703ae2f129cali2703ae2f129: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1440 inet6 fe80::ecee:eeff:feee:eeee prefixlen 64 scopeid 0x20<link> ether ee:ee:ee:ee:ee:ee txqueuelen 0 (Ethernet) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0[root@work1 ~]# ip -d link show tunl06: tunl0@NONE: <NOARP,UP,LOWER_UP> mtu 1440 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000 link/ipip 0.0.0.0 brd 0.0.0.0 promiscuity 0 ipip remote any local any ttl inherit nopmtudisc addrgenmode eui64 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535[root@work4 ~]# route -n|grep 10.101.26.4010.101.26.40 0.0.0.0 255.255.255.255 UH 0 0 0 cali8a0d30f1f5a[root@work4 ~]# ifconfig cali8a0d30f1f5acali8a0d30f1f5a: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1440 inet6 fe80::ecee:eeff:feee:eeee prefixlen 64 scopeid 0x20<link> ether ee:ee:ee:ee:ee:ee txqueuelen 0 (Ethernet) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0[root@work4 ~]# ip -d link show tunl016: tunl0@NONE: <NOARP,UP,LOWER_UP> mtu 1440 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000 link/ipip 0.0.0.0 brd 0.0.0.0 promiscuity 0 ipip remote any local any ttl inherit nopmtudisc addrgenmode eui64 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
通信
- 在pod1上ping pod2的ip 10.99.1.167
- 数据包通过pod1的eth0网卡传输到node work4上虚拟网卡cali8a0d30f1f5a,然后通过查询node work4上的路由,发现目的ip 10.99.1.167匹配到如下路由,故把数据包传输到tunl0网卡,此时IP数据报中Inner IP Header的IP:10.101.26.40 --> 10.99.1.167:
# route -n|grep tunl0Kernel IP routing tableDestination Gateway Genmask Flags Metric Ref Use Iface10.99.1.128 172.18.2.186 255.255.255.192 UG 0 0 0 tunl0
- tunl0收到数据包之后会按照ipip协议规范对进来的IP数据包封装一层外层IP头,外层IP的目的ip地址根据2步骤中的路由设置目的ip为网关172.18.2.186,外层IP的源ip地址为本node的ip 172.18.2.184。此时IP数据报变为: Outer IP Header的IP:172.18.2.184 --> 172.18.2.186; Inner IP Header的IP:10.101.26.40 --> 10.99.1.167。tunl0把接收到的数据包封装成ipip报文直接发给tcp/ip协议栈。
- tcp/ip协议栈根据ipip报文的目的地址和系统路由表,知道目的地址为172.18.2.186的数据报需要通过node work4的eth0发送。
# route -n|grep eth00.0.0.0 172.18.2.1 0.0.0.0 UG 100 0 0 eth0172.18.2.0 0.0.0.0 255.255.255.0 U 100 0 0 eth0
- 此ipip数据报经过网关172.18.2.1并最终发送到了node work1的eth0网卡。node work1的tcp/ip协议栈发现是ipip协议,对外层IP数据报解封装并转发给tunl0。tunl0根据内层IP数据包的目的ip地址和本地的路由协议,把数据包再转发到对应的cali2703ae2f129网卡,完成单向通信。
# route -n|grep cali2703ae2f12910.99.1.167 0.0.0.0 255.255.255.255 UH 0 0 0 cali2703ae2f129
- pod2回复pod1的响应同理
pod node内通信
如果是同一个node内的pod通信,由于本地已经有对应pod的路由信息了,故直接在本地node路由转发数据报就可以完成互相通信,不需要使用ipip封装。
总结
1,calico IP in IP模式,跨node通信需要封装和解封装,node内通信不需要
2,calico IP in IP模式也是一种overlay的方案
3,通过封装IP数据报实现,属于L3层网络通信方案
4,对IP隧道封包/解封包技术有一定了解,但是不够深入,有问题欢迎指正
好知识,才能预见未来
赞赏
0人进行了赞赏支持
更多相关文章
- 关于PHP http 报文设置 CURLOPT_HTTPHEADER
- [Linux] 总结各系统 双网卡绑定
- 获取网卡名称 linux c
- 查看Linux服务器网卡流量小脚本shell和Python各一例
- linux网卡实现高可用:team链路聚合
- linux 判定那块网卡为eth0
- 多队列网卡CPU中断均衡
- Linux基础之无线网卡配置连接测试相关操作
- 如何为UDP组播设置一个套接字,并提供两个网卡?