基本原理
完全通过三层网络的路由转发来实现
calico ippool
以calico 3.2版本为准,在calico 3.3中增加了blockSize可变更以及针对namespace单独设置子网的功能
参考:https://www.projectcalico.org/calico-ipam-explained-and-enhanced/
calico 不同于flannel不需要为每个node分配子网段,所以只需要考虑pod的数量;
例如配置 172.0.0.0/16
即总共可运行 2^16=65536
个pod。
ippool 分配细节:
默认情况下,当网络中出现第一个容器,calico会为容器分配一段子网(子网掩码/26,例如:172.0.118.0/26
),后续出现该节点上的pod都从这个子网中分配ip地址,这样做的好处是能够缩减节点上的路由表的规模,按照这种方式节点上2^6=64
个ip地址只需要一个路由表项就行了,而不是为每个ip单独创建一个路由表项。如下为etcd中看到的子网段的值:
注意:当64个主机位都用完之后,会从其他可用的的子网段中取值,所以并不是强制该节点只能运行64个pod ,只是增加了路由表项
Calico 网络的转发细节
容器 A1 的 IP 地址为 172.17.8.2/32,这里注意,不是 /24,而是 /32,将容器 A1 作为一个单点的局域网了。
容器 A1 里面的默认路由,Calico 配置得比较有技巧。
default via 169.254.1.1 dev eth0
169.254.1.1 dev eth0 scope link
这个 IP 地址 169.254.1.1 是默认的网关,但是整个拓扑图中没有一张网卡是这个地址。那如何到达这个地址呢?
ARP 本地有缓存,通过 ip neigh 命令可以查看。
169.254.1.1 dev eth0 lladdr ee:ee:ee:ee:ee:ee STALE
找个mac地址为外面 caliefb22cb5e12
的mac地址,即到达物理机A路由器:
172.17.8.2 dev veth1 scope link
172.17.8.3 dev veth2 scope link
172.17.9.0/24 via 192.168.100.101 dev eth0 proto bird onlink
为了保证物理机A和物理机B能够相互知道,路由信息,calico使用了bgp协议进行路由发现。
IPIP
如果是跨网段的访问,网络之间存在路由器,比上面的架构更加复杂,如何进行路由发现? 需启用IPIP模式。
使用了 IPIP 模式之后,在物理机 A 上,我们能看到这样的路由表:
172.17.8.2 dev veth1 scope link
172.17.8.3 dev veth2 scope link
172.17.9.0/24 via 192.168.200.101 dev tun0 proto bird onlink
这和原来模式的区别在于,下一跳不再是同一个网段的物理机 B 了,IP 为 192.168.200.101,并且不是从 eth0 跳,而是建立一个隧道的端点 tun0,从这里才是下一跳。
- 内层源 IP 为 172.17.8.2;
- 内层目标 IP 为 172.17.9.2;
- 外层源 IP 为 192.168.100.100;
- 外层目标 IP 为 192.168.200.101。
将这个包从 eth0 发出去,在物理网络上会使用外层的 IP 进行路由,最终到达物理机 B。在物理机 B 上,tun0 会解封装,将内层的源 IP 和目标 IP 拿出来,转发给相应的容器。