0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

在Kubernetes集群发生网络异常时如何排查

马哥Linux运维 来源:博客园 作者:Cylon 2022-09-02 09:45 次阅读

本文将引入一个思路:“在 Kubernetes 集群发生网络异常时如何排查”。文章将引入 Kubernetes 集群中网络排查的思路,包含网络异常模型,常用工具,并且提出一些案例以供学习。

  • Pod 常见网络异常分类
  • 网络排查工具
  • Pod 网络异常排查思路及流程模型
  • CNI 网络异常排查步骤
  • 案例学习

Pod 网络异常

网络异常大概分为如下几类:

  • 网络不可达,主要现象为 ping 不通,其可能原因为:

    • 源端和目的端防火墙(iptables,selinux)限制
    • 网络路由配置不正确
    • 源端和目的端的系统负载过高,网络连接数满,网卡队列满
    • 网络链路故障
  • 端口不可达:主要现象为可以 ping 通,但 telnet 端口不通,其可能原因为:

    • 源端和目的端防火墙限制
    • 源端和目的端的系统负载过高,网络连接数满,网卡队列满,端口耗尽
    • 目的端应用未正常监听导致(应用未启动,或监听为 127.0.0.1 等)
  • DNS 解析异常:主要现象为基础网络可以连通,访问域名报错无法解析,访问 IP 可以正常连通。其可能原因为

    • Pod 的 DNS 配置不正确
    • DNS 服务异常
    • pod 与 DNS 服务通讯异常
  • 大数据包丢包:主要现象为基础网络和端口均可以连通,小数据包收发无异常,大数据包丢包。可能原因为:

    • 可使用ping -s指定数据包大小进行测试
    • 数据包的大小超过了 docker、CNI 插件、或者宿主机网卡的MTU值。

  • CNI 异常:主要现象为 Node 可以通,但 Pod 无法访问集群地址,可能原因有:

    • kube-proxy 服务异常,没有生成 iptables 策略或者 ipvs 规则导致无法访问
    • CIDR 耗尽,无法为 Node 注入PodCIDR导致 CNI 插件异常
    • 其他 CNI 插件问题

那么整个 Pod 网络异常分类可以如下图所示:

1ec3d2c4-2a04-11ed-ba43-dac502259ad0.pngPod network trouble hirarchy

总结一下,Pod 最常见的网络故障有,网络不可达(ping 不通);端口不可达(telnet 不通);DNS 解析异常(域名不通)与大数据包丢失(大包不通)。

常用网络排查工具

在了解到常见的网络异常后,在排查时就需要使用到一些网络工具才可以很有效的定位到网络故障原因,下面会介绍一些网络排查工具。

tcpdump

tcpdump 网络嗅探器,将强大和简单结合到一个单一的命令行界面中,能够将网络中的报文抓取,输出到屏幕或者记录到文件中。

各系统下的安装

  • Ubuntu/Debian:tcpdumpapt-get install -y tcpdump
  • Centos/Fedora:tcpdumpyum install -y tcpdump
  • Apline:tcpdumpapk add tcpdump --no-cache

查看指定接口上的所有通讯

语法

参数 说明
-i [interface]
-w [flle] 第一个 n 表示将地址解析为数字格式而不是主机名,第二个 N 表示将端口解析为数字格式而不是服务名
-n 不显示 IP 地址
-X hex and ASCII
-A ASCII(实际上是以人类可读懂的包进行显示)
-XX
-v 详细信息
-r 读取文件而不是实时抓包
关键字
type host(主机名,域名,IP 地址), net, port, portrange
direction src, dst, src or dst , src and ds
protocol ether, ip,arp, tcp, udp, wlan

捕获所有网络接口

tcpdump-D

按 IP 查找流量

最常见的查询之一host,可以看到来往于1.1.1.1的流量。

tcpdumphost1.1.1.1

按源 / 目的 地址过滤

如果只想查看来自 / 向某方向流量,可以使用srcdst

tcpdumpsrc|dst1.1.1.1

通过网络查找数据包

使用net选项,来要查找出 / 入某个网络或子网的数据包。

tcpdumpnet1.2.3.0/24

使用十六进制输出数据包内容

hex可以以 16 进制输出包的内容

tcpdump-c1-Xicmp

查看特定端口的流量

使用port选项来查找特定的端口流量。

tcpdumpport3389
tcpdumpsrcport1025

查找端口范围的流量

