基于BGP协议的Calico IPIP 网络

时间:2023-01-14 11:57:05

*本文是​​Envoy透明流量劫持和路由转发(Calico网络)学习笔记​​的后续笔记

calico 是 tigera 公司开源的一个 k8s 网络的一整套解决方案。

1、Calico 的主要网络模式有两种,一种是 tunnel 模式,一种是路由模式。其中 tunnel 模式又同时支持 vxlan 和 ipip。(calico 现在也已经支持了 ebpf 模式

2、知识点

  • BGP和IPIP不是二选一的关系,类似via 192.168.31.218等其它host的路由信息需要通过BGP(bird在每台主机上开启BGP协议的客户端进程,bird创建出口 ifacetunl0 设备的规则;Feilx监听etcd)来获取。

# route -n
Destination Gateway Genmask Flags Metric Ref Use Iface
172.17.54.128 192.168.31.218 255.255.255.192 UG 0 0 0 tunl0
[root@k8s-node01 ~]# ip r
172.17.0.0/16 via 192.168.31.219 dev tunl0 proto bird onlink
172.17.54.128/26 via 192.168.31.218 dev tunl0 proto bird onlink //192.168.31.218node的tunl0@NONE172.17.54.128
blackhole 172.17.125.0/26 proto bird //自己的话blackhole
  • ipipMode: Always 实验室是Always。 
    ipipMode还有subnet模式,假设两个node 都在同一个网段,就会不封装,直接走网络bgp模式,如果不在同一个网段,就会使用ipInip模式。
  • 在大型网络规模中,如果仅仅使用BGP client形成mesh全网互联的方案就会导致规模限制,50 台node以上calico建议使用RR(Router Reflector
    )也就是路由反射器。
  • cali的mac地址并不会在实际的链路层报文中使用,因此calico将所有cali网络设备的mac地址都设置为全e
  • 创建一条黑洞路由(route 10.244.2.0/24 blackhole)的作用, 和 ip route add blackhole 效果一样,走这条路由规则的数据包都会被丢弃(其实可以通过抓包 lo 网卡看到),Calico 中需要黑洞是为了当同一台节点中的 pod 互相访问的时候,不让数据流出到其他节点
  • “/etc/calico/confd/config/bird.cfg”是 Calico 运行 BIRD 最主要的配置文件,这个文件在容器里:

# 这个 krt_tunnel 其实在原始的 BIRD 的 c 代码中是没有的
# 这个变量是 Calico 自己加的, 表示设置路由表是的 iface 要走 tunl0
filter calico_kernel_programming {
if ( net ~ 10.244.0.0/16 ) then {
krt_tunnel = "tunl0";
accept;
}
accept;
}

——Calico 自己 fork 了一份儿 BIRD 的代码,给改成了一个只支持 IPIP 的轻量级 BIRD。整体流程上,其实就是做了大概如下几件事儿:

  • 从 IPAM 中获取一个还没有使用的 ip 地址作为本 pod 的 ip
  • 创建一对儿 veth pair,一边放在 pod 的 netns 中,一边留在 host 上
  • 给 pod 的 netns 设置交换路由
  • 并把 pod 留在 host 的那半拉 veth 开启 proxy_arp 以及 forwarding
  • 然后创建 ipip tunnel 设备
  • 给这个 ipip tunnel 设备一个 ip 地址
  • 开启 ipip tunnel 设备的 forwarding
  • 创建 BIRD 配置文件。注意这里因为每个节点的 ip 之类的配置信息都不一样,所以这里需要通过 template 的方式动态生成模板的字符串
  • 启动从 calico bird 那编译好的 bird 程序,注意这个程序你得想办法让它以独立子进程的方式执行哦
  • 把 pod ip 返回给外边,也就是返回给 kubelet

3、不同网络模式是怎么获取信息(每个host是如何获取其他host的路由信息),创建iptables规则

  • host-gw 模式是每次启动一个 pod 时都去 etcd 中拉一下其他节点的 nodeip 以及 podip 的对应信息;
  • ebpf 是通过 watch etcd,当有 pod 被创建时 etcd 自动同步给每个节点;
  • BGP 协议就有点类似于 watch etcd 的那种方式,本质上都是在每个节点上启动一条进程,这条进程会监听本机的路由表以及网络设备变化,同时还能将这些变化发送给在同一个 “自治系统” 中的其他 BGP 客户端。
  • Feilx 是 Calico 中和BIRD程序同步运行的另外一条进程,主要作用就是监听 etcd,当节点上要创建 pod 时,ipam 会分配 ip,然后这个 ip 会写入到 etcd,此时这个 Feilx 就能通过监听 etcd 来感知到被分配了哪些 ip,然后把这些 ip 写入到本机的路由表,此时 BIRD 进程就能监听到路由表发生了变化,然后把新的路由规则根据配置给宣告出去。
  • Feilx 进程除了创建路由表的条目之外,还会创建很多 iptables 规则,通过这些 iptables 规则的一些策略来让 Calico 的网络变得更健壮。

4、BIRD 是一个实现了多种动态路由协议(比如 BGP、OSPF 等),可以运行在 Linux/Unix 操作系统的程序。决定 “哪些本机的路由可以发给其他节点”,“本机可以接收哪些路由信息”,“本机可以和哪些节点形成自治系统”

  • BIRD 在内存中维护了一个自己的路由表,这张路由表和 Linux 中的路由表(FIB 表)不一样。BIRD 的这张表中的内容包含 BIRD 自己从 Linux 的 FIB 路由表中收集到的本机的路由信息,以及从其他 BIRD 客户端接收到的其他节点的路由信息BIRD 会根据一些策略算法,把其他节点发过来的路由信息写入到 Linux 本机的路由表,也就是 FIB 表中,以此来让当前节点感知到其他节点上的 ip 变化。
  • Linux路由表被bird配置了新的路由规则了,就像 calico 这样,会有一些出口 iface 是 tunl0 设备的规则
  •  calico 自己实现了一个 bird,这个 bird 可以在每台主机上开启 BGP 协议的客户端进程,用来做路由宣告。
  • 在运行 BGP 的客户端进程之前,需要指定一个 AS 号,一共有 2^32 次方个,这些自治网络的 AS 号需要由一个叫 IANA 的国际组织来颁发的。从 64512 到 65534 中间的一千多个 AS 号是可以给自己玩着用的。其中 64512 这个号码就是 calico 默认的 BGP 网络的 AS 号。

# 表示当前节点的 ip
router id 192.168.64.14;
# 创建自己的一条邻居
# neighbor 是其他节点的 ip
# source address 是自己的 ip
protocol bgp Mesh_192_168_64_16 from bgp_template {
neighbor 192.168.64.16 as 64512;
source address 192.168.64.14; # The local address we use for the TCP connection
}

5、calico 会通过 deamonset 在每台节点上都运行一个 “calico-node”。

  • 使用 pstree 查看这个容器进程可以发现首先启动了 pause 进程,然后就是通过 “bird6” 以及 “bird” 命令启动了 BIRD 进程,同时还运行了 felix 进程;
  • calico-node容器是一个hostNetwork类型的网络,也就是说它容器里操作网络就相当于操作宿主机的网络。这也是容器中的 BIRD 和 Feilx 进程能修改 host 路由信息的缘故。