一次抓包排除网络故障

相关背景:

从一个k8s集群请求另一台cvm上的服务,请求成功,但是在同一个VPC内的另一个k8s集群上面,请求cvm上的服务失败…


cls-ao1g0oz4 这个k8s集群访问集群外node服务不通

from POD: ip 10.8.0.210 host IP: 172.22.0.47
to host: 172.22.0.55:8421

在 Kubernetes (k8s) 使用 kubectl get pods -o wide 命令时,它会返回集群中 Pod 的详细信息。其中显示的两个 IP 地址通常指的是:

  1. Pod IP (10.8.0.210): 这是分配给 Pod 的内部 IP 地址。在 Kubernetes 集群内部,其他 Pod 可以使用这个 IP 地址来访问此 Pod。这个 IP 地址是在 Kubernetes 集群的内部网络空间中唯一的,通常由集群的网络插件(如 Calico、Flannel、Weave 等)管理和分配。

  2. Node IP (172.22.0.47): 这是承载该 Pod 的物理机(Node)的 IP 地址。这个地址是 Node 在物理网络中的地址,可以用于从集群外部访问 Node 上的服务(根据您的网络和安全配置)。Node IP 是连接 Kubernetes 集群中的 Node 和外部网络的桥梁。

在这个上下文中,10.8.0.210 是 Pod 自己的 IP 地址,用于集群内部通信,而 172.22.0.47 是承载这个 Pod 的物理服务器(Node)的 IP 地址,用于外部通信或者从集群外部访问集群内部资源(取决于你的网络策略和设置)。




小问题1: 应该在哪台机器上面抓包? testnet集群,还是bigdata机器?


我在一个搭建k8s集群的其中一台node节点上(ip为172.22.0.47),访问同一个VPC下面的另一台虚拟机是可以的,telnet 172.22.0.55 8421 能通.

但是到pod里面(ip为10.8.0.210), telnet 172.22.0.55 8421 就不通了. 我现在想通过tcpdump抓包排查问题,需要如何操作?

我感觉chatgpt的办法好像不太对。 按我理解,应该是去cvm上面,也就是bigdata这台机器上抓包吧

要使用tcpdump抓包排查问题,你可以分别在节点上和Pod内部执行抓包操作。这样可以帮助你确定问题是出在节点还是Pod的网络配置上。下面是如何在两个地方使用tcpdump的指导。

在节点上抓包

  1. 找出Pod使用的网络接口:首先,你需要确定Pod通信经过的网络接口。通常,Kubernetes集群使用特定的网络接口或网桥(如cni0flannel.1等)用于Pod之间的通信。你可以通过查看节点的网络接口列表来猜测哪个是用于Pod网络的接口。

    1
    ip addr
  2. 在节点上运行tcpdump:一旦你确定了Pod通信所使用的网络接口,就可以在该接口上运行tcpdump来捕获流量。例如,如果你认为cni0是Pod网络接口,可以使用以下命令:

    1
    sudo tcpdump -i cni0 -nn port 8421

    这个命令会捕获通过接口cni0上端口8421的所有TCP流量。-nn选项防止tcpdump尝试解析主机名和端口名。

在Pod内部抓包

由于Pod内部可能没有安装tcpdump,你可能需要使用一个带有tcpdump的调试容器,或者在现有的Pod中安装tcpdump(如果你的容器镜像支持)。

  1. 进入Pod:使用kubectl exec进入Pod内部。

    1
    kubectl exec -it <pod-name> -- /bin/sh
  2. 安装tcpdump(如果需要):这取决于你的容器基础镜像。对于基于Debian或Ubuntu的镜像,你可以运行:

    1
    apt-get update && apt-get install -y tcpdump
  3. 运行tcpdump:在Pod内部运行tcpdump抓包。由于Pod通常使用虚拟的以太网接口(如eth0),你可以在这个接口上运行tcpdump:

    1
    tcpdump -i eth0 -nn port 8421

分析结果

  • 如果在节点上能看到到172.22.0.55端口8421的流量,但是在Pod内部看不到,这可能表明问题出在Pod网络和节点网络之间的路由或防

上面这样做可以吗?



目标cvm ip route show ;route -n 帮忙执行看下

tun0的那个网卡 和集群网段重叠,需要cvm 改网段

cvm上装了docker,那个段跟这个集群的POD IP cidr cover 了

在 Linux 系统中,route -n 命令显示的是内核的 IP 路由表,这对于了解和管理系统如何将网络流量从一个网络接口转发到另一个网络接口非常有用。路由表的每一行都代表了一条路由规则,说明了数据包如何根据其目的地被转发。对于你提到的两行:

  1. 10.8.0.0 10.8.0.2 255.255.255.0 UG 0 0 0 tun0
  2. 10.8.0.2 0.0.0.0 255.255.255.255 UH 0 0 0 tun0

