目录
Please enable Javascript to view the contents

K8s网络-Calico详解

 ·  ☕ 9 分钟

系列导航

本系列从 Pod 网络连通入手,逐步展开到 K8s 网络全景。

① 概念 → ② Flannel → ③ Calico → ④ 流量路径 → ⑤ Cilium → ⑥ 对比 → ⑦ 排障 ‖ ⑧ 开发 → ⑨ 多网卡 → ⑩ AI 演进

顺序文章定位
概念与入门基础——主机网络、Docker 网络、CNI 标准、方案分类树
Flannel 详解CNI 实现——Overlay 封装(UDP/VXLAN/HostGW)与抓包
本篇 - Calico 详解CNI 实现——三层路由(BGP/IPIP)+ NetworkPolicy
流量路径全解析全貌——Pod/Service/Ingress/Egress,揭示 CNI 的边界
Cilium 详解超越 CNI——eBPF 统一 Pod + Service + L7 + Hubble
插件对比与选型选型——5 插件横向对比 + 决策树
排障思路与常用命令运维——工具链 + 场景排查 + 性能
核心路径 ↑扩展展望 ↓
CNI 插件开发指南扩展——基于 CNI 规范开发自定义插件
多网卡方案详解进阶——Multus + SR-IOV/ipvlan 多网口实战
AI 时代网络演进展望——GPU 网络、eBPF 加速、未来方向

Calico 由 Tigera 维护,核心设计思想:将二三层流量全部收敛为三层路由——不存在类似 Flannel cni0 的独立网桥,veth pair 对端直接挂在宿主机协议栈,所有流量走三层路由决策。


1. Calico 架构

组件

Felix —— 每个节点上的核心 Agent,以 DaemonSet 部署。负责本节点路由表、iptables 规则、网络策略的配置与同步。

BIRD —— BGP 客户端,负责向集群内/外宣告本节点的 Pod 子网路由,动态扩散路由信息。

confd —— 监听 Etcd/K8S API 变更,触发 BIRDFelix 重载配置。

Pod-Node 通信模型

Calico 通过两个关键机制将 Pod 流量全部转换为三层路由:

1. 虚拟网关 169.254.1.1 —— 每个 Pod 的默认路由都指向 169.254.1.1,但没有任一网卡对应此 IP。Calico 在宿主机 cali* 网卡上开启代理 ARP,当 Pod 发 ARP 找 169.254.1.1 的 MAC 时,宿主机用自己的 MAC(ee:ee:ee:ee:ee:ee)应答。Pod 所有出站流量因此被引向宿主机协议栈。

2. 代理 ARP —— ARP 广播被抑制在宿主机内,不会泛洪到其他节点,避免了广播风暴和 ARP 表膨胀。/proc/sys/net/ipv4/conf/cali*/proxy_arp = 1

  1. 选取节点node1中的容器pod-a作为实验节点,进入容器pod-a查看IP地址:

172.17.8.2/32 容器IP地址为/32位的地址,表示容器是一个单点的局域网

1
2
3
4
5
6
7
8
9
[root@pod-a-bc2sm /]$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
3: eth0@if771: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1440 qdisc noqueue state UP
    link/ether 66:fb:34:db:c9:b4 brd ff:ff:ff:ff:ff:ff
    inet 172.17.8.2/32 scope global eth0
       valid_lft forever preferred_lft forever
  1. 查看容器pod-a的默认路由:

根据以下路由表信息可以知道:169.254.1.1为容器默认网关,但没有任一网卡对应此IP地址。
当一个数据包的目的地址不是本机时,会查询路由表,从路由表查询到网关后,会通过arp获取网关的mac地址,然后在二层网络数据包中将目标mac替换为网关的mac地址。也就是说,网关IP只是为了能找到网关的mac地址,响应arp就行。

