遇到了一个使用 glance 命令行工具下载镜像卡住的问题,镜像下载一部分之后就莫名其妙的卡住了,通过分析之后发现了两个问题。
问题一
一个问题和 glance image-download 的选项 --progress
有关,不知为何,客户端机器的两个终端 SecureCRT 和 MobaXterm 往终端写时都存在问题,由于 glance 是一个 Python 单线程程序,导致写终端卡住:
1 | # ps aux | grep image-download |
直接导致 socket 数据接收卡住,直接表现就是发送端的发送报文积压:
1 | # ss -ntp | sort -nk 3 | tail |
由于 TCP 没有接收窗口,导致发送端持续处于零窗口探测阶段:
当然,同时通过 ss 查看客户端的接受队列,也能发现存在大量的报文积压。
显然,简单的解决办法就是去掉 --progress
选项。
问题二
还一个问题看上去与网络有关,通过 tcpdump 进行抓包可以发现 glance-api 发往 Ceph OSD 的重传报文无法顺利送达 OSD:
注意:如果客户端和服务端在同一台机器上,即使 IP 地址绑定在不同的网口上,但使用 tcpdump 时需要使用 -i
选项指定 lo
网口进行抓包。
这里最大的疑问在于,客户端的重传报文在服务端无法得到应答,但是最后服务端那个主动断链的 FIN
报文却在客户端能得到正确的响应,通过多次抓包得到的信息都是这样:
通过 ss 查看最后一个抓包所涉及的 socket 信息:
客户端(glance-api)
1 | # ss -ntpioem 'src 192.168.66.246:52826' |
服务端(Ceph OSD)
1 | # ss -ntpioem 'dst 192.168.66.246:52826' |
显然,客户端一直在尝试重传,但客户端始终未收到任何 TCP 报文。
这里仍是一个悬案,临时的规避手段就是设置 /proc/sys/net/ipv4/tcp_retries2
系统参数,或者 TCP_USER_TIMEOUT
socket 选项。
参考资料
Manpage of PCAP-FILTER
https://www.tcpdump.org/manpages/pcap-filter.7.html
Linux TCP_RTO_MIN, TCP_RTO_MAX and the tcp_retries2 sysctl
https://pracucci.com/linux-tcp-rto-min-max-and-tcp-retries2.html
The “Out of socket memory” error
https://blog.tsunanet.net/2011/03/out-of-socket-memory.html
How to drop 10 million packets per second
https://blog.cloudflare.com/how-to-drop-10-million-packets/
Problem with target “NOTRACK”
https://github.com/ldx/python-iptables/issues/204
nf_conntrack: table full, dropping packet
Caveats about Linux connection tracking and high traffic servers
https://i-admin.blogspot.com/2014/02/caveats-about-linux-connection-tracking.html