tcpdumpportrange21-23

过滤包的大小

如果需要查找特定大小的数据包,可以使用以下选项。你可以使用lessgreater

tcpdumpless32
tcpdumpgreater64
tcpdump<= 128

捕获流量输出为文件

-w可以将数据包捕获保存到一个文件中以便将来进行分析。这些文件称为PCAP(PEE-cap)文件,它们可以由不同的工具处理,包括Wireshark

tcpdumpport80-wcapture_file

组合条件

tcpdump 也可以结合逻辑运算符进行组合条件查询

  • ANDandor&&
  • ORoror||
  • EXCEPTnotor!
tcpdump-ieth0-nnhost220.181.57.216and10.0.0.1#主机之间的通讯
tcpdump-ieth0-nnhost220.181.57.216or10.0.0.1
#获取10.0.0.1与10.0.0.9或10.0.0.1与10.0.0.3之间的通讯
tcpdump-ieth0-nnhost10.0.0.1and(10.0.0.9or10.0.0.3)

原始输出

并显示人类可读的内容进行输出包(不包含内容)。

tcpdump-ttnnvvS-ieth0
tcpdump-ttnnvvS-ieth0

IP 到端口

让我们查找从某个 IP 到端口任何主机的某个端口所有流量。

tcpdump-nnvvSsrc10.5.2.3anddstport3389

去除特定流量

可以将指定的流量排除,如这显示所有到 192.168.0.2 的 非 ICMP 的流量。

tcpdumpdst192.168.0.2andsrcnetandnoticmp

来自非指定端口的流量,如,显示来自不是 SSH 流量的主机的所有流量。

tcpdump-vvsrcmarsandnotdstport22

选项分组

在构建复杂查询时,必须使用单引号'。单引号用于忽略特殊符号(),以便于使用其他表达式(如 host, port, net 等)进行分组。

tcpdump'src10.0.2.4and(dstport3389or22)'

过滤 TCP 标记位

TCP RST

The filters below find these various packets because tcp[13] looks at offset 13 in the TCP header, the number represents the location within the byte, and the !=0 means that the flag in question is set to 1, i.e. it’s on.

tcpdump'tcp[13]&4!=0'
tcpdump'tcp[tcpflags]==tcp-rst'

TCP SYN

tcpdump'tcp[13]&2!=0'
tcpdump'tcp[tcpflags]==tcp-syn'

同时忽略 SYN 和 ACK 标志的数据包

tcpdump'tcp[13]=18'

TCP URG

tcpdump'tcp[13]&32!=0'
tcpdump'tcp[tcpflags]==tcp-urg'

TCP ACK

tcpdump'tcp[13]&16!=0'
tcpdump'tcp[tcpflags]==tcp-ack'

TCP PSH

tcpdump'tcp[13]&8!=0'
tcpdump'tcp[tcpflags]==tcp-push'

TCP FIN

tcpdump'tcp[13]&1!=0'
tcpdump'tcp[tcpflags]==tcp-fin'

查找 http 包

查找user-agent信息

tcpdump-vvAls0|grep'User-Agent:'

查找只是GET请求的流量

tcpdump-vvAls0|grep'GET'

查找 http 客户端 IP

tcpdump-vvAls0|grep'Host:'

查询客户端 cookie

tcpdump-vvAls0|grep'Set-Cookie|Host:|Cookie:'

查找 DNS 流量

tcpdump-vvAs0port53

查找对应流量的明文密码

tcpdumpporthttporportftporportsmtporportimaporportpop3orporttelnet-lA|egrep-i-B5'pass=|pwd=|log=|login=|user=|username=|pw=|passw=|passwd=|password=|pass:|user:|username:|password:|login:|pass|user'

wireshark 追踪流

wireshare 追踪流可以很好的了解出在一次交互过程中都发生了那些问题。

wireshare 选中包,右键选择 “追踪流“ 如果该包是允许的协议是可以打开该选项的

关于抓包节点和抓包设备

如何抓取有用的包,以及如何找到对应的接口,有以下建议

抓包节点

通常情况下会在源端和目的端两端同时抓包,观察数据包是否从源端正常发出,目的端是否接收到数据包并给源端回包,以及源端是否正常接收到回包。如果有丢包现象,则沿网络链路上各节点抓包排查。例如,A 节点经过 c 节点到 B 节点,先在 AB 两端同时抓包,如果 B 节点未收到 A 节点的包,则在 c 节点同时抓包。

