Calico 网络模型的设计思路

不走 Overlay 网络,不引入另外的网络性能损耗,而是将转发全部用三层网络的路由转发实现。

在这里插入图片描述

1、两台物理机的网卡在同一个二层网络中。由于物理机的容器网段不同,可完全将物理机配置为路由器,并按照容器的网段配置路由表。

2、容器外,直接用路由转发到 veth pair 在物理机这一端的网卡,省掉一个 IP。容器内,把容器外面的 veth pair 网卡算作默认网关,下一跳为外面的物理机。

Calico 网络的转发细节

  • 容器 A1 是一个单点的局域网 172.17.8.2/32,默认路由:
default via 169.254.1.1 dev eth0
169.254.1.1 dev eht0 scope link
  • 容器 A1 的默认网关为 veth1,其 IP 169.254.1.1 未出现在图中。因为网关的 IP 不会出现在任何网络包的包头,只要能找到其 MAC 即可。该 MAC 由 Calico 硬塞进去,能响应 ARP。

  • 容器 A1 发出的包,第一跳为 veth1 网卡,即到达了物理机 A 这个路由。

  • 物理机 A 有 3 条路由规则,分别是去两个本机的容器的路由,以及去 172.17.9.0/24,下一跳为物理机 B。物理机 B 同理。

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

Calico 的架构

1、路由配置组件 Felix

每台物理机上有一个 agent,创建和删除容器时,自动配置路由,该 agent 为 Felix。

2、路由广播组件 BGP Speake

每个 Node 上运行一个软件 BIRD,作为 BGP 的客户端,或叫作 BGP Speaker,将路由信息广播出去。所有 Node 上的 BGP Speaker 全互连,每当路由有所变化时,所有节点都能收到。

3、安全策略组件

Network Policy 可灵活配置两个容器通或不通。类似于虚拟机中的安全组,用 iptables 实现。
在这里插入图片描述

  • 网络包进入物理机时,进入 PREOUTING 规则。cali-fip-dnat 主要将外网 IP dnat 为容器内的 IP。
  • 根据路由判断,是到本地,还是转发出去。
  • 如果是本地,走 INPUT 规则。cali-wl-to-host,wl 是 workload,即容器,判断从容器发到物理机的网络包是否符合规则。内嵌规则 cali-from-wl-dispatch 也是匹配从容器来的包。
  • 如果是转发出去,走 FORWARD 规则。cali-FORWARD 分两种情况:从容器里转发到外面,匹配规则 cali-from-wl-dispatch;从外面转发到容器里,匹配规则 cali-to-wl-dispatch。
  • 接下来匹配 OUTPUT 规则,里面有 cali-OUTPUT 规则。
  • 接下来是 POSTROUTING 规。cali-fip-snat,发包时,将容器 IP 转换为浮动 IP。

Calico 所有组件:
在这里插入图片描述
BGP 全连接复杂性与规模问题

BGP Router Reflector,也使用 BIRD 实现。有了它,BGP Speaker 不用全互连了,而是都直接连它,它负责将全网的路由信息广播出去。

为避免 BGP Router Reflector 成为瓶颈,多个 BGP Router Reflector 各自掌管一部分路由分发。

一部分是多大?

数据中心里,服务器都放在机架上,每个机架顶端有个 TOR 交换机。可将一个机架作为一个单元,让一个 BGP Router Reflector 管理。将一个机架设置为一个 AS,AS 内,服务器和 BGP Router Reflector 之间使用数据中心内部的路由协议 iBGP,BGP Router Reflector 之间使用的是数据中心之间的路由协议 eBGP。
在这里插入图片描述

跨网段访问问题

前面假设物理机可作为路由器,是因为物理机 A 和物理机 B 在同一个网段,连接在同一个交换机,如果不是同一个网段呢?

这时需要中间放一台路由器,做一次路由转发,才能跨网段访问。

关键问题是,物理机 A 如何告诉物理机 B 如何到达自己?物理机 A 不可能知道两者之间的路由器有哪些。

方式1,让中间的所有路由适配 Calico,不太可能。

方式2,Calico 的 IPIP 模式,物理机 A 和物理机 B 之间打一个隧道,在隧道的端点处封装,将容器 IP 作为乘客协议放在隧道里,主机 IP 放在外面作为承载协议。

物理机 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,并且不是从 ehth0 跳,而是建立一个隧道的端点 tun0。

在这里插入图片描述

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