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。