抓包设备

对于 Kubernetes 集群中的 Pod,由于容器内不便于抓包,通常视情况在 Pod 数据包经过的 veth 设备,docker0网桥,CNI插件设备(如 cni0,flannel.1 etc..)及 Pod 所在节点的网卡设备上指定 Pod IP 进行抓包。选取的设备根据怀疑导致网络问题的原因而定,比如范围由大缩小,从源端逐渐靠近目的端,比如怀疑是CNI插件导致,则在CNI插件设备上抓包。从 pod 发出的包逐一经过 veth 设备,cni0设备,flannel0,宿主机网卡,到达对端,抓包时可按顺序逐一抓包,定位问题节点。

需要注意在不同设备上抓包时指定的源目 IP 地址需要转换,如抓取某 Pod 时,ping{host}的包,在vethcni0上可以指定 Pod IP 抓包,而在宿主机网卡上如果仍然指定 Pod IP 会发现抓不到包,因为此时 Pod IP 已被转换为宿主机网卡 IP。

下图是一个使用VxLAN模式的flannel的跨界点通讯的网络模型,在抓包时需要注意对应的网络接口

1f0bafd6-2a04-11ed-ba43-dac502259ad0.pngVxLAN in kubernetes

nsenter

nsenter 是一款可以进入进程的名称空间中。例如,如果一个容器以非 root 用户身份运行,而使用docker exec进入其中后,但该容器没有安装sudo或未netstat,并且您想查看其当前的网络属性,如开放端口,这种场景下将如何做到这一点?nsenter就是用来解决这个问题的。

nsenter(namespace enter) 可以在容器的宿主机上使用nsenter命令进入容器的命名空间,以容器视角使用宿主机上的相应网络命令进行操作。当然需要拥有root权限

各系统下的安装[2][1]

  • Ubuntu/Debian:util-linuxapt-get install -y util-linux
  • Centos/Fedora:util-linuxyum install -y util-linux
  • Apline:util-linuxapk add util-linux --no-cache

nsenter的 c 使用语法为,nsenter -t pid -n -t接 进程 ID 号,-n表示进入名称空间内,为执行的命令。

实例:如我们有一个 Pod 进程 ID 为 30858,进入该 Pod 名称空间内执行ifconfig,如下列所示

$ps-ef|greptail
root1763662887020:19pts/20000grep--color=autotail
root3085830838015:55?0001tail-f

$nsenter-t30858-nifconfig
eth0:flags=4163mtu1480
inet192.168.1.213netmask255.255.255.0broadcast192.168.1.255
ether5e98dc:6btxqueuelen0(Ethernet)
RXpackets92bytes9100(8.8KiB)
RXerrors0dropped0overruns0frame0
TXpackets92bytes8422(8.2KiB)
TXerrors0dropped0overruns0carrier0collisions0

lo:flags=73mtu65536
inet127.0.0.1netmask255.0.0.0
looptxqueuelen1000(LocalLoopback)
RXpackets5bytes448(448.0B)
RXerrors0dropped0overruns0frame0
TXpackets5bytes448(448.0B)
TXerrors0dropped0overruns0carrier0collisions0

net1:flags=4163mtu1500
inet10.1.0.201netmask255.255.255.0broadcast10.1.0.255
etherb2f92a:10txqueuelen0(Ethernet)
RXpackets228bytes21272(20.7KiB)
RXerrors0dropped0overruns0frame0
TXpackets216bytes20272(19.7KiB)
TXerrors0dropped0overruns0carrier0collisions0

如何定位 Pod 名称空间

首先需要确定 Pod 所在的节点名称

$kubectlgetpods-owide|awk'{print$1,$7}'
NAMENODE
netbox-85865d5556-hfg6vmaster-machine
netbox-85865d5556-vlgr4node01

如果 Pod 不在当前节点还需要用 IP 登录则还需要查看 IP(可选)

$kubectlgetpods-owide|awk'{print$1,$6,$7}'
NAMEIPNODE
netbox-85865d5556-hfg6v192.168.1.213master-machine
netbox-85865d5556-vlgr4192.168.0.4node01

接下来,登录节点,获取容器 lD,如下列所示,每个 pod 默认有一个pause容器,其他为用户 yaml 文件中定义的容器,理论上所有容器共享相同的网络命名空间,排查时可任选一个容器。