1
2
3
[root@pod-a-bc2sm /]$ ip route
default via 169.254.1.1 dev eth0
169.254.1.1 dev eth0 scope link
  1. 查看容器的arp缓存:

ip neigh: 用于查看系统上的邻居表(Neighbor Table),通常也称为ARP缓存表。这个表存储本机与其它机器或网络设备之间的关联。
返回信息依次为: 目标设备IP地址(169.254.1.1) 与目标设备通信的网卡(dev eth0) 目标设备mac地址(lladdr ee:ee:ee:ee:ee:ee) 与目标设备通信状态(REACHABLE)
arp获取mac地址过程:内核会对外发送arp请求,询问二层网络中拥有169.254.1.1地址的mac,拥有此ip的设备会在二层网络中响应自己的mac地址。
mac地址为calico设置的,如何响应arp:容器和主机都没有169.254.1.1IP地址,甚至连主机上的端口 calicba2f87f6bb,MAC 地址也是一个无用的 ee:ee:ee:ee:ee:ee。按道理容器和主机网络根本就无法通信,但calico采用了网卡代理arp功能。

1
2
[root@pod-a-bc2sm /]$ ip neigh
169.254.1.1 dev eth0 lladdr ee:ee:ee:ee:ee:ee REACHABLE
  1. 代理arp

代理ARP(Proxy ARP): 是 ARP 协议的一个变种,当 ARP 请求目标跨网段时,网关设备收到此 ARP 请求,会用自己的 MAC 地址返回给请求者。

确认宿主机开启了代理arp:

1
2
cat /proc/sys/net/ipv4/conf/calicba2f87f6bb/proxy_arp
1

与 Flannel VXLAN 的关键区别

对比点Flannel VXLANCalico VXLAN
veth 对端插入 cni0 网桥,降级为端口直接挂在宿主机 cali* 接口
同节点 Pod 通信cni0 CAM 二层转发宿主机路由表直接三层转发
跨节点路径Pod → cni0 CAM → 路由 → VTEPPod → 路由 → VTEP(无网桥层)
广播/ARP依赖 cni0 泛洪代理 ARP 抑制在主机内

2. Calico 后端模式

Calico 支持四种后端,按数据路径分为:Overlay 封装(VXLAN/IPIP)、路由模式(BGP/RR)。

backend适用场景优点限制层次实现方式
VxLAN底层不支持 BGP,需二层 Overlay兼容性好,通用标准协议有封装开销(~50B)L2 Overlay内核态 VXLAN,控制平面与 BGP 解耦
IPIP底层不支持 BGP,只需三层互通封装开销极小(~4B),性能好只支持 IP 单播L3 Overlaytunl0 设备内核态 IP-in-IP
BGP底层网络支持 BGP,追求最高性能性能最高,可观测性好要求底层网络支持 BGP路由(不封装)BIRD 通过 BGP 扩散 Pod 子网路由
RRBGP 大规模部署(>50 节点)避免全节点 Mesh 的 N² 复杂度需额外配置 RR 节点路由BGP Route Reflector

2.1 Overlay: VXLAN 模式

通路:内核 VXLAN(同 Flannel),但 veth pair 不经过 cni0 网桥,直接对接宿主机 cali* 接口进入 VTEP 隧道,路径比 Flannel 少一跳 CAM 转发。

2.1.1 组件概念

Calico VXLAN 模式与 Flannel VXLAN 封装协议相同,区别在数据路径——去掉了网桥层:

对比项Flannel VXLANCalico VXLAN
veth 对端插入 cni0 网桥,降级为端口直接挂在宿主机 cali* 接口
同节点 Pod 通信cni0 CAM 二层转发宿主机路由表直接三层转发
跨节点路径Pod → cni0 CAM → 路由 → VTEPPod → 路由 → VTEP(无网桥层)

2.1.2 路由规则对比

Flannel 的 veth 插入 cni0 网桥后降级为端口,失去独立三层转发能力。本地 Pod 流量共享一条路由:

1
2
# Flannel:一条路由覆盖本节点全部 Pod
10.244.1.0/24 dev cni0 proto kernel scope link src 10.244.1.1

Calico 的 cali* 没有网桥承载,每个 Pod 的 veth 对端保留完整网卡能力,不降级。代价是每个 Pod 需要一条独立路由:

1
2
3
4
# Calico:每个 Pod 各一条 /32 路由
10.244.1.5/32 dev cali0a4fde325ea scope link
10.244.1.6/32 dev cali43af9e40d9b scope link
10.244.1.7/32 dev cali8b2c1e77f3a scope link

假设节点上有 30 个 Pod——Flannel 一条路由,Calico 三十条。原理如下:

Flannel VXLAN:
  Pod eth0 ←→ veth pair → cni0端口(已降级)
                              ↓
  IP包进入cni0后,cni0作为二层网桥按CAM转发到目标端口
  同节点:乙Pod.MAC → CAM查端口 → 乙veth → 乙Pod
  跨节点:宿主机路由 10.244.2.0/24 → flannel.1 → VXLAN封装

Calico VXLAN:
  Pod eth0 ←→ veth pair → cali0a4fde325ea (独立网卡,不降级)
                              ↓
  IP包进入cali*接口后直接进宿主机路由决策
  同节点:查路由表匹配 /32 → 下一跳 = 乙cali* → 乙Pod
  跨节点:查路由表匹配远端子网 → vxlan.calico → VXLAN封装

结论: Calico 用更多路由规则换取更精简的数据路径——去掉了网桥层的 CAM 学习和广播泛洪,代价是路由表规模随 Pod 数量线性增长。

2.2 Overlay: IPIP 模式

通路:tunl0 设备内核态 IP-in-IP 封装——在原始 IP 包外再封一层 IP 头,纯三层隧道,~4B 开销,不涉及 MAC 学习。

封包格式:|HostMAC|HostIP|IPIP|内层IP|Data|

2.2.1 组件概念

IPIP (IP-in-IP) 是 Linux 内核的一种隧道模式,将一个 IP 包封装在另一个 IP 包中。作用相当于一个基于 IP 层的网桥——通过两端路由做一个 tunnel,把不通的网络点对点连接起来。

IPIP vs VXLAN 对比:

维度IPIPVXLAN
封装开销~4B(仅 IPIP 头)~50B(MAC+IP+UDP+VNI)
工作层次L3(IP-in-IP)L2(L2-in-UDP)
二层流量不支持(仅 IP 单播)支持(ARP、多播等)
MAC 学习不需要需要 FDB 表
性能略优良好
适用场景只需三层互通需二层互通或标准 Overlay

2.2.2 封装流程

流程说明

报文从 Pod 发出,根据路由发往网关 169.254.1.1

2.2.3 抓包验证

以两个node上的两个容器为例,说一下报文的流动过程。
k8s-cni-calico-ipip.png

报文从PodA(10.244.104.14)发出,根据路由发往容器中的网关169.254.1.1
但PodA中路由信息如下(没有):

1
2
3
4
5
[root@pod-a-bc2sm /]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags   Metric  Ref Use Iface
0.0.0.0         169.254.1.1     0.0.0.0         UG      0       0   0   eth0
169.254.1.1     0.0.0.0         255.255.255.255 UH      0       0   0   eth0

查看网关通向的二层地址(mac地址),容器中网关arp地址为ee:ee:ee:ee:ee:ee

1
2
3
[root@pod-a-bc2sm /]# arp -n
Address           HWtype  HWaddress           Flags Mask      Iface
169.254.1.1       ether   ee:ee:ee:ee:ee:ee   C               eth0

集群节点上执行下面命令,查看mac地址ee:ee:ee:ee:ee:ee对应的网卡

