天天看点

二三层转发原理及过程_容器网络 calico 基本原理和模拟

摘要

在容器网络跨 Host 互联方案中,除了 Flannel 的隧道实现方案,还有一种比较主流的纯三层路由的方案 Calico ,与 Flannel 不同的是 Calico 不使用隧道或 NAT 来实现转发,而是巧妙的把所有二三层流量转换成三层流量,并通过 host 上路由配置完成跨 Host 转发,本文对 Calico 的方案进行基本原理分析和模拟验证。

简介

Calico 官方定义如下:

Calico provides secure network connectivity for containers and virtual machine workloads.

Calico creates and manages a flat layer 3 network, assigning each workload a fully routable IP address. Workloads can communicate without IP encapsulation or network address translation for bare metal performance, easier troubleshooting, and better interoperability. In environments that require an overlay, Calico uses IP-in-IP tunneling or can work with other overlay networking such as flannel.

Calico also provides dynamic enforcement of network security rules. Using Calico’s simple policy language, you can achieve fine-grained control over communications between containers, virtual machine workloads, and bare metal host endpoints.

总结如下:

Calico 为容器和 vm 等提供一个安全的网路互联方法,我们把 VM、Container、白盒等实例统称为 workloads,通过给 workload 分配一个扁平的三层路由可达 IP 地址实现转发,是一种纯三层转发的方案,workload 之间不使用隧道或 NAT 技术,这种方式提供更好的网络性能,提高易维护和可交互性。同时也支持 IPIP 隧道和与 Flannel 集成能力。Calico 提供动态实施的网络安全策略,可使用简单的安全模型语言实现细粒度的安全控制。

相对 Overlay,为什么用 Calico?

Calico 有一篇官方 博文 说明,总结如下:

Calico 是一种 workloads 之间互通的网络方案,并支持以上任意一种场景。在虚拟化平台中,比如 OpenStack、Docker 等都需要实现 workloads 之间互连,但同时也需要对 workloads 做隔离控制,就像在 Internet 中的服务仅开放80端口、公有云的多租户一样,提供隔离和管控机制。

而在多数的虚拟化平台实现中,通常都使用二层隔离技术来实现 workloads 的网络,这些二层的技术有一些弊端,比如需要依赖 VLAN、bridge 和隧道等技术,其中 bridge 带来了复杂性,vlan 隔离和 tunnel 隧道则消耗更多的资源并对物理环境有要求,随着网络规模的增大,整体会变得越加复杂。

那么有更好的方案吗?我们在审视了二层方案并思考如何支持大型网络时从 Internet 网络实现中获得了灵感。我们知道在 Internet 的网络中,路由器作为网关连接着自己的子网络,之间通过 BGP 相互学习,并使用防火墙控制不同子网之间安全策略,所有这些子网络共同组成了 Internet 网络,那么,这种方式能否也应用到虚拟化基础平台中呢?

借鉴这种思路,我们尝试把 Host 当作 Internet 中的路由器,同样使用 BGP 同步路由,并使用 iptables 来做安全访问策略,最终设计出了 Calico 方案,整个方案的优势为:

  1. 更优的资源利用

二层网络通讯需要依赖广播消息机制,广播消息的开销与 host 的数量呈指数级增长,Calico 使用的三层路由方法,则完全抑制了二层广播,减少了资源开销。

另外,二层网络使用 VLAN 隔离技术,天生有 4096 个规格限制,即便可以使用 vxlan 解决,但 vxlan 又带来了隧道开销的新问题。而 Calico 不使用 vlan 或 vxlan 技术,使资源利用率更高。

  1. 可扩展性

Calico 使用与 Internet 类似的方案,Internet 的网络比任何数据中心都大,Calico 同样天然具有可扩展性。

  1. 简单而更容易 debug

因为没有隧道,意味着 workloads 之间路径更短更简单,配置更少,在 host 上更容易进行 debug 调试。

  1. 更少的依赖

Calico 仅依赖三层路由可达。

  1. 可适配性

Calico 较少的依赖性使它能适配所有 VM、Container、白盒或者混合环境场景。

除了以上,还有更多其他优势,因此,如果你在为 OpenStack 或 docker 构建虚拟化网络环境的话,可以好好考虑下 Calico 的方案。

架构

Calico 由 5 部分组件组成,整体构架如下:

二三层转发原理及过程_容器网络 calico 基本原理和模拟
  1. Felix:运行在每一台 Host 的 agent 进程,主要负责网络接口管理和监听、路由、ARP 管理、ACL 管理和同步、状态上报等
  2. Orchestrator Plugin:编排插件,并不是独立运行的某些进程,而是设计与 k8s、OpenStack 等平台集成的插件,如 Neutron’s ML2 plugin 用于用户使用 Neutron API 来管理 Calico,本质是要解决模型和 API 间的兼容性问题。
  3. Etcd:Calico 模型的存储引擎。
  4. BGP Client(BIRD):Calico 为每一台 Host 部署一个 BGP Client,使用 BIRD 实现,BIRD 是一个单独的持续发展的项目,实现了众多动态路由协议比如 BGP、OSPF、RIP 等。在 Calico 的角色是监听 Host 上由 Felix 注入的路由信息,然后通过 BGP 协议广播告诉剩余 Host 节点,从而实现网络互通。
  5. BGP Route Reflector(BIRD):在大型网络规模中,如果仅仅使用 BGP client 形成 mesh 全网互联的方案就会导致规模限制,因为所有节点之间俩俩互联,需要 N^2 个连接,为了解决这个规模问题,可以采用 BGP 的 Router Reflector 的方法,使所有 BGP Client 仅与特定 RR 节点互联并做路由同步,从而大大减少连接数。