$dockerps|grepnetbox-85865d5556-hfg6v
6f8c58377aaef78dd05f11ff"tail-f"45hoursagoUp45hoursk8s_netbox_netbox-85865d5556-hfg6v_default_4a8e2da8-05d1-4c81-97a7-3d76343a323a_0
b9c732ee457eregistry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.1"/pause"45hoursagoUp45hoursk8s_POD_netbox-85865d5556-hfg6v_default_4a8e2da8-05d1-4c81-97a7-3d76343a323a_0

接下来获得获取容器在节点系统中对应的进程号,如下所示

$dockerinspect--format"{{.State.Pid}}"6f8c58377aae
30858

最后就可以通过nsenter进入容器网络空间执行命令了

paping

paping命令可对目标地址指定端口以 TCP 协议进行连续 ping,通过这种特性可以弥补pingICMP 协议,以及nmap,telnet只能进行一次操作的的不足;通常情况下会用于测试端口连通性和丢包率

paping download:paping[2]

paping还需要安装以下依赖,这取决于你安装的paping版本

  • RedHat/CentOS:yum install -y libstdc++.i686 glibc.i686
  • Ubuntu/Debian:最小化安装无需依赖
$paping-h
papingv1.5.5-Copyright(c)2011MikeLovell

Syntax:paping[options]destination

Options:
-?,--helpdisplayusage
-p,--portNsetTCPportN(required)
--nocolorDisablecoloroutput
-t,--timeouttimeoutinmilliseconds(default1000)
-c,--countNsetnumberofcheckstoN

mtr

mtr是一个跨平台的网络诊断工具,将tracerouteping的功能结合到一个工具。与traceroute不同的是mtr显示的信息比起traceroute更加丰富:通过mtr可以确定网络的条数,并且可以同时打印响应百分比以及网络中各跳跃点的响应时间。

各系统下的安装[2][3]

  • Ubuntu/Debian:mtrapt-get install -y mtr
  • Centos/Fedora:mtryum install -y mtr
  • Apline:mtrapk add mtr --no-cache

简单的使用示例

最简单的示例,就是后接域名或 IP,这将跟踪整个路由

$mtrgoogle.com

Start:ThuJun2812132018
HOST:TecMintLoss%SntLastAvgBestWrstStDev
1.|--192.168.0.10.0%50.30.30.30.40.0
2.|--5.5.5.2110.0%50.70.90.71.30.0
3.|--209.snat-111-91-120.hns.n80.0%57.17.17.17.10.0
4.|--72.14.194.2260.0%51.92.91.94.41.1
5.|--108.170.248.1610.0%52.93.52.04.30.7
6.|--216.239.62.2370.0%53.06.22.918.36.7
7.|--bom05s12-in-f14.1e100.net0.0%52.12.42.03.80.5

-n强制mtr打印 IP 地址而不是主机名

$mtr-ngoogle.com

Start:ThuJun2812582018
HOST:TecMintLoss%SntLastAvgBestWrstStDev
1.|--192.168.0.10.0%50.30.30.30.40.0
2.|--5.5.5.2110.0%50.90.90.81.10.0
3.|--???100.050.00.00.00.00.0
4.|--72.14.194.2260.0%52.02.01.92.00.0
5.|--108.170.248.1610.0%52.32.32.22.40.0
6.|--216.239.62.2370.0%53.03.23.03.30.0
7.|--172.217.160.1740.0%53.73.62.05.31.4

-b同时显示 IP 地址与主机名

$mtr-bgoogle.com

Start:ThuJun2812362018
HOST:TecMintLoss%SntLastAvgBestWrstStDev
1.|--192.168.0.10.0%50.30.30.30.40.0
2.|--5.5.5.2110.0%50.70.80.61.00.0
3.|--209.snat-111-91-120.hns.n0.0%51.41.61.32.10.0
4.|--72.14.194.2260.0%51.82.11.82.60.0
5.|--108.170.248.2090.0%52.01.91.82.00.0
6.|--216.239.56.1150.0%52.42.72.42.90.0
7.|--bom07s15-in-f14.1e100.net0.0%53.72.21.73.70.9

-c跟一个具体的值,这将限制mtrping 的次数,到达次数后会退出

$mtr-c5google.com

如果需要指定次数,并且在退出后保存这些数据,使用-rflag