1
2
3
4
5
6
[root@node1 /]# ifconfig | grep -E "flags|ether"
cali0a4fde325ea: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1480
        ether ee:ee:ee:ee:ee:ee  txqueuelen 0 (Ethernet)
cali43af9e40d9b: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1480
        ether ee:ee:ee:ee:ee:ee  txqueuelen 0 (Ethernet)
...

容器中网卡是veth的pair虚拟网卡,一端连接容器(pod-a:eth0),一端连接宿主机(node-a:cali0a4fde325ea)。因此,执行下面命令,查看容器内网卡编号:

1
2
3
[root@pod-a-bc2sm /]# ethtool -S eth0
NIC statistics:
     peer_ifindex: 14

确认宿主机编号为14的网卡

1
2
3
4
[root@node1 /]# ip link show
...
14: cali0a4fde325ea@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1480 qdisc noqueue state UP mode DEFAULT
    link/ether ee:ee:ee:ee:ee:ee brd ff:ff:ff:ff:ff:ff link-netnsid 4

因此容器 pod-a 的报文通过 cali0a4fde325ea 网卡到达宿主机 node1,然后根据宿主机路由发往 tunl0 进入 IPIP 隧道。

2.3 Underlay: BGP 模式

通路:BGP 纯三层路由——每个节点作为 vRouter,BIRD 向全集群扩散 Pod 子网路由,数据包直接按宿主机路由表转发,零封装。

2.3.1 组件概念

Calico BGP 的核心设计: 每个节点都是一个 vRouter,通过 BGP 协议宣告本节点的 Pod 子网路由。

工作原理:

  1. 每个节点运行 Felix 进程,负责本机路由、iptables 规则、网络策略
  2. 每个节点运行 BIRD(BGP 客户端),负责扩散 Pod 子网路由
  3. BGP 有三种部署模式:
模式适用规模说明
Node-to-Node Mesh< 50 节点全节点两两建立 BGP Peer,配置最简单
Route Reflector> 50 节点指定中心路由反射器,其他节点只与反射器建 Peer
External BGP机房级与物理机房路由器建立 BGP Peer,Pod 子网直接宣告到机房网络

2.3.2 主要流程

数据包流程: Pod → 宿主机路由表 → 目标节点 → 目标 Pod

无任何封装、无隧道、无 Overlay。纯 IP 转发,性能等于裸机网络。

核心优势:

  • 性能最高,可观测性最好(标准网络工具 tcpdumptraceroute 都能调试)
  • 原生支持 NetworkPolicy(iptables/eBPF 实现)
  • 可与物理网络的 BGP 路由器对等,直接将 Pod 路由宣告到机房网络

限制:机房网络必须允许 BGP 协议(很多公有云 VPC 不支持),部署复杂度高于 Flannel。

2.4 Underlay: Route Reflector 模式

2.4.1 组件概念

Calico维护的网络在默认是(Node-to-Node Mesh)全互联模式,Calico集群中的节点之间都会相互建立连接,用于路由交换。
但是随着集群规模的扩大,mesh模式将形成一个巨大服务网格,连接数成倍增加。这时就需要使用 Route Reflector(路由器反射)模式解决这个问题。

3. 流量加密

集群内的 pod 流量使用 Wireguard 进行加密,它可以创建和管理节点之间的隧道,提供安全的通信。

4. 网络策略

Calico 的网络策略实现了拒绝/匹配规则,可通过清单为 pod 分配入口策略。支持全局范围策略,可与 Istio 集成控制 pod 流量。


5. 总结

维度BGPIPIPVXLAN
封装开销0~4B~50B
路由方式BGP 动态路由IP-in-IP 隧道L2-in-UDP 隧道
性能最高(裸机)良好良好
二层流量不支持不支持支持
适用场景自建机房公有云(只需L3)公有云(需L2)

参考链接

Calico 网络策略确保 CNI 的安全

Kubernetes 网络:使用 Calico 实现高性能

分享

Hex
作者
Hex
CloudNative Developer