解释

  • 目的地 (Destination): 这是目标网络或主机的 IP 地址。对于第一行,10.8.0.0 是目的网络的地址,对于第二行,10.8.0.2 是一个具体的目的主机地址。
  • 网关 (Gateway): 如果数据包需要通过另一个设备(网关)来达到目的地,这里会显示那个设备的 IP 地址。10.8.0.2 作为网关意味着到达 10.8.0.0/24 网络的流量将被转发到这个地址。0.0.0.0 表示路由直接指向连接的网络,不需要通过网关。
  • 子网掩码 (Genmask): 定义了目的地地址的网络部分和主机部分。255.255.255.0 表示前 24 位是网络地址,最后 8 位是主机地址。255.255.255.255 表示目标是一个单一主机。
  • 标志 (Flags): 提供路由选项和路径的状态。
    • U(Up): 表示路由是活动的。
    • G(Gateway): 表示数据包将被发送至一个中间网关;路由需要通过一个网关。
    • H(Host): 表示目的地是一个主机,而不是一个网络。

特定路由解释

  • 对于 10.8.0.0/24 网络的流量,系统将其转发到网关 10.8.0.2,这里使用了 UG 标志,表示这是一条需要通过网关的活动路由。
  • 第二行指的是到特定主机 10.8.0.2 的路由,这里


route -n命令显示的输出中,你看到的是内核IP路由表的内容。这个路由表用于决定如何将数据包从你的系统路由到其他网络或系统。下面是对你提到的条目的解释:

路由表条目解释

  • 10.8.0.0 10.8.0.2 255.255.255.0 UG 0 0 0 tun0

    • Destination(目的网段): 10.8.0.0 表示这条路由规则适用于前往10.8.0.0/24网络段的数据包。
    • Gateway(网关): 10.8.0.2 是达到目的网段的下一跳地址。数据包会首先发送到这个地址。
    • Genmask(子网掩码): 255.255.255.0 定义了网络段的大小,/24 表示前24位是网络部分,剩下的是主机部分。
    • Flags: UG标志的含义如下。
    • Iface(接口): tun0 是这条路由规则使用的网络接口,通常用于VPN连接。
  • 10.8.0.2 0.0.0.0 255.255.255.255 UH 0 0 0 tun0

    • Destination(目的地址): 10.8.0.2 这条规则是特别针对单个IP地址的,表示所有前往这个具体IP地址的数据包。
    • Gateway(网关): 0.0.0.0 表示这是一个直接路由,数据包直接通过接口发送,没有中间跳。
    • Genmask(子网掩码): 255.255.255.255 表示这个路由规则只适用于单个IP地址。
    • Flags: UH 标志的含义如下。
    • Iface(接口): tun0 同上,是数据包出去的网络接口。

Flags的含义

  • U(Up): 表示路由是活动的,即接口是启动状态。
  • G(Gateway): 表示为了到达目的网段或主机,数据包将被发送到一个中间网关。
  • H(Host): 表示这个路由规则是针对单个主机的,而不是一个网络或子网。

简而言之,第一条路由规则表示,为了到达10.8.0.0/24网络段,数据包需要通过10.8.0.2网关,使用tun0接口。这通常用于VPN或特定的网络配置,其中10.8.0.2可能是VPN服务器的内部地址。

第二条路由规则特别针对10.8.0.2这个地址,说明所有前往这个地址的数据包都应该直接通过tun0接口发送,而不需要经过其他网关,这是一个直接连接的配置。



这个pod里面,telnet没啥问题~


在bigdata(cvm机器)上tcpdump抓包

同时在pod和node上面分别telnet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
sudo tcpdump -i any -nn port 8421
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked v1), capture size 262144 bytes