$mtr-r-c5google.com>1
$cat1
Start:SunAug2122492022
HOST:xxxxx.xxxxx.xxxx.xxxxLoss%SntLastAvgBestWrstStDev
1.|--gateway0.0%50.6146.80.6420.2191.4
2.|--212.xx.21.2410.0%50.41.00.42.30.5
3.|--188.xxx.106.1240.0%50.71.10.72.10.5
4.|--???100.050.00.00.00.00.0
5.|--72.14.209.890.0%543.243.343.143.30.0
6.|--108.xxx.250.330.0%543.243.143.143.20.0
7.|--108.xxx.250.340.0%543.743.643.543.70.0
8.|--142.xxx.238.820.0%560.660.960.661.20.0
9.|--142.xxx.238.640.0%559.767.559.389.813.2
10.|--142.xxx.37.810.0%562.762.962.663.50.0
11.|--142.xxx.229.850.0%561.060.960.761.30.0
12.|--xx-in-f14.1e100.net0.0%559.058.958.959.00.0

默认使用的是 ICMP 协议-i,可以指定-u, -t使用其他协议

mtr--tcpgoogle.com

-m指定最大的跳数

mtr-m35216.58.223.78

-s指定包的大小

mtr 输出的数据

colum describe
last 最近一次的探测延迟值
avg 探测延迟的平均值
best 探测延迟的最小值
wrst 探测延迟的最大值
stdev 标准偏差。越大说明相应节点越不稳定

丢包判断

任一节点的Loss%(丢包率)如果不为零,则说明这一跳网络可能存在问题。导致相应节点丢包的原因通常有两种。

  • 运营商基于安全或性能需求,人为限制了节点的 ICMP 发送速率,导致丢包。
  • 节点确实存在异常,导致丢包。可以结合异常节点及其后续节点的丢包情况,来判定丢包原因。

Notes:

  • 如果随后节点均没有丢包,则通常说明异常节点丢包是由于运营商策略限制所致。可以忽略相关丢包。
  • 如果随后节点也出现丢包,则通常说明节点确实存在网络异常,导致丢包。对于这种情况,如果异常节点及其后续节点连续出现丢包,而且各节点的丢包率不同,则通常以最后几跳的丢包率为准。如链路测试在第 5、6、7 跳均出现了丢包。最终丢包情况以第 7 跳作为参考。

延迟判断

由于链路抖动或其它因素的影响,节点的BestWorst值可能相差很大。而Avg(平均值)统计了自链路测试以来所有探测的平均值,所以能更好的反应出相应节点的网络质量。而StDev(标准偏差值)越高,则说明数据包在相应节点的延时值越不相同(越离散)。所以标准偏差值可用于协助判断Avg是否真实反应了相应节点的网络质量。例如,如果标准偏差很大,说明数据包的延迟是不确定的。可能某些数据包延迟很小(例如:25ms),而另一些延迟却很大(例如:350ms),但最终得到的平均延迟反而可能是正常的。所以此时Avg并不能很好的反应出实际的网络质量情况。

这就需要结合如下情况进行判断:

  • 如果StDev很高,则同步观察相应节点的Bestwrst,来判断相应节点是否存在异常。
  • 如果StDev不高,则通过 Avg 来判断相应节点是否存在异常。

Pod 网络排查流程

Pod 网络异常时排查思路,可以按照下图所示

1f38aa04-2a04-11ed-ba43-dac502259ad0.pngPod network troubleshooting idea

案例学习

扩容节点访问 service 地址不通

测试环境 k8s 节点扩容后无法访问集群 clusterlP 类型的 registry 服务

环境信息:

IP Hostname role
10.153.204.15 yq01-aip-aikefu12 worknode 节点(本次扩容的问题节点)
10.153.203.14 yq01-aip-aikefu31 master 节点
10.61.187.42 yq01-aip-aikefu2746f8e9 master 节点
10.61.187.48 yq01-aip-aikefu30b61e25 master 节点(本次 registry 服务 pod 所在 节点)
  • cni 插件:flannel vxlan
  • kube-proxy 工作模式为 iptables
  • registry 服务
    • 单实例部署在 10.61.187.48:5000
    • Pod IP:10.233.65.46,
    • Cluster IP:10.233.0.100

现象:

  • 所有节点之间的 pod 通信正常
  • 任意节点和 Pod curl registry 的 Pod 的IP:5000均可以连通
  • 新扩容节点 10.153.204.15 curl registry 服务的 Cluster lP 10.233.0.100:5000 不通,其他节点 curl 均可以连通