模拟组网

组网如下:

二三层转发原理及过程_容器网络 calico 基本原理和模拟
  1. guest 配置 169.254.1.1 的默认路由
  2. host 上配置 10.20.2.0/24 和 10.20.1.3/32 路由
  3. 开启 arp proxy 和 ip_forward 能力

网络连通性测试:

# HOST0[[email protected] ~]# ip netns exec ns0 ping 10.20.2.2PING 10.20.2.2 (10.20.2.2) 56(84) bytes of data. bytes from 10.20.2.2: icmp_seq=1 ttl=62 time=0.774 ms bytes from 10.20.2.2: icmp_seq=2 ttl=62 time=0.332 ms
           

10.20.1.2 与跨 Host 跨子网 10.20.2.2 互通成功

# HOST0[[email protected] ~]# ip netns exec ns0 ping 10.20.1.3PING 10.20.1.3 (10.20.1.3) 56(84) bytes of data. bytes from 10.20.1.3: icmp_seq=1 ttl=62 time=957 ms bytes from 10.20.1.3: icmp_seq=2 ttl=62 time=0.432 ms bytes from 10.20.1.3: icmp_seq=3 ttl=62 time=0.563 ms
           

10.20.1.2 与跨 Host 同子网 10.20.1.3 互通成功

[[email protected] ~]# ip netns exec ns0 ping 192.168.100.3PING 192.168.100.3 (192.168.100.3) 56(84) bytes of data. bytes from 192.168.100.3: icmp_seq=1 ttl=63 time=1.00 ms bytes from 192.168.100.3: icmp_seq=2 ttl=63 time=0.695 ms
           

在未做安全策略下,10.20.1.2 与 Host 192.168.100.3 互通成功

转发过程:

  1. guest0 本地所有数据包都转发到一个虚假的地址 169.254.1.1,发送 ARP Req。
  2. Host0 的 veth 端收到 ARP Req 时通过开启网卡的 proxy arp 代理功能直接把自己的 MAC 地址返回给 guest0
  3. guest0 发送目的地址为 guest1 的 IP 数据包
  4. 因为使用了 169.254.1.1 这样的地址,Host 判断为三层路由转发,查询本地路由 10.20.2.0/24 via 192.168.0.3 dev eth0 发送给对端 host1,如果配置 BGP,这里会看到 proto 协议为 BIRD
  5. 在发送之前匹配本地的 iptables 规则进行安全策略控制,这里略
  6. 当 host1 收到 10.20.2.2 的数据包时查找本地路由表匹配 10.20.2.2/32 dev veth0 scope link 转发到对应的 veth0 端从而到达 guest1
  7. 回程类似,略

整体转发流程简单清晰。因此可以看到,Calico 需要给所有 guest 配置一条特别的路由并利用 veth 的 proxy arp 的能力让 guest 出来的所有转发都变成三层路由转发,再利用 host 的路由表进行转发,这种方式不仅仅实现了同 host 的二三层转发,也能实现跨 host 的转发。

遗留问题

  1. 租户隔离问题
  2. Calico 的三层方案是直接在 host 上进行路由寻址,那么对于多租户如果使用同一个 CIDR 网络就面临着地址冲突的问题。
  3. 路由规模问题
  4. 通过路由规则可以看出,路由规模和 guest 分布有关,如果 guest 离散分布在 host 集群中,势必会产生较多的路由项。
  5. iptables 规则规模问题
  6. 1台 Host 上可能虚拟化十几或几十个容器实例,过多的 iptables 规则造成复杂性和不可调试性,同时也存在性能损耗。
  7. 跨子网时的网关路由问题
  8. 当对端网络不为二层可达时,需要通过三层路由机时,需要网关支持自定义路由配置,即 guest 的目的地址为本网段的网关地址,再由网关进行跨三层转发。

总结

  1. Calico 通过巧妙的引导 workload 所有的流量至一个特殊的网关 169.254.1.1,从而引流到 host 的 calixxx 网络设备上,形成了二三层流量全部转换 host 的三层流量转发。
  2. 在 Host 上通过开启 arp proxy 的能力实现 arp 代答,arp 广播被抑制在 host 里,arp 记录变成“无效记录”,抑制了广播风暴和不会有 arp 表膨胀的问题。
  3. 使用 iptables 在 host 做 policy 实现的复杂的安全模型,安全策略应用在每一台虚拟路由器上,最终形成了一个分布式的安全系统。