15:47:51.868424 IP 10.8.0.210.51164 > 172.22.0.55.8421: Flags [S], seq 53434985, win 65535, options [mss 1424,sackOK,TS val 2515692196 ecr 0,nop,wscale 9], length 0
15:47:51.868487 IP 172.22.0.55.8421 > 10.8.0.210.51164: Flags [S.], seq 2443455773, ack 53434986, win 65160, options [mss 1460,sackOK,TS val 1656624443 ecr 2515692196,nop,wscale 7], length 0
15:47:52.887705 IP 172.22.0.55.8421 > 10.8.0.210.51164: Flags [S.], seq 2443455773, ack 53434986, win 65160, options [mss 1460,sackOK,TS val 1656625462 ecr 2515692196,nop,wscale 7], length 0
15:47:52.889915 IP 10.8.0.210.51164 > 172.22.0.55.8421: Flags [S], seq 53434985, win 65535, options [mss 1424,sackOK,TS val 2515693218 ecr 0,nop,wscale 9], length 0
15:47:52.889956 IP 172.22.0.55.8421 > 10.8.0.210.51164: Flags [S.], seq 2443455773, ack 53434986, win 65160, options [mss 1460,sackOK,TS val 1656625464 ecr 2515692196,nop,wscale 7], length 0
15:47:54.903698 IP 172.22.0.55.8421 > 10.8.0.210.51164: Flags [S.], seq 2443455773, ack 53434986, win 65160, options [mss 1460,sackOK,TS val 1656627478 ecr 2515692196,nop,wscale 7], length 0
15:47:54.905891 IP 10.8.0.210.51164 > 172.22.0.55.8421: Flags [S], seq 53434985, win 65535, options [mss 1424,sackOK,TS val 2515695234 ecr 0,nop,wscale 9], length 0
15:47:54.905925 IP 172.22.0.55.8421 > 10.8.0.210.51164: Flags [S.], seq 2443455773, ack 53434986, win 65160, options [mss 1460,sackOK,TS val 1656627480 ecr 2515692196,nop,wscale 7], length 0
15:47:58.969940 IP 10.8.0.210.51164 > 172.22.0.55.8421: Flags [S], seq 53434985, win 65535, options [mss 1424,sackOK,TS val 2515699298 ecr 0,nop,wscale 9], length 0
15:47:58.969983 IP 172.22.0.55.8421 > 10.8.0.210.51164: Flags [S.], seq 2443455773, ack 53434986, win 65160, options [mss 1460,sackOK,TS val 1656631544 ecr 2515692196,nop,wscale 7], length 0
15:48:03.159698 IP 172.22.0.55.8421 > 10.8.0.210.51164: Flags [S.], seq 2443455773, ack 53434986, win 65160, options [mss 1460,sackOK,TS val 1656635734 ecr 2515692196,nop,wscale 7], length 0
15:48:07.161878 IP 10.8.0.210.51164 > 172.22.0.55.8421: Flags [S], seq 53434985, win 65535, options [mss 1424,sackOK,TS val 2515707490 ecr 0,nop,wscale 9], length 0
15:48:07.161951 IP 172.22.0.55.8421 > 10.8.0.210.51164: Flags [S.], seq 2443455773, ack 53434986, win 65160, options [mss 1460,sackOK,TS val 1656639736 ecr 2515692196,nop,wscale 7], length 0
15:48:15.195701 IP 172.22.0.55.8421 > 10.8.0.210.51164: Flags [S.], seq 2443455773, ack 53434986, win 65160, options [mss 1460,sackOK,TS val 1656647770 ecr 2515692196,nop,wscale 7], length 0
15:48:31.319703 IP 172.22.0.55.8421 > 10.8.0.210.51164: Flags [S.], seq 2443455773, ack 53434986, win 65160, options [mss 1460,sackOK,TS val 1656663894 ecr 2515692196,nop,wscale 7], length 0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
sudo tcpdump -i any -nn port 8421
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked v1), capture size 262144 bytes
15:49:48.290829 IP 172.22.0.47.33986 > 172.22.0.55.8421: Flags [S], seq 268160592, win 65535, options [mss 1424,sackOK,TS val 3516757502 ecr 0,nop,wscale 9], length 0
15:49:48.290892 IP 172.22.0.55.8421 > 172.22.0.47.33986: Flags [S.], seq 1232602973, ack 268160593, win 65160, options [mss 1460,sackOK,TS val 873226446 ecr 3516757502,nop,wscale 7], length 0
15:49:48.291032 IP 172.22.0.47.33986 > 172.22.0.55.8421: Flags [.], ack 1, win 128, options [nop,nop,TS val 3516757502 ecr 873226446], length 0



15:50:03.483693 IP 172.22.0.55.8421 > 172.22.0.47.33986: Flags [.], ack 1, win 510, options [nop,nop,TS val 873241639 ecr 3516757502], length 0
15:50:03.483855 IP 172.22.0.47.33986 > 172.22.0.55.8421: Flags [.], ack 1, win 128, options [nop,nop,TS val 3516772695 ecr 873226446], length 0
15:50:18.583698 IP 172.22.0.55.8421 > 172.22.0.47.33986: Flags [.], ack 1, win 510, options [nop,nop,TS val 873256739 ecr 3516772695], length 0
15:50:18.583835 IP 172.22.0.47.33986 > 172.22.0.55.8421: Flags [.], ack 1, win 128, options [nop,nop,TS val 3516787795 ecr 873226446], length 0
15:50:33.687699 IP 172.22.0.55.8421 > 172.22.0.47.33986: Flags [.], ack 1, win 510, options [nop,nop,TS val 873271843 ecr 3516787795], length 0
15:50:33.687904 IP 172.22.0.47.33986 > 172.22.0.55.8421: Flags [.], ack 1, win 128, options [nop,nop,TS val 3516802899 ecr 873226446], length 0
15:50:48.791688 IP 172.22.0.55.8421 > 172.22.0.47.33986: Flags [.], ack 1, win 510, options [nop,nop,TS val 873286947 ecr 3516802899], length 0
15:50:48.791868 IP 172.22.0.47.33986 > 172.22.0.55.8421: Flags [.], ack 1, win 128, options [nop,nop,TS val 3516818003 ecr 873226446], length 0
15:51:03.895701 IP 172.22.0.55.8421 > 172.22.0.47.33986: Flags [.], ack 1, win 510, options [nop,nop,TS val 873302051 ecr 3516818003], length 0
15:51:03.895879 IP 172.22.0.47.33986 > 172.22.0.55.8421: Flags [.], ack 1, win 128, options [nop,nop,TS val 3516833107 ecr 873226446], length 0