分析思路:

  • 根据现象 1 可以初步判断CNI插件无异常
  • 根据现象 2 可以判断registryPod无异常
  • 根据现象 3 可以判断registryservice异常的可能性不大,可能是新扩容节点访问registryservice存在异常

怀疑方向:

  • 问题节点的 kube-proxy 存在异常
  • 问题节点的 iptables 规则存在异常
  • 问题节点到 service 的网络层面存在异常

排查过程:

  • 排查问题节点的kube-proxy
  • 执行kubectl get pod -owide -nkube-system l grep kube-proxy查看kube-proxyPod 的状态,问题节点上的kube-proxyPod 为running状态
  • 执行kubecti logs -nkube-system查看问题节点kube-proxy的 Pod 日志,没有异常报错
  • 在问题节点操作系统上执行iptables -S -t nat查看iptables规则

排查过程:

确认存在到registry服务的 Cluster lP10.233.0.100KUBE-SERVICES链,跳转至KUBE-SVC-* 链做负载均衡,再跳转至KUBE-SEP-* 链通过DNAT替换为服务后端 Pod 的 IP 10.233.65.46。因此判断 iptables 规则无异常执行 route-n 查看问题节点存在访问 10.233.65.46 所在网段的路由,如图所示

1f634e12-2a04-11ed-ba43-dac502259ad0.png10.233.65.46 路由

查看对端的回程路由

1fa6a572-2a04-11ed-ba43-dac502259ad0.png回程路由

以上排查证明问题原因不是cni插件或者kube-proxy异常导致,因此需要在访问链路上抓包,判断问题原因、问题节点执行curl 10.233.0.100:5000,在问题节点和后端 pod 所在节点的 flannel.1 上同时抓包发包节点一直在重传,Cluster lP 已DNAT转换为后端 Pod IP,如图所示

20c21ee6-2a04-11ed-ba43-dac502259ad0.png抓包过程,发送端

后端 Pod(registry服务)所在节点的flannel.1上未抓到任何数据包,如图所示

20dc53ce-2a04-11ed-ba43-dac502259ad0.png抓包过程,服务端

请求serviceClusterlP时,在两端物理机网卡抓包,发包端如图所示,封装的源端节点 IP 是 10.153.204.15,但一直在重传

210c52ae-2a04-11ed-ba43-dac502259ad0.png包传送过程,发送端

收包端收到了包,但未回包,如图所示

21497490-2a04-11ed-ba43-dac502259ad0.png包传送过程,服务端

由此可以知道,NAT 的动作已经完成,而只是后端 Pod(registry服务)没有回包,接下来在问题节点执行curl10.233.65.46:5000,在问题节点和后端(registry服务)Pod 所在节点的flannel.1上同时抓包,两节点收发正常,发包如图所示

22397454-2a04-11ed-ba43-dac502259ad0.png正常包发送端226fd382-2a04-11ed-ba43-dac502259ad0.png正常包接收端

接下来在两端物理机网卡接口抓包,因为数据包通过物理机网卡会进行vxlan封装,需要抓vxlan设备的 8472 端口,发包端如图所示

发现网络链路连通,但封装的 IP 不对,封装的源端节点 IP 是 10.153.204.228,但是存在问题节点的 IP 是 10.153.204.15

23fe6420-2a04-11ed-ba43-dac502259ad0.png问题节点物理机网卡接口抓包

后端 Pod 所在节点的物理网卡上抓包,注意需要过滤其他正常节点的请求包,如图所示;发现收到的数据包,源地址是 10.153.204.228,但是问题节点的 IP 是 10.153.204.15。

243c4e98-2a04-11ed-ba43-dac502259ad0.png对端节点物理机网卡接口抓包

此时问题以及清楚了,是一个 Pod 存在两个 IP,导致发包和回包时无法通过隧道设备找到对端的接口,所以发可以收到,但不能回。

问题节点执行ip addr,发现网卡enp26s0f0上配置了两个 IP,如图所示

247753a8-2a04-11ed-ba43-dac502259ad0.png问题节点 IP

进一步查看网卡配置文件,发现网卡既配置了静态 IP,又配置了 dhcp 动态获取 IP。如图所示

2491119e-2a04-11ed-ba43-dac502259ad0.png问题节点网卡配置

最终定位原因为问题节点既配置了 dhcp 获取 IP,又配置了静态 IP,导致 IP 冲突,引发网络异常

