说明:本文由 Codex 根据作者提供的主题、素材与公开资料辅助生成,属于 AI 生成/整理内容,非作者原创。请读者自行甄别并交叉验证。
先区分两个问题#
Calico 经常和 Service、kube-proxy、Ingress 等概念一起出现,但它主要回答的是另一个层面的问题:
Pod IP 到 Pod IP 的三层连通性怎么实现?
NetworkPolicy 规则怎么在节点上执行?
跨节点流量要直接路由,还是封装后转发?而 Kubernetes Service 主要回答的是:
客户端访问一个稳定的虚拟 IP 或服务名时,如何转到后端 Pod?所以排查网络问题时,最好先把问题拆开:
| 问题 | 常见责任组件 |
|---|---|
| Pod 是否有 IP | CNI 插件、IPAM |
| Pod IP 到 Pod IP 是否可达 | Calico 路由或封装数据面 |
| Service ClusterIP 是否可用 | kube-proxy 或 eBPF Service 处理 |
| DNS 名称是否能解析 | CoreDNS、Service、EndpointSlice |
| 流量是否被安全策略拦截 | Calico NetworkPolicy、Kubernetes NetworkPolicy |
如果访问 Pod IP 正常,但访问 Service 不正常,优先看 Service、EndpointSlice 和 kube-proxy。
如果访问 Pod IP 本身就不通,优先看 Calico 路由、封装模式、节点防火墙和网络策略。
Calico 的核心思路#
Calico 的默认思路很接近传统三层网络:
每个 Pod 拿到一个可路由的 IP;
每个 Node 知道本机 Pod 的路由;
跨 Node 时,通过路由或封装把包送到目标 Node;
目标 Node 再把包送进目标 Pod。以 Pod A 访问 Pod B 为例:
Pod A
↓
Pod A 所在 Node 的 veth / 路由表
↓
本机转发或跨节点转发
↓
Pod B 所在 Node
↓
Pod B同节点通信时,流量通常只在本机转发,不需要跨宿主机网络。
跨节点数据包如何到达目标节点,取决于路由和 IPPool 配置:原生三层路由、IPIP 或 VXLAN。
另一个独立选择是数据面实现:传统 Linux 路由和 iptables 路径,或 eBPF 数据面。eBPF 可以替换部分策略和 Service 处理逻辑,但它不是与 BGP、IPIP、VXLAN 并列的一种封装方式。
从 kube-proxy 已选出目标 PodIP 开始追包#
这一节只讨论 Service 已经选定后端 Endpoint 之后的部分。以传统 kube-proxy 的 iptables 或 IPVS 数据面为例,kube-proxy 会根据 Service 和 EndpointSlice 选择 Pod B,并把访问 Service VIP 的请求改写到该 Endpoint。
假设有如下地址:
Pod A:10.244.1.10,位于 Node A(172.16.1.11)
Service:10.96.0.100:80
Pod B:10.244.2.20:8080,位于 Node B(172.16.2.12)Pod A 发起请求时,应用最初看到的目标是 Service:
10.244.1.10:<client-port> -> 10.96.0.100:80在这里设定的前提下,源节点的 kube-proxy 已选择 Pod B,并完成到 Endpoint 的 DNAT。后续交给 Calico 的关键内层报文可以抽象为:
10.244.1.10:<client-port> -> 10.244.2.20:8080这个内层报文的目标已经是 Pod B 的真实 IP。Calico 接下来不再关心这是由哪个 Service 选出来的,而是按“如何到达 10.244.2.20”来执行路由、封装和 NetworkPolicy。
上面的源 IP 只用于讲解最常见的 Pod 到 ClusterIP 场景。是否额外做 SNAT,还会受 Service 类型、externalTrafficPolicy、masquerade 配置和流量入口位置影响;因此排障时应以抓包和 conntrack 中的实际五元组为准。
以下所有链路都默认源端 egress 与目标端 ingress 的 NetworkPolicy 已允许该连接。
先看共同的分叉点#
Pod A
-> kube-proxy 选择 Endpoint 并 DNAT 到 Pod B IP
-> Node A 查询到 10.244.2.20 的路由
-> Pod B 在 Node A:直接交付本机 veth
-> Pod B 在 Node B:按无封装、IPIP 或 VXLAN 送到 Node B
-> Node B 解封装(如有)并路由到 Pod B 的 veth
-> Pod B决定分支的是目标 Pod IP 的路由,而不是 Service VIP。也就是说,kube-proxy 的 Endpoint 选择与 Calico 的跨节点转发是前后衔接、但职责不同的两段。
目标 Pod 与源 Pod 同节点#
若 Pod B 也在 Node A,DNAT 后的包不会离开该节点:
Pod A
-> veth
-> Node A 的路由与策略处理
-> 指向 10.244.2.20 的本机 cali* / veth 路由
-> Pod B报文始终是内层的 PodAIP -> PodBIP,不需要 BGP、IPIP、VXLAN,也不会经过物理网卡或宿主机 underlay。此时如果 Service 请求失败,而直接访问 Pod B IP 成功,优先检查 Service、EndpointSlice 和 kube-proxy;如果两者都失败,再看本机策略、Pod 网络命名空间和应用监听。
跨节点无封装:BGP 发布路由,报文保持原样#
这里的“BGP 模式”特指 BGP 加无封装 Pod 路由。BGP 是控制面协议,它把“10.244.2.0/24 在 Node B”这样的路由信息发给 Node A 或上游路由器,本身不为每个数据包加头或转发数据。
Node A 上的路由语义:10.244.2.0/24 via 172.16.2.12
Pod A
-> Node A 路由表命中 Pod B 的远端路由
-> 物理网卡 / underlay
在线路上的 IP 包仍是:10.244.1.10 -> 10.244.2.20
-> Node B
-> Node B 的本机 Pod 路由 / veth
-> Pod B此模式下 underlay 必须能承载或学习 Pod CIDR 的路由;否则它只看到一个去往 10.244.2.20 的普通 IP 包,却不知道下一跳在哪里。Calico 官方文档中的典型数据路径也是:Felix 为本机工作负载配置直连路由,BGP 客户端把远端工作负载路由分发出去。
不要把“启用了 BGP”直接等同于“无封装”。Calico 也可以使用 BGP 分发 IPIP Pool 的路由;真正决定线路上有没有额外包头的是 IPPool 的封装配置。
跨节点 IPIP:外层只使用节点 IP#
IPIP 的路由结果是把前述内层包交给 tunl* 一类隧道接口,并增加一个 IPv4 外层头:
外层 IPv4:172.16.1.11 -> 172.16.2.12,协议号 4
内层 IPv4:10.244.1.10 -> 10.244.2.20完整路径如下:
Pod A
-> Node A 路由到 IPIP 隧道接口
-> IPIP 封装
-> underlay 仅路由 Node A IP 到 Node B IP
-> Node B 解封装
-> Node B 路由到 Pod B 的 veth
-> Pod B因此,underlay 无需知道 10.244.2.20 或整个 Pod CIDR 的下一跳,只要 Node A 与 Node B 的地址可达即可。IPIP 仅支持 IPv4;抓包时可用 tcpdump -ni any proto 4 观察外层报文。
ipipMode: Always#
对需要离开源节点、且目标位于该 IPPool 中的工作负载流量,Calico 总是使用 IPIP 封装。Pod B 位于同一节点时仍会优先走本机的直连 Pod 路由,不会为了绕一圈而发送隧道报文。
ipipMode: CrossSubnet#
CrossSubnet 的判断对象是 Node A 与 Node B 所在的底层子网,不是 Pod CIDR:
Node A 与 Node B 在同一底层子网:按无封装路径转发
Node A 与 Node B 跨底层子网:按 IPIP 路径转发它的目的,是只在经过无法自行路由 Pod CIDR 的三层边界时才付出封装开销。
跨节点 VXLAN:把内层 Pod 报文装入 UDP#
VXLAN 的逻辑和 IPIP 相同,区别在于外层是 UDP/VXLAN。默认情况下可将在线路上的包理解为:
外层 IP:172.16.1.11 -> 172.16.2.12
外层 UDP:目标端口通常为 4789
VXLAN 负载:10.244.1.10 -> 10.244.2.20 的内层报文在 Node A 上,远端 Pod 路由指向 vxlan.calico。该接口根据目标节点的 VTEP 信息封装报文;Node B 收到 UDP/VXLAN 包后解封装,再沿本机 Pod 路由交给 Pod B:
Pod A
-> Node A 路由到 vxlan.calico
-> UDP/VXLAN 封装
-> underlay
-> Node B 的 vxlan.calico 解封装
-> Node B 路由 / veth
-> Pod B与 IPIP 一样,underlay 只需让节点 IP 互通并允许 VXLAN 使用的 UDP 端口,不必理解 Pod CIDR。排障时可用 tcpdump -ni any udp port 4789 观察封装报文;实际端口可以由 Felix 配置变更,不能只凭默认值下结论。
vxlanMode: Always#
对需要离开源节点、且目标位于该 IPPool 中的工作负载流量,跨节点时都走 VXLAN。它常用于底层网络无法承载 Pod 路由、又不希望维护 BGP 的环境。
vxlanMode: CrossSubnet#
与 IPIP 的 CrossSubnet 相同:同一底层子网内的远端 Pod 流量不封装,跨底层子网时才使用 UDP/VXLAN 封装。Calico 官方文档推荐在适合的环境使用 CrossSubnet,以减少封装开销;切换封装模式可能影响进行中的连接,应在变更窗口内实施。
eBPF 数据面:先区分“谁选择 Endpoint”和“如何跨节点”#
eBPF 不是第四种隧道。它改变的是节点内核中执行 Service、策略和转发逻辑的方式,跨节点传输仍然要选择无封装路由或 overlay。
在 Calico 的标准 eBPF Service 模式中,Calico 会直接实现 Kubernetes Service 网络,而不是依赖 kube-proxy。因此此时本节开头“源节点 kube-proxy 已完成 DNAT”的前提要改成:Calico eBPF 程序已经选出目标 Pod B。从选定后端开始,仍可按同节点、本机直连、无封装路由或 VXLAN 来理解后续路径。
传统数据面:kube-proxy 选择 Endpoint -> Calico 路由 / 封装
eBPF 数据面:Calico eBPF 选择 Endpoint -> eBPF 路由 / 策略 -> 直连或 VXLANCalico 当前文档还明确了两个边界:eBPF 模式不支持 IPIP;若需要 overlay,应使用 VXLAN。若 kube-proxy 因发行版限制仍然运行,需要按 Calico 的兼容配置避免它与 eBPF 的 iptables 清理逻辑互相争用,不能把两个 Service 数据面当成互不相关的组件。
各路径的报文对照#
| 场景 | Node A 到 Node B 之间看到的报文 | underlay 需要知道什么 | Node B 的最后一步 |
|---|---|---|---|
| Pod B 在 Node A | 无跨节点报文 | 无 | 本机路由到 Pod B veth |
| BGP 加无封装路由 | 内层 PodAIP -> PodBIP 原样出网 | Pod CIDR 的路由或下一跳 | 直接按 Pod 路由交付 |
| IPIP | 外层 NodeAIP -> NodeBIP,内层仍为 PodAIP -> PodBIP | 节点 IP 可达 | 解封装后按 Pod 路由交付 |
| VXLAN | 外层 NodeAIP -> NodeBIP 的 UDP/VXLAN,内层仍为 PodAIP -> PodBIP | 节点 IP 可达且允许 VXLAN UDP | 解封装后按 Pod 路由交付 |
CrossSubnet | 同子网无封装,跨子网使用对应的 IPIP 或 VXLAN | 取决于是否跨底层子网 | 与选中的分支相同 |
回包并不是新的独立模式#
Pod B 的响应先按 PodBIP -> PodAIP 走反向 Calico 路径:无封装直接路由,IPIP 或 VXLAN 则从 Node B 向 Node A 做相应的反向封装。回到源节点后,连接跟踪会基于已建立的 Service NAT 状态执行反向改写,因此 Pod A 看到的响应通常仍来自最初访问的 Service IP 和端口,而不是突然变成 Pod B IP。
这也是 Service 请求排障常需要同时看 NAT、conntrack 与 Calico 路由的原因:正向 Endpoint 选择正确,并不自动保证跨节点封装、策略、MTU 或回包的反向 NAT 都正确。
针对这个前提的最短排查路径#
已经确认 Endpoint 为目标 Pod IP 后,可以依次确认:
# 1. 源节点此刻会怎样到达目标 Pod IP
ip route get <目标-PodIP>
# 2. 确认实际使用的 IPPool 传输方式
kubectl get ippools.crd.projectcalico.org -o yaml
# 3. 无封装时观察 Pod IP 是否直接出现在节点网卡上
tcpdump -ni <节点网卡> host <目标-PodIP>
# 4. IPIP 或 VXLAN 时分别观察外层封装
tcpdump -ni any proto 4
tcpdump -ni any udp port 4789抓包应分别在 Node A 与 Node B 上进行:源节点确认是否按预期封装或直出,目标节点确认是否收到、解封装,并能继续送到 Pod B。若只在源节点看到 Service DNAT 后的内层包,却在目标节点看不到相应流量,问题通常就在两节点之间的路由、封装端口、防火墙、安全组或 MTU。
谁在节点上工作:calico-node、CNI 与 Linux 内核#
在 Kubernetes 中,calico-node 通常以 DaemonSet 运行。它会在每个符合调度条件的节点上创建一个 Pod;对 Calico 这类 CNI 来说,通常意味着所有需要承载工作负载 Pod 的 Linux 节点。
DaemonSet 并不等于无条件覆盖所有节点。nodeSelector、node affinity 和 taint/toleration 都会影响节点是否符合条件;标签变化后,控制器会自动在新匹配节点创建 Pod,并从不再匹配的节点移除 Pod。
calico-node 主要是节点网络的控制代理,而不是逐包转发的用户态代理:
| 组件 | 主要职责 |
|---|---|
| Calico CNI 插件 | kubelet 创建 Pod 时调用它,为 Pod 接入 Calico 网络 |
Felix(calico-node 中的节点代理) | 读取配置与策略,在宿主机编程路由、cali* 接口、策略规则,以及 vxlan.calico 或 tunl* 等接口 |
| BIRD / confd(使用 BGP 时) | 发布和维护路由信息 |
| Linux 内核 | 按已配置的路由、iptables 或 eBPF 程序实际转发、封装、解封装或丢弃每一个包 |
所以,“每个节点的 Calico 接收网络包,再转给 Pod”这个说法只对结果近似正确,对实现则不准确。正常数据包并不会先进入一个 calico-node 用户态进程;是宿主机内核的数据路径把包转给目标 Pod。
以跨节点 VXLAN 为例:
Pod A
-> veth
-> Node A 内核路由
-> vxlan.calico 封装(外层:Node A IP -> Node B IP)
-> underlay 网络
-> Node B 的 vxlan.calico 解封装
-> Node B 内核路由 / veth
-> Pod B同节点 Pod 通信通常只走本机 veth 和路由,不会经过 VXLAN。使用 CrossSubnet 时,只有跨子网的通信才会封装。
为什么 calico-node 能配置宿主机网络#
calico-node 是一个 Pod,但它的 Pod 模板会被授予节点网络组件所需的宿主机访问能力。常见机制如下:
spec:
template:
spec:
hostNetwork: true
containers:
- name: calico-node
securityContext:
privileged: true上面只是结构示意,不应直接替代官方安装清单。实际 manifest 还会挂载宿主机目录,并且不同安装方式和版本的权限细节会不同。
hostNetwork: true:该 Pod 共享宿主机网络命名空间,因此看到的是节点的网络接口、路由和端口;它本身不等于获得修改权限。securityContext:可以写在 Pod 级别,也可以写在容器级别。Calico 这类节点网络组件通常需要特权模式或网络管理能力,例如NET_ADMIN,才能创建接口、写路由或加载相应配置。hostPath:常用于让初始化容器安装 CNI 二进制与 CNI 配置,或让节点代理访问所需的宿主机路径。
hostNetwork 与 securityContext 不是 DaemonSet 独有字段;它们属于 DaemonSet 的 Pod template,也同样可用于普通 Pod、Deployment 或 StatefulSet。DaemonSet 只是很适合部署这种“每个节点都需要一份”的节点级组件。
BGP、underlay、overlay 与 eBPF:不要放在同一层比较#
把 “BGP 属于 underlay,VXLAN/IPIP 属于 overlay” 当作速记可以,但更准确的分层是:
| 层次 | 解决的问题 | 典型选项 |
|---|---|---|
| 路由控制面 | 谁知道某段 Pod CIDR 应该去哪个节点 | BGP |
| 跨节点传输方式 | 数据包在线路上以什么形式发送 | 原生三层路由、IPIP、VXLAN |
| 节点数据面实现 | 内核如何执行策略、Service 与转发逻辑 | iptables / Linux 路由,或 eBPF |
因此,BGP 本身不是数据平面,也不等于 underlay。它是把 Pod 网段可达性发布给其他节点或物理网络设备的控制协议;当数据包不再封装、直接按三层路由发送时,才是在借助底层网络的原生路由能力。
IPIP 和 VXLAN 则会把原始 Pod 报文再封一层,让 underlay 只需认识节点 IP,所以它们是 overlay。eBPF 是内核中执行数据面逻辑的方式,可以与无封装路由或 VXLAN 等传输方式组合,不能简单拿来和 BGP 或 VXLAN 做一对一替换。
BGP 模式:把 Pod 网段当成路由来传播#
BGP 是 Calico 的经典模式。
每个节点会把自己负责的 Pod 网段发布出去,其他节点或上游路由设备学习到这些路由后,就能直接把目标 Pod IP 的流量送到正确节点。
大致链路是:
Pod A
↓
Node A 查路由:Pod B 网段在 Node B
↓
底层网络直接把包送到 Node B
↓
Node B 转发给 Pod B这种模式的优点:
- 不需要额外封装,报文开销低。
- 路由语义清晰,容易和传统网络集成。
- 在可控的私有数据中心、裸金属环境里很自然。
主要要求:
- 底层网络要允许节点之间直接三层互通。
- 路由规模要可控,必要时使用 Route Reflector。
- 网络团队需要接受 Pod CIDR 作为可路由地址空间。
常见排查命令:
calicoctl node status
ip route
kubectl get ippools -o wide
kubectl get bgppeers.crd.projectcalico.org如果 BGP 邻居没有建立,跨节点 Pod 通常会表现为不可达。
如果 BGP 正常但 Pod 仍不通,再继续看路由表、反向路径过滤、节点防火墙和 NetworkPolicy。
IPIP:把 Pod 包封进另一个 IPv4 包里#
IPIP 是一种 IPv4-in-IPv4 封装方式。
它的思路是:原始 Pod 报文不直接暴露给底层网络,而是在外层再包一层节点 IP。
原始包:
PodAIP -> PodBIP
封装后:
NodeAIP -> NodeBIP
内层:PodAIP -> PodBIP这样底层网络只需要知道 Node IP 怎么互通,不需要知道 Pod CIDR 怎么路由。
IPIP 常见于这些场景:
- 底层网络不能学习 Pod 路由。
- 跨三层网段节点之间需要 Pod 互通。
- 只运行 IPv4 的集群。
Calico 里常见的 IPIP 配置不是一定全量封装,也可以使用 CrossSubnet:同一二层网段内不封装,跨子网才封装。
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
name: default-ipv4-ippool
spec:
cidr: 192.168.0.0/16
ipipMode: CrossSubnet
vxlanMode: Never
natOutgoing: true排查时可以看:
kubectl get ippools.crd.projectcalico.org -o yaml
ip tunnel show
ip route
tcpdump -ni any proto 4IPIP 的代价是额外封装开销,并且主要适用于 IPv4。
VXLAN:用 UDP 封装二层语义#
VXLAN 也是 overlay,但它使用 UDP 封装,默认常见端口是 4789。
链路可以理解为:
PodAIP -> PodBIP
↓
封装成 NodeAIP -> NodeBIP 的 UDP/VXLAN 包
↓
底层网络只负责 Node IP 间转发
↓
目标 Node 解封装后送到 Pod B和 BGP 相比,VXLAN 对底层网络要求更低,不要求网络设备学习 Pod 路由。
和 IPIP 相比,VXLAN 更常见于云环境、跨三层网络或不方便运行 BGP 的环境。
典型 IPPool 配置:
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
name: default-ipv4-ippool
spec:
cidr: 192.168.0.0/16
ipipMode: Never
vxlanMode: CrossSubnet
natOutgoing: true排查命令:
kubectl get ippools.crd.projectcalico.org -o yaml
ip link show type vxlan
bridge fdb show
tcpdump -ni any udp port 4789如果节点安全组、防火墙或云网络 ACL 禁止 VXLAN 端口,跨节点 Pod 通信就可能失败。
eBPF 数据面:把更多转发逻辑放到内核钩子里#
Calico 还提供 eBPF 数据面。
传统 Calico 数据面常依赖 Linux 路由表、iptables、ipset 等机制。eBPF 数据面则把一部分策略、转发和 Service 处理逻辑放到 eBPF 程序里执行。
可以粗略理解为:
传统数据面:
包进入节点
↓
Linux 路由 / iptables / conntrack
↓
转发或丢弃
eBPF 数据面:
包进入节点
↓
eBPF 程序在内核路径上快速决策
↓
转发、NAT、策略判断或丢弃它的价值主要在于:
- 减少大量 iptables 规则带来的复杂度。
- 在大规模 Service 和 NetworkPolicy 场景下改善性能和可观察性。
- 可以提供更高效的 Service 处理能力。
- 支持一些高级能力,例如 Direct Server Return、源 IP 保留等能力,具体要看部署配置。
但 eBPF 不是无条件开启的银弹。它对内核版本、发行版能力、Calico 版本和 kube-proxy 部署方式都有要求。生产环境开启前,应该严格按官方文档检查前置条件。
常见检查方向:
kubectl get felixconfigurations.crd.projectcalico.org default -o yaml
kubectl -n calico-system get pods -o wide
bpftool prog show
bpftool map show如果使用 Calico eBPF 来处理 Service,通常还要关注 kube-proxy 是否仍在运行,以及集群是否按官方建议完成迁移。
几种模式的选择#
先选跨节点传输方式,再独立选择节点数据面:
| 决策维度 | 选项 | 典型场景 |
|---|---|---|
| 路由和传输 | BGP + 原生三层路由 | 裸金属、私有机房、可控网络 |
| 路由和传输 | IPIP | IPv4 环境、底层不承载 Pod 路由 |
| 路由和传输 | VXLAN | 云环境、不方便跑 BGP 的环境 |
| 节点数据面 | eBPF | 大规模策略、Service 加速、性能优化;需核对内核与 Calico 前提 |
一个比较实用的选择思路:
底层网络能稳定承载 Pod 路由,并且团队能维护 BGP:
优先考虑 BGP。
底层网络不能或不愿承载 Pod 路由:
优先考虑 VXLAN。
已有集群使用 IPIP,且运行稳定:
不必为了“新”而贸然迁移。
需要大规模策略或 Service 性能优化:
在上述路由/封装方案之外,评估 eBPF 数据面,但要先做兼容性验证。常见误区#
误区一:Calico 负责所有 Kubernetes 网络问题#
Calico 负责 CNI、Pod 网络和网络策略,但 Service VIP、DNS 解析、Ingress 七层路由并不全由 Calico 负责。
排查时不要一看到网络问题就只看 Calico。
误区二:用了 overlay 就一定更安全#
IPIP 和 VXLAN 是封装,不等于加密。
如果需要传输加密,要额外评估 WireGuard、IPsec、服务网格 mTLS 或应用层 TLS 等方案。
误区三:BGP 一定比 VXLAN 好#
BGP 开销低,但它要求底层网络配合。VXLAN 开销略高,但部署边界更清晰。
好坏取决于环境,不取决于名字。
误区四:eBPF 开了就不用理解网络#
eBPF 改变的是实现路径,不改变网络基本问题。
仍然要理解 Pod IP、节点路由、Service、NetworkPolicy、conntrack、MTU 等概念。
一套排查顺序#
跨节点 Pod 不通时,可以按这个顺序:
# 1. 确认 Pod 分布和 IP
kubectl get pod -A -o wide
# 2. 确认 Calico Pod 状态
kubectl -n calico-system get pod -o wide
kubectl -n kube-system get pod -o wide | grep calico
# 3. 看 IPPool 模式
kubectl get ippools.crd.projectcalico.org -o yaml
# 4. 如果是 BGP,看邻居
calicoctl node status
# 5. 如果是 overlay,看封装接口和抓包
ip tunnel show
ip link show type vxlan
tcpdump -ni any proto 4
tcpdump -ni any udp port 4789
# 6. 看策略是否拦截
kubectl get networkpolicy -A
kubectl get globalnetworkpolicy.crd.projectcalico.org从现象上也可以快速分流:
| 现象 | 优先怀疑 |
|---|---|
| 同节点 Pod 通,跨节点 Pod 不通 | BGP、IPIP、VXLAN、节点防火墙、MTU |
| Pod IP 通,Service 不通 | kube-proxy、EndpointSlice、Service 配置 |
| DNS 名称不通,但 ClusterIP 通 | CoreDNS 或 DNS 策略 |
| 某些命名空间或标签组合不通 | NetworkPolicy |
| 大包失败,小包正常 | MTU、封装开销 |
总结#
Calico 的流量走向可以先抓住一句话:
Calico 负责让 Pod IP 在集群中可达,并在节点上执行网络策略;跨节点时可以选择原生路由、IPIP、VXLAN 或 eBPF 数据面。日常排查时,先判断问题发生在 Pod IP 层、Service 层、DNS 层还是策略层,再决定看 Calico、kube-proxy、CoreDNS 还是应用自身。