当前位置: 首页 > news >正文

ftrace calico netns问题8 - 小镇

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 pairhost:cali71340cd83eacontainer: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)
doecho ==== $ireadlink /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/tracingecho > kprobe_eventsecho 'p:waitref netdev_wait_allrefs' > kprobe_eventsecho 1 > events/kprobes/waitref/enableecho 1 > options/stacktraceecho 1 > tracing_oncat 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。