解决方法:修改网卡配置文件/etc/sysconfig/network-scripts/ifcfg-enp26s0f0BOOTPROTO="dhcp"BOOTPROTO="none";重启dockerkubelet问题解决。

集群外云主机调用集群内应用超时

问题现象:Kubernetes 集群外云主机以 http post 方式访问 Kubernetes 集群应用接口超时

环境信息:Kubernetes 集群:calicoIP-IP 模式,应用接口以 nodeport 方式对外提供服务

客户端:Kubernetes 集群之外的云主机

排查过程:

  • 在云主机 telnet 应用接口地址和端口,可以连通,证明网络连通正常,如图所示
  • 云主机上调用接口不通,在云主机和 Pod 所在 Kubernetes 节点同时抓包,使用 wireshark 分析数据包
24ded046-2a04-11ed-ba43-dac502259ad0.png

通过抓包结果分析结果为 TCP 链接建立没有问题,但是在传输大数据的时候会一直重传1514大小的第一个数据包直至超时。怀疑是链路两端 MTU 大小不一致导致(现象:某一个固定大小的包一直超时的情况)。如图所示,1514 大小的包一直在重传。

报文 1-3 TCP 三次握手正常

报文 1 info 中 MSS 字段可以看到 MSS 协商为 1460,MTU=1460+20bytes(IP 包头)+20bytes(TCP 包头)=1500

报文 7 k8s 主机确认了包 4 的数据包,但是后续再没有对数据的 ACK

报文 21-29 可以看到云主机一直在发送后面的数据,但是没有收到 k8s 节点的 ACK,结合 pod 未收到任何报文,表明是 k8s 节点和 POD 通信出现了问题。

250562ba-2a04-11ed-ba43-dac502259ad0.pngwireshark 分析

在云主机上使用ping -s指定数据包大小,发现超过 1400 大小的数据包无法正常发送。结合以上情况,定位是云主机网卡配置的 MTU 是 1500,tunl0配置的 MTU 是 1440,导致大数据包无法发送至tunl0,因此 Pod 没有收到报文,接口调用失败。

解决方法:修改云主机网卡 MTU 值为 1440,或者修改 calico 的 MTU 值为 1500,保持链路两端 MTU 值一致。

集群 pod 访问对象存储超时

环境信息:公有云环境,Kubernetes 集群节点和对象存储在同一私有网络下,网络链路无防火墙限制 k8s 集群开启了节点自动弹缩(CA)和 Pod 自动弹缩(HPA),通过域名访问对象存储,Pod 使用集群 DNS 服务,集群 DNS 服务配置了用户自建上游 DNS 服务器

排查过程:

  • 使用 nsenter 工具进入 pod 容器网络命名空间测试,ping 对象存储域名不通,报错 unknown server name,ping 对象存储 lP 可以连通。
  • telnet对象存储 80/443 端口可以连通。
  • paping对象存储 80/443 端口无丢包。
  • 为了验证 Pod 创建好以后的初始阶段网络连通性,将以上测试动作写入 dockerfile,重新生成容器镜像并创 pod,测试结果一致。

通过上述步骤,判断 Pod 网络连通性无异常,超时原因为域名解析失败,怀疑问题如下:

  • 集群 DNS 服务存在异常
  • 上游 DNS 服务存在异常
  • 集群 DNS 服务与上游 DNS 通讯异常
  • pod 访问集群 DNS 服务异常

根据上述方向排查,集群 DNS 服务状态正常,无报错。测试 Pod 分别使用集群 DNS 服务和上游 DNS 服务解析域名,前者解析失败,后者解析成功。至此,证明上游 DNS 服务正常,并且集群 DNS 服务日志中没有与上游 DNS 通讯超时的报错。定位到的问题:Pod 访问集群 DNS 服务超时

此时发现,出现问题的 Pod 集中在新弹出的 Kubernetes 节点上。这些节点的kube-proxyPod 状态全部为pending,没有正常调度到节点上。因此导致该节点上其他 Pod 无法访问包括 dns 在内的所有 Kubernetes service。

再进一步排查发现kube-proxyPod 没有配置 priorityclass 为最高优先级,导致节点资源紧张时为了将高优先级的应用 Pod 调度到该节点,将原本已运行在该节点的 kube-proxy 驱逐。

