Hi,欢迎来到 卡瓦邦噶!我是 laixintao,现在生活在新加坡。我的工作是 SRE,喜欢在终端完成大部分工作,对各种技术都感兴趣。我从 2013 年开始写这个博客,写的内容很广泛,运维的方法论,编程的思考,工作的感悟,除了技术内容之外,还会分享一些读书感想,旅行游记,电影和音乐等。欢迎留下你的评论。

声明:本博客内容仅代表本人观点,和我的雇主无关。本博客承诺不含有 AI 生成的内容,所有内容未加说明均为博主原创,一经发布自动进入公有领域,本人放弃所有权利。转载无需本人同意。但是依然建议在转载的时候留下本博客的链接,因为这里的很多内容在发布之后会还会不断地继续更新和追加内容。 Not By AI

网络问题排查的思路和技巧

这一篇计划很久了还没有写,今天终于开始下笔了。

许久无从下笔的原因是,网络问题排查——哦不,应该说不光网络,基本所有的问题排查,都是这样——思路相比于技巧要重要很多。思路,简单来说就是几句话的事情:

  • 依据事实猜测而不是全凭经验猜测;
  • 验证测试,比如使用工具复现,或者实现一个最小化的 case;
  • 提出 fix;
  • 实施 fix;

核心就是一句话,「基于事实猜测」,如果实践起来,却不是那么容易。顺藤摸瓜的正确排查方法是需要大量的基础以及经验支撑的,并不是什么独门秘籍,可以让人瞬间开悟的东西。

但还是有一些规律可以遵循。

一般的问题定位,第一步是明确问题。很多人表达问题不清楚的,与这种人沟通很容易就陷入了 X Y 问题1。所以无比问清楚:现在问题是什么,网络从哪里到哪里不通,预期的结果是什么。在非常复杂的网络环境下,需要收集必要的信息,比如有没有 overlay,有没有一些特殊的配置。可能问题的报告者也说不清,大部分情况需要自己收集信息。

第二步就是复现问题。如果问题没有办法复现,就很难解决。如果可以复现,基本就解决了 90% 了。我自己最怕的问题也是无法复现的问题,比如高流量的偶尔延迟高,复现的现象定义不明确,复现条件也不明确。有一些工具可以使用,比如 iperf,scapy,或者自己写一些程序2来复现。有人遇到问题直接去查有没有变更,去看监控,这就像无头苍蝇。从根本解决问题,第一步一定是复现,最后一步对应的,是确定之前复现的场景下问题已经解决了。当然了,如果是线上的故障,立即查找变更和监控是正确的,应该需要在不明确根因的情况下能够恢复故障的手段。

第三步就很简单了,根据现象,做合理的假设,测试,逐步排除错误的假设,剩下的就是正确的答案。

时间长了,每个人都会积累一些技巧。比如,在最近的上一篇博客中使用到的,找一个正常的机器,进行比较一下。积累也是一个比较重要的过程,我喜欢把有意思的 case 都记录下载,对我很有帮助。

我发现厉害的人(偶尔,我自己也是),在看相同的信息的时候可以得到更多的结论。比如看到同样一个网络问题,使用同样的工具查看,别人说是网络不通,高手通过 curl -v 看发现是网络可以连接,而服务器没有返回内容。就把问题进一步定位到了 7 层问题,可能是 LB,WAF,application 的问题,但不会是路由或者 TCP 的问题。再比如,看到同样一个 MTR,高手可以分析出来默认网关有没有问题,出机房有没有问题,是单设备的问题还是某一跳的问题。

这是一种很酷的能力:能够在有限的环境里面定位到根本问题。

又想起来一个例子,我们经常需要网工给我们配置路由,但是配置好了没有?我们无从得知,因为我们没有交换机的登录权限。遇到问题的时候,低手会直接去麻烦人家,问问这个路由配置好了没,人家说好了,也没有办法验证是不是真的好了。高手在麻烦人家之前必然会提供相应的证据,比如,使用 traceroute,目标为这个网段的任意一个 IP,能不能 ping 通并不重要,重要的是看网工配置的交换机有没有出现在 traceroute 里面。这样报告问题,无法甩锅,解决问题的速度也快。

