CoreOS:tcpdump 神秘解决网络问题(使用过多的套接字)

Ste*_*ein 14 tcpdump linux-networking linux-kernel coreos azure-networking

我今天有一个谜团要告诉你。我们在 Azure 上运行一个基于 CoreOS (2023.5.0 / Linux 4.19.25-coreos) 的小型三节点 Elasticsearch 集群。Elasticsearch 在主机网络模式下的 docker 容器内运行。在几乎完全免维护运行一年多之后,我们看到机器进入了一种非常有趣的状态。

更新

此问题已通过修复Linux 内核中的驱动程序解决。请参阅下面的答案。

症状

基本上,受影响的机器和其他两个节点之间的网络连接失效。它们都在同一个虚拟网络和同一个子网中,通常可以与其他人通信。仍然可以从其他子网(我可以通过 ssh 进入)和不同的对等虚拟网络访问受影响的节点。这台机器也有(非常不稳定的)互联网连接,但大多数请求只是超时。

我们观察到,在受影响的节点上,报告的“使用的套接字”数量/proc/net/sockstat非常高(大约 4.5k 而不是健康节点上的大约 300)。监控显示,这个数字从节点变得不可用的那一刻起迅速上升。

有趣的是,我们似乎无法识别这些使用过的套接字的来源:

# cat /proc/net/sockstat
sockets: used 4566
TCP: inuse 2 orphan 0 tw 2 alloc 98 mem 4
UDP: inuse 1 mem 0
UDPLITE: inuse 0
RAW: inuse 0
FRAG: inuse 0 memory 0

# cat /proc/net/sockstat6
TCP6: inuse 98
UDP6: inuse 1
UDPLITE6: inuse 0
RAW6: inuse 1
FRAG6: inuse 0 memory 0
Run Code Online (Sandbox Code Playgroud)

除此之外,机器看起来还不错。没有可疑进程在运行,CPU 使用率最低,可用内存充足。

在同一子网导致一些查验的“无法访问” VMEAGAIN反应,recvmsg然后再跨越到获得ENOBUFS从后面sendmsgstrace ping 输出在这里

我收集了一些额外的输出(在对系统进行任何修改之前)并将其发布在此要点中:https : //gist.github.com/privatwolke/e7e2e7eb0272787765f5d3726f37107c

分析

我们已经尝试关闭服务器上我们能想到的所有内容,其中第一个怀疑是 elasticsearch。但是关闭 elasticsearch 容器不会释放使用的套接字。所有 CoreOS 相关进程(更新引擎、locksmithd 等)甚至整个 Docker 运行时或 Azure 特定的东西都是一样的。似乎没有任何帮助。

但现在它变得更奇怪了:我们试图tcpdump在机器上运行以查看发生了什么。看哪:问题自行解决,连接恢复。我们的理论是 tcpdump 会执行某种系统调用来解决它。我们使用 gdb 运行 tcpdump 并在所有系统调用上设置断点。在单步执行大量断点之后,我们终于发现在捕获套接字上设置混杂模式的行为(特别是 libpcap 中的这一行)是重置套接字使用计数器并将我们返回到正常状态的事情。

其他发现

  • 我们已经验证,tcpdump使用该-p/--no-promiscuous-mode标志运行不会清除已使用的套接字计数器并将机器返回到可用状态。
  • 运行会ifconfig eth0 txqueuelen 1001重置已使用套接字计数器,但不会恢复连接。
  • 手动设置 promisc 模式ip link set eth0 promisc on也不会恢复连接。
    • net.ipv4.xfrm4_gc_thresh 设置为 32768 并且稍微增加它并不能解决问题。

使用的插座

我们一直与 Azure 保持联系,他们和我们一样对此感到困惑。我知道这可能不是问题,而只是一个症状。但这是迄今为止我发现的唯一有形的东西。我希望通过了解症状,我可以更接近根本原因。Azure 上的网络接口使用此网络驱动程序运行。

也许 CoreOS/Kernel 是罪魁祸首?

从时间线来看,问题始于 2019 年 3 月 11 日,也就是 CoreOS 自动更新到最新版本的那一天。根据发行说明,此更新包含4.15.23 到 4.19.25内核更新。我仍在浏览变更日志,看看那里是否有任何问题。到目前为止,我只发现 hyperv 网络驱动程序在最近几个月收到了相当多的更新,并非所有更新似乎都是 4.19.25 的一部分。CoreOS 应用到 4.19.25 的补丁集并没有那么令人印象深刻,但是引入假 nf_conntrack_ipv4 模块的补丁是新的。

更新:可能相关的传入内核补丁?

帮助!

到目前为止,我们的问题如下:

  • 什么会导致这个“使用的套接字”指标猛增?我已经阅读了这个指标的内核源代码,它似乎只是一个计数器,没有提到它们实际上是什么类型的套接字或创建它们的原因。

  • 为什么数字在 4.5k 左右持平?哪个限制会导致这种情况?

  • 内核 4.14.96 和 4.19.25 之间有什么重大变化吗?

  • 为什么setsockopt()libpcap中的调用会重置状态?

相关 CoreOS 错误:https : //github.com/coreos/bugs/issues/2572

Ste*_*ein 0

这是由 Linux 内核中的 hv_netsvc 驱动程序中的错误引起的。我们可以与 Microsoft 开发人员一起解决此问题,并设法在上游应用修复程序。

我将在这里引用提交消息,因为它很好地总结了问题:

当环形缓冲区由于 RX 完成消息而几乎满时,TX 数据包可能达到“低水位线”并导致队列停止。如果 TX 完成早于队列停止到达,则可能会错过唤醒。

此补丁将对最后一个待处理数据包的检查移至涵盖 EAGAIN 和成功情况,因此队列将在必要时可靠地唤醒。

为了供将来参考,修复此问题的提交是https://github.com/torvalds/linux/commit/6d9cfab853ca60b2f77b5e4c40443216988cba1f