容器网络故障排查:跨节点、Service、MTU与DNS案例
容器网络问题最让人头疼的地方,不在于它有多难,而在于它常常摆出一副“配置全都对”的样子来糊弄你——YAML 没问题、镜像能起来、同节点内一切正常,可一旦跨节点、一旦走 Service、一旦碰上大包,故障就如约而至。我在过去几年里处理过的容器网络故障,粗略算下来能归成五六类,每一类都有它固定的“作案手法”和固定的排查路径。这篇就把这几个典型案例拆开讲,从现象、判断依据、定位手法一直讲到修复动作和回归验证,尽量把每一步“为什么这么做”也交代清楚。
内容偏向实战,适合已经在跑容器集群、被跨节点不通、Service 访问失败、MTU 玄学超时、DNS 解析卡顿这些问题折腾过的同学;如果你刚接触容器网络,也可以把里面的排查顺序当成一张地图,遇到问题时按图索骥,至少不会一上来就乱抓包。文中出现的环境一律用泛称,集群编排平台、CNI 插件、服务代理组件这些,你按自己实际用的那套对号入座即可。
1. 排查之前先想清楚:这个包到底走在哪一层
1.1 一上来就 tcpdump 为什么通常是浪费时间
我见过太多人(包括早期的我自己)遇到容器网络不通,第一反应就是在源 Pod 里敲tcpdump -i eth0,然后盯着满屏的重传和 RST 发呆。抓包本身没错,错在顺序。容器网络是一条由至少五段组成的链路:Pod 内的 veth 一端、节点上的网桥或路由、隧道封装(如果是 overlay)、对端节点的解封装与转发、对端 Pod 的 veth。你在源端抓包,只能看到“包发出去了”,看不到它在中间哪一段被丢掉。
更麻烦的是,很多故障根本不是丢包,而是包被改写、被拒绝、被转到错误的目的地。比如服务转发规则把流量 DNAT 到了一个已经不存在的后端地址,源端抓包会显示 SYN 发出、没有回应,看起来像“网络不通”,实际上包早就被送到了错误的地方。这时候你在源端抓一万次包也没用。
所以我现在的习惯是:先用侵入性最低的手段把故障范围压缩到一个网段或一台节点,再决定去哪抓包。所谓侵入性低,指的是不改配置、不重启组件、不影响业务,纯读取类的操作。这个顺序后面会反复用到。
1.2 把封包路径拆成四段,逐段对账
我的做法是把整条链路拆成四段,逐段确认“包进得去、出得来”:
| 段位 | 关注点 | 常用验证手段 |
|---|---|---|
| 第一段:Pod 内部 | 容器网卡地址、默认路由、DNS 配置 | ip addr、ip route、cat /etc/resolv.conf |
| 第二段:节点侧 | veth 对、网桥、节点路由表、转发开关 | ip link、brctl show、ip route、sysctl |
| 第三段:节点间 | 隧道设备、底层物理网络、节点防火墙 | ip -d link show、traceroute、对端节点抓包 |
| 第四段:服务转发 | 服务代理规则、连接跟踪表、后端健康状态 | 规则链计数、连接跟踪查询、后端列表 |
这四段里,第一段和第四段出问题的概率最高,第三段次之,第二段最少但一旦出问题最隐蔽。你可能注意到我没把“集群 DNS 组件”单独列一段,因为 DNS 问题本质是第四段访问服务的一个特例,但它的表现形式太有辨识度,值得单独拎出来讲。
提示:判断问题落在哪一段,最快的方法是做“同节点 vs 跨节点”和“直连 Pod IP vs 走服务地址”两组对照。两组对照一做完,范围基本就锁死了。
1.3 工具清单:从只读观察到主动探测
我把常用手段按侵入性从低到高排了个序,遇到线上问题时严格按这个顺序往上走,能不跨级就不跨级:
- 只读观察:查看网卡、路由、规则链计数、连接跟踪表、内核转发参数。这些操作不改变任何状态,随时可做。
- 被动抓包:在 Pod 或节点上抓包,只监听不注入。注意抓包本身会消耗 CPU,在流量大的节点上要加过滤条件。
- 主动探测:从 Pod 内往外 ping、curl、dig,从节点往 Pod 内探测。会引入新流量,可能干扰现场。
- 主动注入:进入容器网络命名空间执行命令、手动加规则、改 MTU。这一步开始有风险,务必先记录原始状态。
- 重启组件:最后手段,只在确认是组件状态异常且无法热修复时使用。
这套顺序的价值在于:大部分故障在“只读观察”阶段就能定位,真正需要动配置的比例并不高。下面几个案例基本都是靠前两步解决的。
2. 跨节点 Pod 互不通:顺着路由表反推封包路径
2.1 现象描述:同节点通、跨节点不通
第一个案例是特别经典的一类。某个业务做了灰度发布,新版本的两个副本被调度到不同节点,结果服务一上线就报连接超时。运维上去ping了一下,同一节点上的副本之间能通,跨节点的两个 Pod 完全不通,连 ICMP 都没回。
这种“同节点通、跨节点不通”的形态,基本可以排除 Pod 内部配置问题(因为同一份镜像、同一套配置在别的节点上是好的),范围直接收缩到节点侧和节点间这两段。接下来要做的是确认 CNI 插件是否真的把每个 Pod 的地址段路由下发到了所有节点。
2.2 先对账:路由表里到底有没有对方的地址段
我在两个节点上分别执行:
ip route show预期看到的是每个 Pod 网段都有一条指向本节点隧道设备或者对端节点地址的路由。实际输出里,节点 A 只有自己负责的那些网段的路由,节点 B 的网段压根没出现。这就是问题所在——包从 Pod 出来到了节点 A,节点 A 一查路由,没有到节点 B 网段的路由,只能走默认路由甩给网关,网关当然不知道容器网段在哪,包就这么没了。
继续往下查,为什么路由没下发。这里有个容易被忽略的点:CNI 插件通常依赖节点之间的某种“对账机制”来同步路由或者地址池分配,这个机制可能是监听集群里某个资源对象的变化,也可能是周期性扫描。查看对应组件的日志,发现它一直在报连接不上集群 API 的错误,原因是该组件使用的凭证过期了。凭证过期这种事在自动化运维里不算罕见,尤其是证书轮换策略和组件版本不匹配的时候。
修复动作很直接:更新凭证、重启受影响的组件、确认路由重新下发。但我想强调的是验证方式:修复之后不能只看ip route里有那条路由就完事,要从 Pod 内部实际测一次,并且要测双向。我吃过一次亏,单向路由修好了,反方向还是旧的,结果 TCP 三次握手只完成了前两步,表现出来是“能连上但传不了数据”,比完全不通更难查。
2.3 转发链和桥接参数:那个常年被忘记的开关
第二个案例和上面很像,但根因完全不同。现象是跨节点不通,路由表里该有的都有,节点之间ping物理地址也没问题,可 Pod 的包就是过不去。
这时候要往节点侧的第二段深挖。容器网络在节点上通常要经过一座网桥,而包是否从网桥进到主机协议栈、是否需要经过主机防火墙规则,由一组内核参数控制:
sysctl net.bridge.bridge-nf-call-iptables sysctl net.bridge.bridge-nf-call-ip6tables sysctl net.ipv4.ip_forward这三个值正常应该是 1、1、1。那次排查里,ip_forward是 0。为什么?因为这台节点之前跑过别的容器运行时,那个运行时在初始化时改过这些参数,后来容器编排组件接管时没有重新校正,参数就一直是错的。表现出来就是“包到了节点,节点不转发”。
还有一类更隐蔽的问题来自转发链的默认策略。某些容器运行时在启动时会把主机上的转发链默认策略设成丢弃,如果 CNI 插件没有把自己的规则插到前面,或者插入顺序被后来的规则覆盖了,跨节点的包就会在转发环节被静默丢弃。这类问题的特征是:iptables -L FORWARD -v -n里能看到某条规则的丢包计数一直在涨。
注意:修改这些内核参数是全局生效的,会同时影响主机上所有容器网络。改之前一定先记下原始值,改完确认业务正常后再决定是否写进持久化配置,否则重启后会打回原形。
2.4 一个容易被误判的“不通”:单向可达
还有一种情况特别容易误判成“完全不通”。现象是从 A 侧主动连 B 侧超时,但 B 侧主动连 A 侧是好的。很多人一看到单向就怀疑是路由不对称,实际上更常见的原因是连接跟踪表里残留了半开连接,或者某一侧的会话超时时间设置得很短。
我的处理办法是先确认基础连通性:从 A 的 Pod 里往 B 的 Pod 地址发 ICMP,再从 B 往 A 发。两个方向都通,说明三层没问题,问题在四层以上;只有一个方向通,那才是路由或过滤规则的问题。如果两个方向都不通但同节点通,回到 2.2 和 2.3 去查。
判断依据一定要落在“能不能收到回应”上,而不是“命令有没有报错”。ping超时和ping被拒绝是两回事:超时说明包出去了没回来,被拒绝说明有设备明确告诉你“不许过”。这两者在排查方向上是相反的。
3. 服务地址能连却握手失败:转发链路上的三处高频断点
3.1 “能 ping 通”这件事到底证明了什么
先澄清一个常见误解。很多人排查服务访问问题,第一步是ping一下服务地址,通了就觉得链路没问题。这个动作在容器网络里的参考价值非常有限。
服务地址本质上是一个虚拟地址,它的转发靠的是节点上的规则链。ICMP 报文会不会被这些规则改写、会不会被转发到后端,完全取决于实现方式和具体规则。有些实现下 ICMP 根本不参与转发,ping直接返回不可达;有些实现下能通,但通的是节点自己。所以“能 ping 通”既不能证明后端健康,也不能证明转发规则正确。真正有意义的测试是建立一条 TCP 连接,比如用nc -zv或者带超时控制的curl。
3.2 规则链要顺着数据流方向读,不是从上往下背
服务转发的规则分布在几个不同的链里,分别对应包进入节点、路由决策、发出节点三个阶段。我见过不少同学对着规则列表从头看到尾,看半天也看不出所以然。正确的读法是顺着一条包的生命周期走:
- 包从 Pod 网卡出来,先经过进入阶段的规则链,这里通常会做目的地址判断,命中服务地址就改写目的地址为某个后端。
- 改写之后进入路由决策,此时目的地址已经是后端 Pod 地址,路由表决定从哪张网卡出去。
- 出节点前经过发出阶段的规则链,这里可能会做源地址伪装,把 Pod 地址换成节点地址。
三处任何一处出问题,表现都是“连不上”,但排查手法完全不同。第一处出问题,规则计数不增长;第二处出问题,包被送到了错误的网卡;第三处出问题,包出去了但回不来。
具体怎么确认?我会先看规则的命中计数:
iptables -t nat -L -v -n | grep -A 2 <服务网段>计数不涨,说明包压根没走到这条规则,可能是服务地址不对、可能是包根本没离开 Pod、也可能是前面的规则把它拦了。计数涨了但连接还是失败,往后端和回程方向查。
3.3 连接跟踪表:后端换了,旧连接还认老地址
这是我在生产环境遇到过的最隐蔽的一类问题,值得单独说。
现象是:某个服务平时好好的,滚动更新之后开始间歇性超时,大概十分之一的请求会卡住几十秒然后失败。查后端列表,所有后端都是健康的;查规则,规则也是对的;抓包看,SYN 包发出去了,但没有回应。
根因在连接跟踪表。服务转发在有状态的情况下会记录每条连接的转换关系,同一条连接后续的包直接按记录走,不再查规则。后端实例被重建之后地址变了,但连接跟踪表里还留着指向旧地址的记录。新连接如果五元组恰好和旧记录撞上(在高并发短连接的场景下并不是小概率事件),就会被送到一个已经不存在的地址上,自然是超时。
确认方法很直接:
conntrack -L | grep <旧后端地址>如果能看到大量指向旧地址的记录,基本就实锤了。处理方式是清理这些记录:
conntrack -D -d <旧后端地址>治本的做法是调整连接跟踪的超时参数,把已建立连接的空闲超时从默认的几天缩短到业务能接受的量级,同时在服务滚动更新流程里加一步主动清理。不过要提醒一句,缩短超时时间会增加连接重建的频率,对长连接业务可能有副作用,这个参数得结合业务形态来定,不能照抄。
顺带说一个相关现象:连接跟踪表满。表现是新连接直接被丢弃,日志里能看到表满的提示。排查时看当前条目数和上限的比值,接近上限就要考虑调大上限或者缩短超时。这个问题在高并发短连接的场景下特别容易撞上。
3.4 负载均衡模式下后端权重的“隐形故障”
如果服务转发用的是负载均衡模式而不是纯规则模式,还有一类问题:后端条目存在、状态显示健康,但流量就是不往它上面分。
这种模式下每个后端都有一个权重值,权重为 0 意味着不接收新连接。有些组件在健康检查失败时会临时把权重降到 0,恢复后不一定能自动调回来,特别是有过短暂网络抖动的节点。确认方法是列出当前的转发条目,看每个后端的权重和连接数:
ipvsadm -Ln如果某个后端的连接数长期是 0 而其他后端都在涨,基本可以确定它被摘掉了。手工把权重调回去能临时恢复,但要查清楚为什么会被摘——是健康检查探测地址配错了,还是探测频率太高导致误判,还是节点负载过高响应慢。
提示:负载均衡模式下服务地址通常挂在节点的一张虚拟网卡上,这张网卡的存在本身不代表转发正常。判断转发是否正常,看的是后端条目和连接分布,不是网卡在不在。
4. 小包秒回、大包卡死:MTU 算不对账的典型表现
4.1 症状画像:为什么偏偏是握手和上传出问题
这类故障的表现非常有辨识度,认过一次就忘不掉:ping通、telnet端口通、小请求也通,但一旦做 TLS 握手、上传文件、返回大 JSON,就会卡住几十秒然后超时。日志里通常看不到明确错误,只有客户端侧的“连接超时”或者“读取响应超时”。
原因是路径上某一段的最大传输单元小于实际发送的包大小,而路径上的设备又不允许分片。小包不受影响,大包要么被丢弃,要么在设置了“不分片”标志时直接返回一个“包太大”的 ICMP 消息。如果这个 ICMP 消息被中间的防火墙拦掉了,发送端就永远收不到反馈,只能等超时重传,表现出来就是“卡住”。
容器网络里这个问题的发生率比传统物理网络高得多,因为 overlay 方案要在原始包外面再套一层封装,封装头会吃掉一部分可用空间。
4.2 把 MTU 的账算清楚
以最常见的隧道封装为例,外层要加以太头、IP 头、UDP 头和隧道头,加起来大约 50 字节。物理网卡如果是标准的 1500,那么隧道内部能承载的最大就是 1450。如果容器的网卡还按 1500 配置,容器发出的 1500 字节包加上封装头之后就是 1550 字节,超过物理网卡的承载能力,必然出问题。
把几种常见方案的开销列一下:
| 封装方式 | 额外开销(字节) | 1500 物理网卡下建议的容器网卡值 |
|---|---|---|
| 无封装,纯路由 | 0 | 1500 |
| IP-in-IP | 20 | 1480 |
| 隧道封装(UDP 承载) | 50 | 1450 |
| 加密隧道 | 50 到 80 不等 | 1420 到 1450 |
这个账一定要算,而且要注意是整条路径上最小的那个值。如果两个节点之间的物理链路中间还过了一层云厂商的网络,云厂商那层可能自己就只支持 1450 或者更低,那你容器里设 1450 也不够。
4.3 定位手法:不分片探测一路往上试
定位思路很简单:发一个设置了“不分片”标志的包,逐步加大包体,找到发不出去的那个临界值。
ping -M do -s 1400 <对端地址> ping -M do -s 1420 <对端地址> ping -M do -s 1450 <对端地址>-s参数指的是数据部分长度,加上 28 字节的 ICMP 和 IP 头才是实际包大小。如果 1400 能通、1420 不通,说明路径的实际承载能力在两者之间。注意这个探测要从容器内部发起,不是从节点上发起,因为容器网卡的 MTU 是独立配置的。
还有一种情况是节点之间通、容器之间不通,那就说明瓶颈在封装这一层。这时候在节点上探测是通的,在容器里探测是不通的,这个对比结果本身就是结论。
对于 TCP 业务,还有一种更贴近真实的验证方式:用curl请求一个返回大响应的地址,加上详细输出,看它在哪个阶段卡住。如果是在接收响应体的时候卡住,基本可以确定是 MTU 问题。
4.4 改 MTU 的落点和它的连锁反应
改 MTU 有三个落点:物理网卡、隧道设备、容器网卡。三者必须形成递减关系,物理网卡最大,隧道设备减去封装开销,容器网卡等于或略小于隧道设备。只改其中一个基本没用。
修改容器网卡的 MTU 通常要在 CNI 插件的配置里改,改完之后新建的 Pod 才生效,已有 Pod 需要重建。这一点很关键,我见过有人改完配置发现没效果,以为改错了,其实是老 Pod 还在用旧值。
还有几个副作用要提前想到:
- MTU 调小会增加包的数量,在吞吐敏感的场景下会带来额外开销,通常 1450 相比 1500 的性能损失在可接受范围内,但调到 1300 以下就要评估了。
- 有些中间设备会做包重组,MTU 太小反而触发异常行为。
- 数据库、消息队列这类长连接服务对 MTU 变化比较敏感,调整窗口要避开业务高峰。
提示:MTU 问题的排查结论一定要落到“具体数值”上,不要停在“可能是 MTU 问题”。算出路径实际承载能力,记录在案,下次换节点、换机房可以直接复用。
5. 解析卡住五秒钟:DNS 配置里被忽略的放大效应
5.1 那个固定五秒是怎么来的
容器里访问一个外部域名,前面几次请求都要卡五秒左右才成功,之后就正常了。这个“五秒”太有标志性了,几乎可以直接指向 DNS 配置。
容器内的解析配置文件通常包含搜索域列表和若干选项,其中有一个超时时间参数,默认值就是五秒。当解析一个不在搜索域内的名字时,解析器会依次尝试把搜索域拼到名字后面去查,每查一次失败就要等一轮超时。搜索域有几个,就可能等几个五秒。
先看配置文件:
cat /etc/resolv.conf典型输出里会有search后面跟三四个域,以及options ndots:5。这个ndots是问题的核心。
5.2 ndots 的乘法效应:为什么外部域名特别慢
ndots的含义是:如果一个域名里的点数量少于这个值,就先按“相对名字”处理,依次拼接搜索域去查,全部失败之后才按“绝对名字”去查。
集群里常见的配置是ndots:5。而一个普通的外部域名比如api.example.com,点只有两个,小于 5,于是解析器会先做五次拼接查询:
api.example.com.集群域1api.example.com.集群域2api.example.com.集群域3- ……
这五次查询绝大部分返回“不存在”,每次都要走一轮解析流程。如果集群 DNS 组件本身响应就慢,或者上游转发有问题,这五次查询的时间累加起来就是好几秒。而集群内部的服务名比如db.default.svc.cluster.local点足够多,一次就命中,所以表现得“内部服务很快,外部服务很慢”。
这里还有个放大器:如果集群 DNS 组件对不存在的域名不做负缓存,那么每次请求外部域名都要把这五次查询重走一遍,永远等不到缓存加速。
5.3 三种收敛方案和各自的代价
针对这个问题,我实践下来有三条路,各有取舍:
第一条:调小 ndots。把ndots从 5 调到 2 或者 1,外部域名点数量够就直接走绝对解析,内部短名还是能拼搜索域。代价是内部短名解析可能变慢或者行为变化,需要确认业务里有没有依赖多级搜索域的相对写法。这是通用性最好的方案,但改动影响面是全集群的。
第二条:业务侧用绝对域名。在配置文件里给域名末尾加上点,比如写成api.example.com.,解析器看到末尾的点就直接按绝对名字查,跳过所有搜索域拼接。这个方案零风险,但需要业务方配合改配置,而且有些框架或者客户端库对末尾点的处理不一致,得逐一验证。
第三条:本地缓存。在节点或者 Pod 侧加一层解析缓存,把第一次的慢查询成本摊薄。这个方案见效快,但引入了额外组件,缓存过期策略和一致性要额外考虑,而且掩盖了根因。
我一般的做法是:先确认业务方的域名写法能不能统一改成带点的绝对形式(成本最低),不行再推动调小ndots,缓存作为兜底手段。
注意:调整
ndots之前一定要统计一下集群内有多少服务在用短名互相访问。这个统计可以从审计日志或者访问日志里捞,别拍脑袋决定。
6. 策略都放开了还是不通:两层过滤叠加的悬案
6.1 一个“两边配置都正确”的故障
有个案例让我印象很深。某服务连不上数据库,查了服务端策略,允许来自该命名空间的所有流量;查了客户端策略,允许访问目标端口;两边的选择器也都对得上。可就是不通。
这类“配置都对但就是不通”的问题,本质是有两层过滤在同时生效,而你只查了其中一层。容器网络里常见的两层是:集群层面的网络策略,和节点层面的主机防火墙规则。前者管 Pod 之间的访问,后者管节点进出流量。当流量走的是节点网络而不是纯粹的 overlay 转发时,两层都会拦。
还有一个容易忽略的第三层:云环境或者虚拟化平台自身的安全组。这一层在集群内部完全看不见,但从节点出去的包会被它检查。
6.2 用二分法把范围压到一个方向
遇到这种多层过滤的悬案,我的做法是二分。具体来说:
第一步,在客户端 Pod 里直接连目标 Pod 的地址,不经过服务地址。通,说明问题在服务转发层;不通,说明在网络策略或更底层。
第二步,如果直连不通,从客户端所在的节点上连目标 Pod 地址。通,说明问题在 Pod 到节点的这一段,通常是 Pod 侧的出向策略;不通,说明问题在节点到节点或者目标侧。
第三步,从目标 Pod 反向连客户端 Pod。如果反向通而正向不通,说明是单向策略的问题,重点查源地址方向。
这三步做完,范围基本能压到一个具体方向。我上面那个案例,第二步就从“节点直连目标 Pod 通”这一条线索定位到了客户端 Pod 的出向策略——策略里配的选择器匹配的是 Pod 标签,而那个 Pod 的标签在最近一次发版时被改了,选择器没匹配上,策略实际生效的是“默认拒绝”。
6.3 验证策略是否真的生效的三个动作
光看配置文件不够,因为策略从被创建到真正下发到节点是需要时间的,而且下发失败不一定有明显的报错。我一般做三个验证动作:
- 看策略对象的状态:有些实现会在策略对象上标注下发状态或者时间戳,确认它确实被处理过。
- 看节点上的规则:策略最终会变成节点上的过滤规则,直接去看规则里有没有对应的条目,比看配置可靠。
- 做一次反向验证:临时加一条明确允许的规则,看是否立刻恢复。如果加了允许规则还是不通,说明问题根本不在策略层,别再在这上面耗时间。
第三个动作很关键,它能帮你及时止损。我见过有人在策略层折腾了大半天,最后发现是目标端口压根没在监听。
7. 把这些经验沉淀成一张随手可查的对照表
7.1 我的分层检查顺序
排查做过几十次之后,我把它固化成了一张表,遇到问题按顺序过一遍,大部分情况在三步之内就能定位:
| 顺序 | 检查项 | 快速命令 | 异常特征 |
|---|---|---|---|
| 1 | Pod 内地址和路由 | ip addr、ip route | 没有默认路由、地址不在预期网段 |
| 2 | 同节点连通性 | 直接连同节点另一个 Pod | 同节点也不通,问题在 Pod 或节点侧 |
| 3 | 跨节点连通性 | 连另一个节点的 Pod | 只有跨节点不通,看路由和转发 |
| 4 | 服务地址直连后端 | 绕过服务地址连 Pod | 直连通、走服务不通,看转发规则 |
| 5 | 不分片探测 | ping -M do -s | 小包通大包不通,看 MTU |
| 6 | 解析耗时 | dig带计时 | 固定几秒,看搜索域和 ndots |
| 7 | 连接跟踪 | 查目标地址的记录 | 大量指向旧地址,清理 |
这张表的价值不在于命令本身,而在于顺序。它把侵入性最低、信息量最大的检查放在前面,避免一上来就动配置。
7.2 几个长期存在的隐患
最后分享几个我在多套环境里反复见到的隐患,它们不一定马上引发故障,但会在某个时间点集中爆发:
第一个是节点内核参数的漂移。同一批机器,因为上线时间不同、跑过的组件不同,转发开关、连接跟踪上限、端口范围这些参数可能各不相同。平时没事,一旦某个 Pod 被调度到“参数不一样”的那台机器上,就会出现“同样的镜像,换个节点就不行”。我的做法是把这个参数集合做成开机自检脚本,节点启动时统一校正并在不一致时告警。
第二个是地址池的碎片化。节点反复上下线之后,地址段的分配会变得零散,路由条目越来越多。到某个临界点,路由表的查找性能会下降,表现为网络延迟整体升高。定期做一次地址整理,把空闲的段回收,能避免这个问题。
第三个是抓包工具的滥用。抓包在生产节点上是很重的操作,一次全量抓包可能把节点 CPU 打满,把一个小故障变成一个大故障。我现在的习惯是抓包必须带过滤条件、必须限制包数量、必须设超时自动停止:
timeout 30 tcpdump -i any -c 2000 -w /tmp/cap.pcap 'host 10.0.0.5 and tcp port 8080'-c限制包数、timeout限制时长、过滤条件缩小范围,这三件事缺一不可。
第四个是变更和故障的时间相关性。我处理过的故障里,超过一半在发生前两小时内有配置变更、组件升级或者节点扩缩容。所以排查的第一步应该是问一句“最近动过什么”,而不是直接扎进技术细节。这个习惯帮我省下的时间比任何工具都多。
我个人在实际操作中的体会是,容器网络问题的排查能力,七成来自对链路结构的清晰认知,三成来自工具熟练度。知道自己发的包会经过哪几道关卡,比会背一百条命令有用得多。真要给个建议,那就是每次解决完一个问题,都把当时的判断依据和验证步骤记下来,攒到十几个案例之后,你会发现新问题基本都是旧问题的变体,处理起来会快很多。