目前社区存在一个 ovn nb 操作死锁的问题,原因在上游的 libovsdb,上游也提交了一个 PR,可能可以修复,但是已经快两年没有更新该 PR 了,所以导致该问题依旧存在
1. libovsdb 问题分析
这个提交使用客户端的 Echo 方法发送不活动探测,因为它可以作为一个有时间限制的调用,这样 rpc读锁 就不会被无限期地持有。这将使当前的 ovsdb leader 意外消失时立即断开连接(这发生在非常罕见的情况下,在这种情况下,end echo 方法仅在 12 分钟后返回意外的 EOF 错误),并与新的 ovsdb leader 连接。
但是实际上,我们遇到的情况已经锁了半小时以上。
2. kube-ovn 社区问题分析
3. kube-ovn 对 libovsdb 的使用
ovn nb db client 和 sb db client 都是用了该方法
现在的超时时间默认是 10 s
4. 分析
这个问题看 libovsdb 的 PR,分两个部分:
- grpc 的 http/2 tcp 的 keepalived 的 timeout 机制( 2018 年就合入的 PR),猜测关系不大。
- libovsdb 自己的 rpc client 的读锁,猜测是唯一的问题点
目前 libovsdb 使用的是 2024 年 11 月的版本
4.1 查看 libovsdb 所使用的 grpc 版本以及对 timeout 配置
github.com/cenkalti/rp… 这个项目从init 起, go mod 就没变过
目前认为这个项目和 GRPC 无关,PR 中有提到应该只是参考,这里只有单独的 json RPC的实现,可能是像参考 GRPC 实现类似的 TCP 的 timeout 机制,如果没有实现的话,可能会在 tcp 层面出现连接 keepalived 已断,但仍被上层应用使用的情况。
但是,无论 TCP 有没有问题,你一个应用层一个动作执行了那么久,自己加一个 timeout 机制也应该有的,ovs-vsctl --timout 命令行工具都具备的东西,不可能在这里不做。
而且这个 kube-ovn 社区的 libovsdb 已经修复了
4.1 查看 rpc client 的锁机制
分析这些锁哪个位置没有使用 ctx timeout 机制,或者存在 goroutine 锁泄漏的风险
root@debian:~/g/libovsdb main ✔
▶ grep -n rpcMutex -r * | grep -v -i unlock | grep -i lock
client/client.go:244: o.rpcMutex.Lock()
client/client.go:537: o.rpcMutex.Lock()
client/client.go:570: o.rpcMutex.RLock()
client/client.go:580: o.rpcMutex.RLock()
client/client.go:586: o.rpcMutex.RLock()
client/client.go:788: o.rpcMutex.RLock()
client/client.go:802: o.rpcMutex.RLock()
client/client.go:867: o.rpcMutex.Lock()
client/client.go:921: o.rpcMutex.RLock()
client/client.go:1078: o.rpcMutex.RLock()
client/client.go:1146: o.rpcMutex.Lock()
client/client.go:1201: o.rpcMutex.RLock()
client/client.go:1279: o.rpcMutex.Lock()
client/client.go:1366: o.rpcMutex.Lock()
client/client.go:1375: o.rpcMutex.Lock()
5. ovn nb sb db Transact() 都有设置 timeout 时间
但是,问题就是这个配置,在 libovsdb rpc client 层面,因为 rpc client lock 死锁的问题,导致这个 timeout 根本没有用(生效)