Cilium IPCache 条目删除指南:用 cilium-dbg bpf ipcache delete 精准清掉 BPF 身份映射
【免费下载链接】ciliumeBPF-based Networking, Security, and Observability项目地址: https://gitcode.com/GitHub_Trending/ci/cilium
在 Cilium 里,每个 IP/CIDR 前缀都对应一个安全身份,这个映射存放在内核的 BPF mapcilium_ipcache_v2中。当某条映射被写错、残留或需要在排障时临时纠正,cilium-dbg bpf ipcache delete就是你用来精确删除单条 IPCache 条目的命令。下面用白话把它的语法、参数、底层原理和常见坑一次讲清楚。
什么时候你会用到这条命令
先说清楚 IPCache 是干嘛的:Cilium 数据平面每处理一个包,都要靠 IPCache 完成"这个 IP 是谁(身份)、要不要走隧道、隧道端点在哪"的决策。正常情况下它由 Agent 自动维护,但你可能会遇到这些场景:
- 怀疑某个身份映射被写错或残留,想手动清掉一条验证效果;
- 在 ClusterMesh 多集群环境里,远端集群同步来的条目带了非 0 的 clusterid,需要按同样的键去删;
- 做测试或演练时,配合
update手动造条目、再删掉,走一遍完整的增删流程。
记住一点:它是个"外科手术"式的低级运维命令,直接改内核 BPF map,正常生产环境不建议随手执行。
一条命令删除 IPCache 条目
最常用的写法就一行:
cilium-dbg bpf ipcache delete 10.244.3.110/32这是在删除本集群(clusterid 缺省为 0)下10.244.3.110/32这条前缀。执行成功后你会看到:
Deleted entry 10.244.3.110/32@0末尾的@0是 clusterid,说明删除的键是"前缀 + 集群 0"。如果条目不存在,命令会向 stderr 输出Error deleting entry ...: no such file or directory并以退出码 1 结束——看到 ENOENT 别慌,多半是前缀或 clusterid 对不上。
几个前置条件:
- 必须在运行 Cilium Agent 的节点上执行,且用root权限(源码里有
common.RequireRootPrivilege强校验,非 root 直接被拒); - 位置参数必须是带前缀长度的 CIDR,比如
10.244.3.110/32、fd00::a0/128。传裸 IP(如10.244.3.110)会被netip.ParsePrefix拒绝,报Invalid prefix address.。
参数怎么填
这条命令的参数很少,正好按场景揉在一起讲:
- 位置参数(唯一且必填):要删的 IP/CIDR 前缀,只认一个。IPv4、IPv6 都支持,地址族会自动识别,不用额外传参。
--clusterid(uint16,默认 0):多集群场景的关键。条目写入时带了哪个 clusterid,删除时就必须传哪个,否则构造出的键和 map 里的键不一致,删除会失败:
# 删除来自远端集群 1 的条目,clusterid 必须与写入时一致 cilium-dbg bpf ipcache delete 10.244.3.110/32 --clusterid 1- 继承自 cilium-dbg 根命令的通用选项:
-H/--host(Agent API 地址)、-D/--debug(调试日志)、--config(配置文件,默认$HOME/.cilium.yaml)、--log-driver/--log-opt(日志后端与格式)。排障时加-D看更多细节会方便不少。
完整参数清单可以直接看官方生成的命令参考:Documentation/cmdref/cilium-dbg_bpf_ipcache_delete.md。
它到底改了哪个映射,按什么键定位
用一段话讲透底层:
- 命令先校验 root 和参数,再用
netip.ParsePrefix把 CIDR 解析成前缀; - 通过
ipcache.NewKey(prefix, clusterID)构造 BPF 键——前缀长度、clusterid、地址族、IP 地址一起编码进去; - 调用 map 单例
ipcache.IPCacheMap(nil)对这个键执行 Delete; - 成功则打印
Deleted entry 前缀@clusterid。
这张 map 在内核侧是LPM Trie类型(cilium_ipcache_v2,容量上限 51.2 万条),键结构定义在 pkg/maps/ipcache/ipcache.go 的Key结构里(Prefixlen+ClusterID+Family+ 16 字节 IP 字段),与 BPF 侧bpf/lib/eps.h中的struct ipcache_key严格保持同步。LPM Trie 的删除语义是精确删键:删10.244.3.110/32不会影响同网段的/24等其他前缀条目,它们在 map 里是各自独立的键,不存在"删宽前缀连累窄前缀"的路由表式级联行为。
那删掉一条会影响什么?值里存的是安全身份、隧道端点、IPsec 加密密钥编号和若干标志位(skip tunnel、IPv6 隧道端点等)。条目消失后,这个前缀的包在数据路径上就查不到身份和隧道端点——策略判定会按未知/无身份处理,封装决策也随之改变。所以动手前务必确认后果,这也是它只适合排障、测试的原因。命令的实现本体在 cilium-dbg/cmd/bpf_ipcache_delete.go,想逐行对照读源码非常方便。
配合 update 做一次完整的增删演练
最典型的实战就是"先查、再增、后删"。update支持--tunnelendpoint、--identity、--encryptkey、--skiptunnel、--clusterid参数(见 cilium-dbg/cmd/bpf_ipcache_update.go):
# 1) 写入一条映射:前缀归属 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看输出时重点确认:第 2 步能 grep 到条目,第 4 步查不到,说明一轮增删闭环成功。顺带认识三个"查询三兄弟":list列出全部条目(别名ls);match按前缀做精确匹配;get传一个 IP 则做最长前缀匹配,模拟内核 LPM 查找的命中结果。
避坑速查
| 现象 | 可能原因 / 处理 |
|---|---|
Error deleting entry ...: no such file or directory(ENOENT) | 键没命中:前缀拼错或--clusterid与写入时不一致。先list看真实键格式再删 |
Invalid prefix address. | 参数不是合法 CIDR。必须带前缀长度,如/32、/128,裸 IP 不行 |
No prefix provided. | 忘传位置参数了 |
| 提示权限不足 | 非 root 执行,用sudo或在 root 会话里跑 |
| 删了但流量行为没变化 | 正常——条目本就不存在,或该前缀另有其他宽前缀条目在命中,用get <IP>验证实际命中的是哪一个 |
一句话收束
- 语法极简:
cilium-dbg bpf ipcache delete <PREFIX> [--clusterid N],位置参数必须是带前缀长度的 CIDR; - 删除按"前缀 + clusterid"精确构造键定位,LPM Trie 只删这一个键,不级联影响其他前缀;
- 老规矩先查后删:
list/match/get三件套确认目标真实存在; - 必须 root、必须在 Agent 节点上执行;它直接改动数据路径的身份与隧道封装决策,只用于排障和测试;
- 想读实现,看 cilium-dbg/cmd/bpf_ipcache_delete.go;想读键值结构,看 pkg/maps/ipcache/ipcache.go。
【免费下载链接】ciliumeBPF-based Networking, Security, and Observability项目地址: https://gitcode.com/GitHub_Trending/ci/cilium
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考