就写到这里,有很多大道理讲,但是讲起来没有什么说服力。好在日常已经积累了很多问题排查的博客,写具体的例子还是比较有意思。读者可以关注一下我的这类文章。

对了,在 AI 时代,如今大部分问题 AI 如果有权限都可以排查出来了,我们人类排查问题的技能还有用吗?

当然是有的,排查问题,解决问题,再想怎么一劳永逸地解决问题,对最终的质量负责,还是需要人的。如果你把一个系统完全交给 AI,AI 来应对用户的问题和需求,这里面没有了人做 trade off,感觉过不久就会变成非常大的一坨屎吧。

不过这也是现在,说不定多段时间 AI 真的可以完全自主运行系统了。在那之前,我们还是好好享受技术带来的快乐和成就感吧。

  1. https://zh.wikipedia.org/zh-sg/XY%E9%97%AE%E9%A2%98 ↩︎
  2. 现在有了 AI,这样做已经非常方便了 ↩︎
 

一次内存引起的网络丢包问题排查

记录一下最近排查的一个问题:某台机器一上线就有丢包,同 Rack 同规格的其他机器都没有问题,由于负载都是一样的,所以问题集中到这台机器本身的问题。已经可以 100% 复现,只要一接流量,网卡就开始时不时的丢包。

网卡使用率对应丢包,左边蓝色的线是有问题的机器,0% 是下线状态,可见,只要一上线就会丢包

初步检查:网卡的 CRC 正常,光模块正常。(这些一般是丢包的常见问题)

仔细检查网卡的计数器,发现丢包发生在 rx_prio0_buf_discard: 397172。

中间经历了很多错误的排查思路,比如这个 metric 是每一个 NIC 都有一个,但是 driver 的实现应该是用了同一个 metric,因为 2 个 NIC 的数字总是相同的。

以为是 DCB 的 buffer 不够,尝试了调大 DCB 的 buffer。

发现 buffer 大了丢包反而更严重了一些,buffer 调小也是有丢包。应该是和 buffer 无关。

由于是 rx 的丢包,应该是 ingress 的处理能力不足,接下来的排查包括了:

  • 查看 PCIe 的带宽,状态;
  • 调整 Interrupt coalescing,让它处理更快;

……都没有效果。

中间经历了一次大促,容量足够,就暂停排查了,这周又开始继续。

好像和网卡有关的东西检查都是正常的,同事建议换一张网卡试试。换之前我使出了最后的一招:server diff.

server diff 是我排查问题作为没有思路之后的一个手段,可以简化成一段 skill:

这是一个正常的机器,这是一个异常的机器。你对比一下两个机器之间的 sysctl 参数,kernel 参数,硬件规格,看下两台机器有什么不一样的部分。

AI 发现的问题如下:

能找到的差异点(按怀疑程度排)

  1. 硬件/内存健康 IPMI SEL:08/31 16:46 和 16:49 两次 Uncorrectable ECC DIMMB5;mcelog 有 08/31 15:39 一条 Memory read corrected error;随后 08/31、09/02、09/03 连续多次重启。DIMM 全是 Micron 36ASF4G72PZ-3G2J3(.144 是 Samsung M393A4K40DB3-CWE),B5 序列号 2E313345,看不出被换过。 本次启动(09-03)以来 EDAC ce/ue 都是 0,但 Dell 在 UE/CE 后可能进入 ADDDC/lockstep 降级模式, 会拉低内存带宽/延迟。 保留意见:网卡在 NUMA node0(CPU1/A 组),B5 属于 CPU2(B 组),RX ring 页也在 node0, 理论上不直接受影响;但这台机器的内存子系统整体存疑。
  2. …

这是非常可疑的一个点,Linux 的收包链路上,NIC DMA 到内存1,路线是:

PCIe NIC → PCIe Root Port/Root Complex → IOMMU → CPU Mesh/Interconnect → LLC(L3) / Memory Controller → DRAM

