前段时间抽了很多时间进入了网络开发,所以也恶补了不少知识,由于是现成的方案,于实上手就可以开始设计程序编码,少了很多思考的过程。譬如该方案相比其它的方案,有何优势与劣势,缺少了选型的一环。

需要全面的掌握一个方向的知识,各种方案的了解是必不可少的,首先先来简单的来看一下Calico这个网络架构方案。

Calico也主要是创建一个虚拟网络,让宿主机上的多个容器或者虚机之类的,可以进行通讯。首先它与隧道方案最大的不同在于,它不必封装外部隧道头,直接利用linux现有的各种网络虚拟设备与路由表即可实现流量的转发。

这里简单的记录下最核心的一点,网络流量的走向信息。

假设我们有宿主机A与B,其上分别各有一个容器,分别称之为CA,CB,容器的ip分别为192.168.18.64/32与192.168.196.129/32。

首先我们看一下CA的网络信息:

[[email protected] ~]# docker exec -it containerA sh
/ # ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
5: cali0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue 
    link/ether ee:ee:ee:ee:ee:ee brd ff:ff:ff:ff:ff:ff
    inet 192.168.18.64/32 scope global cali0
       valid_lft forever preferred_lft forever

假设CA需要与CB进行通讯,执行ping命令ping 192.168.196.129,首先看下CA的路由信息:

/ # ip route
default via 169.254.1.1 dev cali0 
169.254.1.1 dev cali0 

从路由信息可知,它们肯定不在同一个网段,必须经过169.254.1.1这个网关来进行三层转发。所以ping包最终会交给该网关,二层地址是该网关地址,三层地址是要ping的ip地址。

为了获取该网关地址,需要发送一个arp广播包,我们来看下arp reply的回复的MAC地址是什么:

[[email protected] ~]# tcpdump -nn -i calif24874aae57 -e
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on calif24874aae57, link-type EN10MB (Ethernet), capture size 262144 bytes
13:54:28.280252 ee:ee:ee:ee:ee:ee > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 42: Request who-has 169.254.1.1 tell 192.168.18.64, length 28
13:54:28.280274 a2:ff:0a:99:57:d2 > ee:ee:ee:ee:ee:ee, ethertype ARP (0x0806), length 42: Reply 169.254.1.1 is-at a2:ff:0a:99:57:d2, length 28

我们发现arp的回包的mac地址是a2:ff:0a:99:57:d2,这个地址是哪里来的呢?

首先我们得知道容器与宿主机该如何进行网络通讯。容器由于进行了网络隔离,所以宿主机是无法访问到容器内的网卡的,所以一般都会建立一个虚拟设备,叫veth,它有两端,一端在容器内,一端在宿主机内,它的作用是作为一个通道,一端进去的数据,会由另一端读出,反之也是。所以我们通过veth设备,就可以让宿主机和容器之间进行通讯了。

我们在CA中看到的网络设备,其中有一个叫cali0的,就是veth的一段,另一端则是宿主机的一个端口。我们来宿主机上看一下该veth pair的信息:

# ethtool -S cali0
NIC statistics:
     peer_ifindex: 6
     
# ip addr
6: calif24874aae57: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP 
    link/ether a2:ff:0a:99:57:d2 brd ff:ff:ff:ff:ff:ff
    inet6 fe80::a0ff:aff:fe99:57d2/64 scope link 
       valid_lft forever preferred_lft forever

我们可以看到,cali0的对应的宿主机的一端,名为calif24874aae57,MAC地址为a2:ff:0a:99:57:d2,正式arp reply中回复的MAC地址。但是该网卡的ip并不是网关的ip,为何会做应答呢?

calico做了个特殊的设置,它开启了该网卡的arp proxy,让该网卡代答arp请求,收到任何请求,它都会将自己的MAC地址作为arp reply来发送回包:

# cat /proc/sys/net/ipv4/conf/calif24874aae57/proxy_arp
1

于是任何的数据包,最终都会到对应veth宿主机上的网卡上,然后进行下一步的转发。

宿主机收到该数据包后,行为则是根据宿主机的路由表来进行了:

[[email protected] ~]# ip route
169.254.0.0/16 dev enp0s3  scope link  metric 1002 
169.254.0.0/16 dev enp0s8  scope link  metric 1003 
192.168.18.64 dev calif24874aae57  scope link 
blackhole 192.168.18.64/26  proto bird 
192.168.18.65 dev cali4e5ed993aed  scope link 
192.168.196.128/26 via 172.17.8.101 dev enp0s8  proto bird 

我们可以看到,ping的对端ip地址是192.168.196.129,命中的路由表条目为:

192.168.196.128/26 via 172.17.8.101 dev enp0s8  proto bird

最终该数据包会通过enp0s8物理网卡口子通过物理网络的网关172.17.8.101来进行发送。

经过物理网络的传输之后,宿主机B的物理网卡口子enp0s8收到了网络数据包,我们看下宿主机B上的路由表条目:

[[email protected] ~]# ip route
169.254.0.0/16 dev enp0s3  scope link  metric 1002 
169.254.0.0/16 dev enp0s8  scope link  metric 1003 
192.168.18.64/26 via 172.17.8.100 dev enp0s8  proto bird 
192.168.196.128 dev cali4907e793262  scope link 
blackhole 192.168.196.128/26  proto bird 
192.168.196.129 dev cali69b2b8c106c  scope link 

可以看到,dip为192.168.196.129的数据包,最终会命中

192.168.196.129 dev cali69b2b8c106c  scope link

该路由表条目,被转发到设备cali69b2b8c106c上,和宿主机A一样,该网卡是一个veth pair,最终就由CB容器收到了该数据包,该数据包就会由容器进行处理。

所以我们可以看出,calico的网络模型,需要在每台机器上都有各个该虚拟网络中所有节点的路由信息,不然数据包无法进行转发,该工作通常由BGP协议来实现的。

共 0 条回复
暂时没有人回复哦,赶紧抢沙发
发表新回复

作者

sryan
today is a good day