知识卡片

Calico的核心思路:让容器网络完全落回三层路由,不需要NAT也不需要隧道封包

结构图卡

内容

Calico是一个纯三层的SDN实现,基于BGP协议和Linux自身的路由转发机制运作,不依赖任何特殊硬件,也不使用隧道封包技术。它实现跨节点容器通信的关键思路是:把容器网络的问题彻底还原成传统IP网络里”路由表该怎么写”这个经典问题,而不是发明一套新的封装协议。具体流程是——容器启动时,Calico通过劫持Docker API介入网络初始化:如果没有指定IP就查询Etcd自动分配一个可用IP,创建一对veth接口用于容器和宿主机之间通信,给容器内的接口配好IP并开启IP转发;接着在宿主机的本地路由表里添加一条指向这个veth接口的路由;最关键的一步是,Calico节点之间通过BGP协议建立连接,本地新增的这条路由会通过BGP广播给其他所有Calico节点,让每个节点的路由表都知道”要到达某个具体的容器IP,应该把数据包转发给哪台宿主机”。这样当node2上的container2要访问node1上的container1时,只需要查一次本地路由表,就知道要把数据包转发给node1这台物理机,整个过程完全没有经过任何NAT地址转换,也没有经过任何隧道封包解包——数据包在网络层面走的路径和传统物理网络里跨网段路由完全一样,容器网络的”特殊性”被彻底封装消解掉了,暴露给底层网络的就是一套标准的三层路由。这个设计给出了一条重要的架构启示:面对”如何让新的抽象单元(容器)具备旧世界(物理网络)原生就有的能力(跨网段通信)”这类问题,最优雅的解法有时不是在旧能力之上叠加一层新协议去适配新单元,而是想办法把新单元的行为特征改造成能够直接复用旧能力本身——只要三层网络可达,Calico就能工作,这个”够简单”的适用条件正是省去额外协议层带来的直接收益。

结构图

sequenceDiagram
    participant C1 as container1(node1, 192.168.0.1)
    participant N1 as node1路由表
    participant Etcd as Etcd集群
    participant N2 as node2路由表
    participant C2 as container2(node2, 192.168.0.2)

    Note over C1,N1: container1启动时Calico劫持Docker API
    C1->>Etcd: 查询/分配可用IP
    N1->>N1: 添加本地路由(192.168.0.1→veth接口)
    N1->>N2: 通过BGP协议广播此路由
    Note over N2: node2路由表新增:\n访问192.168.0.1需转发给node1(192.168.78.21)
    C2->>N2: 查路由表,访问192.168.0.1
    N2->>N1: 直接转发数据包给node1(无NAT无Tunnel)
    N1->>C1: 转发到container1的veth接口

参考来源

- 位置:《高可用架构(第1卷)》第4章《容器与云计算》"4.3 使用开源Calico构建Docker多租户网络"节,"4.3.2 使用Calico实现Docker的跨服务器通信"(源文件:_epub-src/OEBPS/Text/Chapter4_3_3.xhtml) - 结论依据:原文详细描述路由实现流程("Calico节点启动后会查询Etcd,和其他Calico节点使用BGP协议建立连接……在主机路由表添加指向此接口的路由……然后将此路由通过BGP协议广播给其他所有节点"),并总结"整个流程没有任何NAT、Tunnel封包。所以只要三层可达的环境,就可以应用Calico",直接支撑本卡片结论与结构图。 - 原始内容:Calico节点启动后会查询Etcd,和其他Calico节点使用BGP协议建立连接……在主机路由表添加指向此接口的路由……然后将此路由通过BGP协议广播给其他所有节点……至此,跨节点通信打通,整个流程没有任何NAT、Tunnel封包。