内存子系统异常会显著降低 host RX path 的处理和 buffer 回收能力,可能进一步造成 NIC ingress buffer 无法及时 drain,最终表现为 rx_prio0_buf_discard。

于是我下线机器之后测试内存的带宽,我们使用的服务器有 2 个 CPU,2 个 NUMA node,于是分别测试。

测试使用 stream.c 2结果如下:

(CPU 2 和 3 分别在 NUMA node 0 和 1)

可以看到,node 1 的内存,无论是同 NUMA node local 读写还是跨 NUMA remote 读写,速度只有区区 700MB,性能只有 node 0 的 1/17,确定 node 1 的内存有问题了。

进一步验证,由于我们使用的 NIC 是双网口 bond,port 1 的中断绑定到 node 0 的 CPU,port 2 的中断都绑定到 node 1 的 CPU,(这样提高 CPU 的利用率,又提供稳定的转发延迟)。所以可以通过关闭 port 2 来关闭 node 1 的使用,验证只有 node 1 的内存有问题。

关闭一个网卡之后上线,再也没有发现有丢包。

由于是单卡模式上线,机器分到的流量不变,所以这台机器的网卡使用率是其他机器的2倍,但是丢包是0.
  1. 见服务器高性能网络调优 ↩︎
  2. source code: https://www.cs.virginia.edu/stream/FTP/Code/stream.c ↩︎
 

BPG 连接建立失败问题的答案和解析

本文是 BPG 连接建立失败问题 一文的答案和解析。

抓包文件中有两处可疑的地方。

第一处是 BGP OPEN 消息建立的过程,我可以直接 follow 这个 tcp stream:

Open 消息

可以看出:

  • Server 是可以正常和对端设备建立 TCP 连接的,所以 4 层以下的网络没有问题;
  • 在 TCP 连接建立之后,一旦发送 OPEN 消息,直接收到了 TCP RST,意味着对面的设备拒绝和我们建立 BGP 连接;
  • 我们收到的 RST 包,IP 层的 TTL 是 1,这个也很可疑。

另一处可疑的地方是,对面的设备一直再对我们发送 keepalive 的消息:

从对面发给我们的 keepalive 消息

综上可以推断:我们的 Server 和对面的设备已经存在一个 BGP 会话了,而且 Server 上建立 BGP 会话使用的 port 是 22709,根据这个 port,我们可以找出来是哪一个进程。

后来我们发现,机器上有一个 bird 进程,使用 EBGP (这也就是为什么发过来的 keepalive 包的 TTL 都是 1 的原因)与对面的设备建立连接。由于连接已经建立好了,所以我们的进程如果使用 IBGP 再尝试建立连接的话就会被直接拒绝。

为什么一次升级会触发这个问题呢?

因为之前我们的 IGBP 会话是正常的,bird 尝试的 EBGP 反而是一直失败的,在我们重启过一次之后,EBGP 会话成功建立了,我们的 IGBP 就一直失败。

(还好只是一个无关紧要的环境,上面部署的东西太乱了。)

 

BGP 连接建立失败问题

好久没有更新「抓包破案」系列了,最近遇到的一个 case 适合拿出来考一考读者,需要一点点的 BGP 前置知识,嘿嘿。

事情是这样:在一次日常升级中,服务器原本可以与一个网络设备建立 BGP 连接,但是升级之后无法建立了。

服务器升级操作执行的内容有:

  • 更新程序;
  • 重启;

理论上应该可以重新连接对端 IP 的 179 端口,然后恢复服务。但是升级之后一直没有流量进来,排查发现是 BGP 异常。为什么重启之后,原本好好的 BGP 就异常了呢?

我们进行了抓包,文件如下:

看了半天也没有看出所以然来,于是在终端启动了一个 AI Agent,让它分析这个文件。

第一轮,agent 也没有分析出来问题。因为调用的工具失败了。

我告诉它不应该用 wireshark 这种 GUI,对你来说最好的工具应该是 tshark。

Agent 开始使用 tshark 分析,不到一分钟,就准确地告诉了我答案,令人震惊!

回到这个问题,我发现即使不使用 AI,也是完全可以破案的,这里就把问题交给读者,看看能否发现异常的本质。