Cilium 里为什么删不掉这条记录?cilium-dbg bpf ipcache delete 三步安全清理指南
【免费下载链接】ciliumeBPF-based Networking, Security, and Observability项目地址: https://gitcode.com/GitHub_Trending/ci/cilium
上周值班遇到一个怪现象:某节点上的 Pod 换了新 IP 后,跨集群流量开始莫名丢包。顺着日志查下来,问题出在 Cilium 的 BPF IPCache——数据面靠它把每个 IP 解析成安全身份并决定隧道封装,而旧 IP 回收后残留的那条映射一直没被清掉,新流量的身份判定和封装决策全都跟着跑偏。正常情况下这块缓存由 Agent 自动维护,但状态一旦异常,就得亲手下场。这篇文章带你用cilium-dbg bpf ipcache delete把 BPF IPCache 条目删干净,顺便讲清楚参数怎么配、删之前查什么、删不掉时怎么排障。
这条命令到底是干什么的
一句话定位:它直接从内核里的 BPF map 中删掉一条“IP/CIDR 前缀 → 身份 + 隧道端点”的记录,是清理 IP 身份映射的最低层手段。删掉之后,这个前缀在数据面上就查不到身份了,策略判定和封装决策会立刻按“未知”处理,所以动手前想清楚影响面。
最小可用示例就一条命令:
cilium-dbg bpf ipcache delete 10.244.3.110/32 --clusterid 0执行成功后会看到这样的输出,其中@0表示条目所属的 clusterid:
Deleted entry 10.244.3.110/32@0参数怎么写才对
位置参数只有一个:要删的前缀。必须是带前缀长度的 CIDR,裸 IP 不认。下面这组对照可以贴在工位上:
| 合法写法 | 非法写法(为什么不行) |
|---|---|
10.244.3.110/32 | 10.244.3.110(缺前缀长度,报 Invalid prefix address) |
fd00::a0/128 | 10.244.3.110/33(前缀位数越界) |
192.168.0.0/24 | 空参数(报 No prefix provided) |
专属选项其实只有两个:--clusterid(uint16,默认 0)和-h。--clusterid决定什么时候该传:单集群场景缺省即可;一旦条目来自 ClusterMesh 远端集群,写入时带了非 0 的 clusterid,删除时必须原样带上。传错的后果不是“删错了别的”,而是构造出来的键和 map 里那条对不上,命令报条目不存在(ENOENT),什么也没删掉。其余像--config、-D/--debug、-H/--host这些全局选项从根命令继承而来,标准安装下用不到,知道即可。
删除前必做的三步检查
⚠️ 先把安全原则放前面:先查后删,一次只碰一条。ipcache 命令族里三个只读兄弟命令,各回答一个问题:
list(别名ls):map 里总共有哪些条目?——用来确认真实键的格式和 clusterid 后缀长什么样;match <PREFIX>:这个前缀精确存在吗?——按键做精确匹配,删之前先跑它,能直接排除“键没写对”的嫌疑;get <IP>:这个 IP 实际会命中哪个身份?——按最长前缀匹配(LPM:按前缀长度做最长匹配的一种查找),回答的是数据面真实的行为。
“查→删→验”的完整序列长这样:
# 1) 确认目标键真实存在(注意看输出里的 @clusterid) cilium-dbg bpf ipcache match 10.244.3.110/32 # 2) 顺带确认该 IP 当前解析到的身份 cilium-dbg bpf ipcache get 10.244.3.110 # 3) 执行删除 cilium-dbg bpf ipcache delete 10.244.3.110/32 # 4) 验证:此时应提示 no match / does not match cilium-dbg bpf ipcache match 10.244.3.110/32组合演练:update 写入 → 删除的四步法
排障时最常见的场景是和update搭配,临时纠正或重建一条映射。update支持--tunnelendpoint、--identity、--encryptkey、--skiptunnel、--clusterid五个参数。完整走一遍:
# 1) 写入:10.244.3.110/32 归属 identity 6,隧道端点 172.21.0.2 cilium-dbg bpf ipcache update 10.244.3.110/32 \ --tunnelendpoint 172.21.0.2 --identity 6 --encryptkey 255 --clusterid 0 # 2) 确认写入 cilium-dbg bpf ipcache list | grep 10.244.3.110 # 3) 删除 cilium-dbg bpf ipcache delete 10.244.3.110/32 --clusterid 0 # 4) 验证删除 cilium-dbg bpf ipcache match 10.244.3.110/32两个写法差异顺手记一下:多集群(ClusterMesh)场景下,写入和删除必须用同一个 clusterid,上面第 1 步和第 3 步的--clusterid要一致;IPv6 前缀则不需要任何额外参数,地址族由键自动识别,直接delete fd00::a0/128即可。
底层机制速览:为什么删除参数必须和写入时一致
先解释两个名词:LPM Trie 是按前缀长度做最长匹配的一种内核查找结构,Cilium 的 IPCache map(常量名cilium_ipcache_v2,容量上限 512000 条)正是这种类型。map 的键由“前缀 + clusterid”共同编码,地址族(IPv4/IPv6)由前缀自动识别后写入键中;值侧则装着身份号、隧道端点、IPsec 密钥编号和若干标志位(如 skiptunnel、remotecluster)。
delete 的执行流程其实很短:校验 root 权限,解析前缀,用NewKey(prefix, clusterID)组装键,再对这个 map 单例执行Delete,成功打印Deleted entry ...,失败报错并以退出码 1 结束。所以“参数必须与写入一致”的原因就一句话:键是确定性编码的,前缀或 clusterid 任何一位不同,你拿到的就是一把指向空槽位的钥匙——LPM Trie 的删除是精确删键,不会级联影响更宽或更窄的前缀,删 /32 不会动 /24 的条目。
避坑清单
你可能会遇到下面这四种情况,对号入座:
| 现象/报错 | 原因 | 处理 |
|---|---|---|
Error deleting entry ...: no such file or directory(ENOENT) | 键没命中:前缀拼错、clusterid 与写入时不一致 | 先list看真实键格式(注意@clusterid后缀),再照抄重删 |
Invalid prefix address. | 参数不是合法 CIDR,裸 IP 或前缀位数越界 | 补上/32、/128等前缀长度 |
No prefix provided. | 没传位置参数 | 把前缀作为第一个参数 |
| 权限不足、命令直接拒绝 | 未以 root 在 Agent 节点执行(源码里有强制校验) | 用sudo或切 root 重试 |
收尾:排障检查清单
✅ 下次再遇到 IPCache 状态异常,按这张清单过一遍就能收工:
- 已在 Agent 节点以 root 身份执行命令
- 用
list/match确认了条目的存在、格式与@clusterid后缀 - 删除参数(前缀、clusterid)与写入时完全一致
- 删除后已用
match/get复核,并观察了数据面转发是否恢复 - 明确告知团队:手动改动只是止血,根因要回到 Agent 的自动维护链路去查
源码入口就两处,想深挖时直接看:命令实现在 cilium-dbg/cmd/bpf_ipcache_delete.go,键/值结构与 map 定义在 pkg/maps/ipcache/ipcache.go。
【免费下载链接】ciliumeBPF-based Networking, Security, and Observability项目地址: https://gitcode.com/GitHub_Trending/ci/cilium
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考