残留 veth 接口如何关联到对应 pod/container 并批量删除

13次阅读

残留veth接口源于Pod强制删除、运行时异常或CNI清理失败,需先通过netns inode或CNI配置定位归属Pod,再安全批量删除,避免盲目操作;预防需保障CNI与运行时兼容并禁用直接kill。

残留 veth 接口如何关联到对应 pod/container 并批量删除

残留的 veth 接口通常是因为 Pod 被强制删除、容器运行时异常退出或 CNI 插件未正确清理导致的。它们不会自动消失,但又无法被 kubectl 或 docker工具直接识别。要批量清理,关键在于:**先定位 veth 属于哪个 Pod(即对应哪个 network Namespace),再安全删除**。

确认 veth 接口归属的 Pod

veth 总是成对出现(一端在宿主机,一端在容器 netns),宿主机侧的 veth 名字形如 vethxxxxxx。可通过以下方式反向查找它所属的 Pod:

  • ip link show 查出所有 veth 设备,例如:
    ip -o link show | awk -F': ' '/veth[0-9a-f]{6}/ {print $2}'
  • 对每个 veth,查其对端 netns inode
    readlink /sys/class/net/vethabc123/device/net/*/name 2>/dev/null | grep -o '/proc/[0-9]+/fd/[0-9]+' | xargs -I{} ls -l {} 2>/dev/NULL | grep -o 'net:[0-9]+'
    (更稳的方式是:cat /sys/class/net/vethabc123/ifindex,然后查 /proc/*/task/*/fd/ 下指向该 ifindex 的 netns)
  • 更实用的方法:遍历所有容器的网络命名空间,比对 veth 的 ifindex。
    例如使用 crictl(对接 containerd):
    crictl ps -a --quiet | xargs -I{} crictl inspect {} | jq -r '.info.runtimeSpec.linux.namespaces[] | select(.type=="network") | .path' 2>/dev/null
    拿到 netns 路径后,用 ls -l /proc/*/fd/* 2>/dev/null | grep "net:" 匹配 inode,再关联到具体容器 ID。

通过 CNI 配置和 Pod UID 关联 veth

多数 CNI(如 bridge、calico、cilium)会在创建 veth 时将 Pod UID 写入接口名或 sysfs 属性中:

  • 检查 /sys/class/net/vethxxxxx/device/ 下是否有 pod_uidpod_name 等字段(部分 CNI 会写)
  • 查看 CNI 日志:journalctl -u kubelet | grep -i "cni.*add|del" | grep veth,找最近的 add 操作及对应 Pod 名
  • 检查 /var/lib/cni/networks// 下的 IP 分配文件(如 10.244.1.10 对应的 last_reserved_ip.0),里面常存有容器 ID 或 Pod UID

批量识别并安全删除残留 veth

不建议盲目删所有 veth。推荐脚本化清理逻辑:

  • 列出当前所有 veth:ip -br link show | awk '$1 ~ /^veth/ && $2 == "DOWN" {print $1}'
  • 对每个 veth,检查是否属于任一活跃容器的 netns:
    for v in $(...); do ns=$(find /proc/*/task/*/fd -lname "net:[0-9]*" 2>/dev/null -exec readlink {} ; 2>/dev/null | grep -o 'net:[0-9]+' | sort -u | while read n; do ip netns identify "$n" 2>/dev/null; done | grep "$v" | head -1); [ -z "$ns" ] && echo "$v"; done
    (说明:若没找到任何 netns 引用该 veth,则极可能是残留)
  • 确认无引用后,批量删除:
    ip link delete vethxxxxx
  • 额外清理:检查 /var/run/netns/ 是否有残留 netns 文件,用 ip netns del xxx 清理

预防后续残留

根源在 CNI 和容器运行时协作:

  • 确保 kubelet 使用的 CNI 插件版本与集群兼容(如 calico v3.25+ 对 containerd 1.7+ 更健壮)
  • 避免直接 kill 容器进程;优先用 kubectl delete podcrictl stop
  • 定期运行清理脚本(可封装为 CronJob),例如每小时扫描并记录无主 veth
  • 启用 CNI 的 sync 模式(如 calico-node 的 FELIX_SYNCROUTES)有助于状态收敛
text=ZqhQzanResources