相关背景:
从一个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 地址通常指的是:
Pod IP (
10.8.0.210): 这是分配给 Pod 的内部 IP 地址。在 Kubernetes 集群内部,其他 Pod 可以使用这个 IP 地址来访问此 Pod。这个 IP 地址是在 Kubernetes 集群的内部网络空间中唯一的,通常由集群的网络插件(如 Calico、Flannel、Weave 等)管理和分配。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的指导。
在节点上抓包
找出Pod使用的网络接口:首先,你需要确定Pod通信经过的网络接口。通常,Kubernetes集群使用特定的网络接口或网桥(如
cni0、flannel.1等)用于Pod之间的通信。你可以通过查看节点的网络接口列表来猜测哪个是用于Pod网络的接口。1
ip addr
在节点上运行tcpdump:一旦你确定了Pod通信所使用的网络接口,就可以在该接口上运行
tcpdump来捕获流量。例如,如果你认为cni0是Pod网络接口,可以使用以下命令:1
sudo tcpdump -i cni0 -nn port 8421
这个命令会捕获通过接口
cni0上端口8421的所有TCP流量。-nn选项防止tcpdump尝试解析主机名和端口名。
在Pod内部抓包
由于Pod内部可能没有安装tcpdump,你可能需要使用一个带有tcpdump的调试容器,或者在现有的Pod中安装tcpdump(如果你的容器镜像支持)。
进入Pod:使用
kubectl exec进入Pod内部。1
kubectl exec -it <pod-name> -- /bin/sh
安装tcpdump(如果需要):这取决于你的容器基础镜像。对于基于Debian或Ubuntu的镜像,你可以运行:
1
apt-get update && apt-get install -y tcpdump
运行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 路由表,这对于了解和管理系统如何将网络流量从一个网络接口转发到另一个网络接口非常有用。路由表的每一行都代表了一条路由规则,说明了数据包如何根据其目的地被转发。对于你提到的两行:
10.8.0.0 10.8.0.2 255.255.255.0 UG 0 0 0 tun010.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连接。
- Destination(目的网段):
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同上,是数据包出去的网络接口。
- Destination(目的地址):
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 | sudo tcpdump -i any -nn port 8421 |
1 | sudo tcpdump -i any -nn port 8421 |
只看到了请求端的包(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报文段中所有标志位都被清除了,也就是零长度的标志。
一般情况下这个标志出现的情况包括:
初始连接建立后第一个ACK报文。第一个ACK没有其它标志设置。
一些TCP控制报文,比如一些RST/FIN报文。
虚假报文或有问题的报文。网络中可能会存在此类不完整或有误配置的报文。
某些状态没有定义的TCP报文。
所以简单来说,Flags [.]表示这是一个没有任何标志设定的TCP报文段,标志长度为0。主要出现在初始化和一些特殊控制报文中。
一直都是Flags [S],是不是有问题?
如果tcpdump抓取的TCP包头一直显示Flags [S],即使建立连接后都没有ACK标志,很可能表示存在问题:
网络问题,例如接口错误导致无法建立正常连接。
客户端软件问题,可能连接请求一直在发送但没有正确处理SERVER端响应。
服务器软件问题,无法正确响应客户端连接并完成三次握手。
防火墙或者网络设备过滤规则问题,过滤了非SYN 数据包。
一些可以检查的地方:
查看客户端和服务器是否有错误日志提示连接建立失败。
用tcpdump分别在客户端和服务器两端抓包对比,看连接建立过程是否正常。
检查相关接口是否有错误,如IP地址重复等网络配置问题。
尝试使用简单测试程序建立TCP连接端到端,是否也是一直在建立未成功。
检查是否有防火墙或其他设备阻断非SYN的数据包通行。
查看操作系统日志是否有破坏三次握手的进程或规则。
更新网络驱动或升级操作系统,排除程序兼容问题。
常见的情况,如果一直仅显示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
原文链接: https://dashen.tech/2017/03/05/一次抓包排除网络故障/
版权声明: 转载请注明出处.