解决方法:将kube-proxy设置priorityclass值为system-node-critical最高优先级,同时建议应用 Pod 配置就绪探针,测试可以正常连通对象存储域名后再分配任务。

审核编辑:汤梓红


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 网络
    +关注

    关注

    14

    文章

    7251

    浏览量

    87437
  • kubernetes
    +关注

    关注

    0

    文章

    219

    浏览量

    8567

原文标题:Kubernetes 网络排错骨灰级中文指南

文章出处:【微信号:magedu-Linux,微信公众号:马哥Linux运维】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    Kubernetes 网络模型如何实现常见网络任务

    Kubernetes 是为运行分布式集群而建立的,分布式系统的本质使得网络成为 Kubernetes 的核心和必要组成部分,了解 Kubernete
    的头像 发表于 10-08 11:32 833次阅读

    阿里云上Kubernetes集群联邦

    规模的上限等等。Federation集群联邦可以一定程度上解决这些问题。Federation是可以将分布多个Region或者多个云厂商的Kubernetes集群整合成一个大的
    发表于 03-12 17:10

    Kubernetes Ingress 高可靠部署最佳实践

    摘要: Kubernetes集群中,Ingress作为集群流量接入层,Ingress的高可靠性显得尤为重要,今天我们主要探讨如何部署一套高性能高可靠的Ingress接入层。简介
    发表于 04-17 14:35

    kubernetes集群配置

    基于v1104版本手动搭建高可用kubernetes 集群
    发表于 08-19 08:07

    Kubernetes 从懵圈到熟练:集群服务的三个要点和一种实现

    以我的经验来讲,理解 Kubernetes 集群服务的概念,是比较不容易的一件事情。尤其是当我们基于似是而非的理解,去排查服务相关问题的时候,会非常不顺利。这体现在,对于新手来说,ping 不通服务
    发表于 09-24 15:35

    kubernetes v112二进制方式集群部署

    kubernetes v112 二进制方式集群部署
    发表于 05-05 16:30

    请问鸿蒙系统上可以部署kubernetes集群吗?

    鸿蒙系统上可以部署kubernetes集群
    发表于 06-08 11:16

    [组图]脉冲波群发生

         脉冲波群发生器又称“Bust波发生器”,多用于
    发表于 04-15 23:03 810次阅读
    [组图]脉冲波<b class='flag-5'>群发生</b>器

    如何部署基于Mesos的Kubernetes集群

    的内核。把Kubernetes运行在Mesos集群之上,可以和其他的框架共享集群资源,提高集群资源的利用率。 本文是Kubernetes和M
    发表于 10-09 18:04 0次下载
    如何部署基于Mesos的<b class='flag-5'>Kubernetes</b><b class='flag-5'>集群</b>

    浅谈Kubernetes集群的高可用方案

    Kubernetes作为容器应用的管理中心,通过对Pod的数量进行监控,并且根据主机或容器失效的状态将新的Pod调度到其他Node上,实现了应用层的高可用性。针对Kubernetes集群,高可用性
    发表于 10-11 10:04 1次下载
    浅谈<b class='flag-5'>Kubernetes</b><b class='flag-5'>集群</b>的高可用方案

    Kubernetes网络模型介绍以及如何实现常见网络任务

    Kubernetes 是为运行分布式集群而建立的,分布式系统的本质使得网络成为 Kubernetes 的核心和必要组成部分,了解 Kubernete
    的头像 发表于 05-05 20:22 1480次阅读

    Kubernetes网络模型的基础知识

    Kubernetes 是为运行分布式集群而建立的,分布式系统的本质使得网络成为 Kubernetes 的核心和必要组成部分,了解 Kubernete
    的头像 发表于 07-20 09:46 916次阅读

    Kubernetes 集群的功能

    Telepresence 是一个开源工具,可让您在本地运行单个服务,同时将该服务连接到远程 Kubernetes 集群
    的头像 发表于 09-05 10:58 802次阅读

    Kubernetes集群的关闭与重启

    在日常对 Kubernetes 集群运行维护的过程中,您可能需要临时的关闭或者是重启 Kubernetes 集群集群进行维护,本文将介绍如
    的头像 发表于 11-07 09:50 8729次阅读

    Kubernetes集群部署

    Kubeadm是一种Kubernetes集群部署工具,通过kubeadm init命令创建master节点,通过 kubeadm join命令把node节点加入到集群
    的头像 发表于 02-15 10:35 964次阅读