ftrace calico netns问题8

你这个输出非常关键,可以先排除一类问题。

结论:CNI IPAM cache 目前看没有明显泄漏

你的 /var/lib/cni/networks/k8s-pod-network/ 内容:

172.18.105.198 -> containerID
...
172.18.105.239 -> 02ede461f000...
last_reserved_ip.0 -> 172.18.105.239

这是典型的 host-local CNI IPAM 状态文件

格式:

IP文件名
    |
    +---- containerID

例如:

172.18.105.239
        |
        +---- 02ede461f00035d...

然后你验证:

docker ps -a | grep 02ede461f

得到:

02ede461f000 k8s_POD_zfzhaobiao...

说明:

IP 172.18.105.239
        |
        |
pause sandbox
        |
        |
pod zfzhaobiao-middleware-extractor

仍然存在。

所以:

不是 CNI IPAM cache 残留导致。


现在问题范围进一步缩小

当前链路:

Pod
 |
 |
pause sandbox
 |
 |
CNI ADD
 |
 |
创建:
   veth pair

host:
   cali71340cd83ea

container:
   eth0

 |
 |
CNI DEL
 |
 |
删除 cali veth
 |
 |
kernel unregister_netdevice()
 |
 |
Usage count = 1

卡在最后一步。


为什么重启 calico 不解决?

因为:

calico-node 负责:

  • Felix

  • route

  • iptables

  • BGP

但是:

veth 生命周期属于:

kubelet
 |
dockershim
 |
CNI
 |
kernel net_device

不是 calico-node container。

你重启:

k8s_calico-node

不会清掉:

struct net_device

引用。


下一步需要确认:哪个接口卡住

现在不要继续看 CNI cache。

执行:

1. 找所有 cali

ip link show | grep cali

记录数量。


2. 对比 CNI IP

例如:

你的:

172.18.105.239

对应:

cali71340cd83ea

查:

ip neigh | grep 172.18.105.239

得到:

172.18.105.239 dev cali71340cd83ea

然后:

ip link show cali71340cd83ea

3. 看接口 namespace

执行:

for i in $(ls /sys/class/net | grep cali)
do
    echo ==== $i
    readlink /sys/class/net/$i
done

正常:

/devices/virtual/net/caliXXXX

异常:

可能存在:

deleted

或者大量孤儿。


判断 GC vs kernel bug 的最终方法

现在做一个实验。

找一个确定已经不存在 pod 的 cali。

例如:

kubectl get pod -A -o wide | grep spider50

如果:

pod列表没有:

172.18.xxx.xxx

但是:

ip link

还有:

caliXXXX

那么:

GC问题

概率高。


但是如果:

pod存在:

例如:

172.18.105.239

对应:

zfzhaobiao-middleware-extractor

并且:

kernel不断:

unregister_netdevice waiting

那么:

kernel refcount问题

概率高。


你现在最关键的证据

之前:

trace:

unregister_netdevice_many

调用者:

rtnetlink_rcv
netlink_sendmsg

说明:

删除请求来源:

用户态 netlink

不是 kernel 自动 GC。

而现在:

CNI cache:

正常。

所以剩余:

CNI DEL执行
        |
        |
kernel删除veth
        |
        |
net_device refcount=1

下一步抓最后引用(重点)

你的内核看起来是老版本,ftrace 支持 kprobe。

增加:

cd /sys/kernel/debug/tracing

echo > kprobe_events

echo 'p:waitref netdev_wait_allrefs' > kprobe_events

echo 1 > events/kprobes/waitref/enable

echo 1 > options/stacktrace

echo 1 > tracing_on

cat trace_pipe

如果出现:

netdev_wait_allrefs

调用栈:

例如:

netdev_wait_allrefs
 |
cleanup_net
 |
...

就能知道是谁没有释放。


如果最终确认是 kernel ref leak

临时恢复:

方式1:删除孤儿接口

ip link del caliXXXX

如果立即恢复:

说明 CNI残留。

方式2:重启节点

因为:

struct net_device
refcount

属于 kernel 内存对象。

只有:

net namespace destroy

才能彻底释放。


当前判断概率

根据你所有数据:

问题概率
CNI IP cache泄漏 <10%
sandbox残留 <10%
calico-node异常 20%
CNI DEL触发内核veth释放失败 70%
kernel net_device refcount bug 最高

现在建议你补两个输出:

uname -r

和:

ip link show | grep cali | wc -l

再加:

ip link show cali71340cd83ea

这三个基本可以判断是不是老 kernel veth unregister bug。

posted on 2026-07-27 23:40  小镇-做题家  阅读(2)  评论(0)    收藏  举报

导航