只看到了请求端的包(172.22.0.55,10.8.0.210),没收到回的包(172.22.0.47)

问题在于cvm回包因为本地路由关系送到了tun0(之前在bigdata上搭建过测试用的openvpn),回包的报文被openvpn吸走了



sudo tcpdump -i any -nn port 8421时返回的Flags [S],其中S是什么

S标志位在tcpdump输出的TCP包头 Flags 字段表示SYN包。

TCP三次握手的第一步是客户端发送一个SYN包到服务器,这个包的Flags字段就是S(SYN)。

具体来说:

  • S - SYN包,表示建立连接的请求。客户端在三次握手的第一步发送。

  • A - ACK包,确认包。三次握手第二步和第三步,以及后续的数据包确认号都是ACK。

  • P - PSH包,推送数据。TCP层请求发送数据给应用层。

  • F - FIN包,完成报文。请求关闭连接。

  • R - RST包,复位报文。出现错误时使用。

所以当你使用tcpdump抓取TCP包头,如果Flags字段显示S,表示这个数据包是一个客户端请求建立连接的SYN包。它是TCP三次握手建立连接的第一步。


Flags [.] 是什么?


Flags [.]表示一个零长度的标志字段。

在tcpdump输出的TCP包头信息中,Flags 字段用来显示该TCP报文段的标志位情况。

常见的标志有:

  • S - SYN报文,表示建立连接请求
  • A - ACK报文,确认报文
  • P - PSH报文,推送数据
  • F - FIN报文,关闭连接请求

而Flags以”.”表示的意思是这个TCP报文段中所有标志位都被清除了,也就是零长度的标志。

一般情况下这个标志出现的情况包括:

  1. 初始连接建立后第一个ACK报文。第一个ACK没有其它标志设置。

  2. 一些TCP控制报文,比如一些RST/FIN报文。

  3. 虚假报文或有问题的报文。网络中可能会存在此类不完整或有误配置的报文。

  4. 某些状态没有定义的TCP报文。

所以简单来说,Flags [.]表示这是一个没有任何标志设定的TCP报文段,标志长度为0。主要出现在初始化和一些特殊控制报文中。


一直都是Flags [S],是不是有问题?


如果tcpdump抓取的TCP包头一直显示Flags [S],即使建立连接后都没有ACK标志,很可能表示存在问题:

  • 网络问题,例如接口错误导致无法建立正常连接。

  • 客户端软件问题,可能连接请求一直在发送但没有正确处理SERVER端响应。

  • 服务器软件问题,无法正确响应客户端连接并完成三次握手。

  • 防火墙或者网络设备过滤规则问题,过滤了非SYN 数据包。

一些可以检查的地方:

  1. 查看客户端和服务器是否有错误日志提示连接建立失败。

  2. 用tcpdump分别在客户端和服务器两端抓包对比,看连接建立过程是否正常。

  3. 检查相关接口是否有错误,如IP地址重复等网络配置问题。

  4. 尝试使用简单测试程序建立TCP连接端到端,是否也是一直在建立未成功。

  5. 检查是否有防火墙或其他设备阻断非SYN的数据包通行。

  6. 查看操作系统日志是否有破坏三次握手的进程或规则。

  7. 更新网络驱动或升级操作系统,排除程序兼容问题。

常见的情况,如果一直仅显示Flags [S]且连接建立失败,很可能存在上述网络、软件或设备配置等问题。需要进一步排查分析问题原因。



也可以在pod里面抓包,在新起一个shell界面,在pod里执行telnet 172.22.0.55 8421

没有172.22.0.47的回包


而在node上面执行抓包命令 sudo tcpdump -i any port 8421 and host 172.22.0.55 ,再新起一个shell,进行telnet,能看到有172.22.0.47的ack