Calico网络结构
Calico网络模型主要工作组件:
- Felix:运行在每一台 Host 的 agent 进程,主要负责网络接口管理和监听、路由、ARP 管理、ACL 管理和同步、状态上报等。
- etcd:分布式键值存储,主要负责网络元数据一致性,确保Calico网络状态的准确性,可以与kubernetes共用;
- BGP Client(BIRD):Calico 为每一台 Host 部署一个 BGP Client,使用 BIRD 实现,BIRD 是一个单独的持续发展的项目,实现了众多动态路由协议比如 BGP、OSPF、RIP 等。在 Calico 的角色是监听 Host 上由 Felix 注入的路由信息,然后通过 BGP 协议广播告诉剩余 Host 节点,从而实现网络互通。
- BGP Route Reflector:在大型网络规模中,如果仅仅使用 BGP client 形成 mesh 全网互联的方案就会导致规模限制,因为所有节点之间俩俩互联,需要 N^2 个连接,为了解决这个规模问题,可以采用 BGP 的 Router Reflector 的方法,使所有 BGP Client 仅与特定 RR 节点互联并做路由同步,从而大大减少连接数。
Felix
Felix会监听ECTD中心的存储,从它获取事件,比如说用户在这台机器上加了一个IP,或者是创建了一个容器等。用户创建pod后,Felix负责将其网卡、IP、MAC都设置好,然后在内核的路由表里面写一条,注明这个IP应该到这张网卡。同样如果用户制定了隔离策略,Felix同样会将该策略创建到ACL中,以实现隔离。
BIRD
BIRD是一个标准的路由程序,它会从内核里面获取哪一些IP的路由发生了变化,然后通过标准BGP的路由协议扩散到整个其他的宿主机上,让外界都知道这个IP在这里,你们路由的时候得到这里来。
架构特点
由于Calico是一种纯三层的实现,因此可以避免与二层方案相关的数据包封装的操作,中间没有任何的NAT,没有任何的overlay,所以它的转发效率可能是所有方案中最高的,因为它的包直接走原生TCP/IP的协议栈,它的隔离也因为这个栈而变得好做。因为TCP/IP的协议栈提供了一整套的防火墙的规则,所以它可以通过IPTABLES的规则达到比较复杂的隔离逻辑。
Node上的Pod通信
1、每个Node的Pod的IP分配都是基于每个node上的pod-cidr配置的,相同node上的pod分别的ip都是 同一个网段的,不同node的pod网段不一样。比如: node1上分配的pod-cidr网段是: 172.20.192.x,node2上分配的pod-cidr网段是: 172.20.193.x,那么在node1分配的pod的ip的都是172.20.192.xx 172.20.192.cc 。然后通过pod-cidr的网段就可以知道当一个pod需要和其他pod通信时是否在同一个node中,如果是在同一一个node上,那么网段肯定是一致的,那么就直接通过calixxx01 ------> 本机路由表--->calixxx02 来实现通信,如果不是同一个网段的就直接通过ipip隧道,把数据在封装成对方pod所在的node节点的ip.
准备知识点
veth pair
veth pair
(虚拟以太网设备对)是 Linux 内核提供的一种网络接口类型,它允许创建一对相互连接的虚拟网络接口。这两个接口之间形成一个双向通道,任何发送到其中一个接口的数据包都会从另一个接口接收。这在容器化环境中特别有用,因为它可以用来建立宿主机与容器之间的网络通信,以及容器之间的网络通信。
veth pair 的工作原理
-
创建:当你在系统中创建一个
veth pair
时,实际上是在内核网络栈中同时创建了两个接口。这两个接口总是成对存在,并且它们之间形成了一个点对点的连接。 -
命名空间分离:在 Kubernetes 或 Docker 等容器化平台中,通常会将这对接口中的一个放置在宿主机的根命名空间中,而另一个则移动到容器的独立网络命名空间中。这样做的目的是让容器拥有自己的网络栈,从而实现网络隔离。
-
桥接或直接路由:宿主机上的那一端可以被添加到一个 Linux 桥接设备上(如 Docker 默认行为),或者通过路由规则直接与其他网络接口相连。对于 Calico 这样的 CNI 插件,它倾向于使用 BGP 来动态配置路由,而不是依赖于传统的桥接方式。
-
数据传输:当容器内的应用程序尝试发送数据包时,这些数据包会被发送到容器命名空间中的那个 veth 接口;然后,数据包会出现在宿主机命名空间中的配对 veth 接口上,再根据路由表决定下一步去哪里。反之亦然,来自外部网络的数据包也会通过同样的路径到达容器。
-
网络策略和安全:由于每个 Pod 都有自己的 veth 对,网络插件(例如 Calico)可以在这些接口上应用细粒度的安全策略,限制哪些流量可以进出容器,从而增强了集群的安全性。
在 Kubernetes 中,每当一个新的 Pod 被创建时,CNI 插件(比如 Calico)就会负责设置这个 Pod 所需的所有网络资源,包括创建并配置相应的 veth pair
。具体来说:
- 一个 veth 接口被放在宿主机的网络命名空间中,并连接到 Calico 的路由机制。
- 另一个 veth 接口被移到新创建的 Pod 的网络命名空间中,成为 Pod 的默认网卡(eth0)。
这种设计不仅实现了容器间的高效通信,还确保了良好的网络隔离性和安全性,使得 Kubernetes 能够支持复杂的微服务架构和多租户环境。
有个问题是:Node怎么知道其他Node的pod-cidr的网段呢?
这个就需要通过每个节点上运行的bird+felix协作来完成,每一个节点加入时,calico组件会为本机分配一个pod-cidr的pod的网段,然后通过bird协议来告诉集群中的其他节点。然后其他节点得到消息之后,就修改路由表信息。