容器访问应用服务不通问题排查

发布时间:2020-07-27 11:40:31 作者:AntfinCloud
来源:网络 阅读:496

问题的起点

1、用户反馈同个ECS启动了多个容器,其中一个容器无法与Anytunnel 100.64.0.1通信,TCP建联失败。不通的容器IP是172.16.0.13。其他能通的容器比如 172.16.0.15。

2、在Anytunnel 100.64.0.1的后端RS上抓包,发现有172.16.0.13 TCP 建联成功的的记录。说明有其他VPC也有用172.16.013地址来访问,并且是通的。

PS:AnyTunnel地址指的是每个VPC中100.64.0.0/10内的地址,用于VPC中DNS、YUM、NTP、OSS或SLS等云服务中使用。简单可以理解为在VPC下为了解决不同VPC内网互通的特殊的SLB。这个SLB能被同个Region下所有的VPC访问。

容器访问应用服务不通问题排查

排查过程

1、首先我们要确定VPC1下172.16.0.13的请求有没有到达AnyTunnel后端RS上,最简单的方法就是在172.16.0.13和后端RS上同时抓包进行分析。

容器访问应用服务不通问题排查

容器访问应用服务不通问题排查

客户端和RS上抓包通过“tcp.analysis.retransmission”条件过滤出有问题的重传报文,发都是SYN的重传。

重传报文数量都是7个,并且源端口一致,那么说明请求报文已经到达RS上,但是RS没有响应SYN-ACK,导致TCP建联失败。

2、在RS上查看TCP计数发现:

netstat -ts |grep SYNs   
3631812 SYNs to LISTEN sockets dropped

有大量tcp syn包被丢弃,数值一直在增长,进一步说明是RS收到客户端的SYN请求但是没有响应。

为何RS没有响应SYN请求分析

netstat中的计数统计,里面定义了TCP连接失败统计,具体如下:

通过netstat -ts查看到passive connections rejected because of time stamp统计数值非常大,并且接近于SYNs to LISTEN sockets dropped的数量。

3631476 passive connections rejected because of time stamp

说明就是由于syn包相应连接的时间戳问题导致的。

于是再次分析RS的抓包文件:

容器访问应用服务不通问题排查

报文序列

是否成功响应SYN

TimeStamp值

1

成功响应SYN

2088983548

2

没有响应SYN

271344470

3

没有响应SYN

271345544

4

没有响应SYN

271346612

5

没有响应SYN

271348509

6

没有响应SYN

271351766

7

成功响应SYN

2088993553

从抓包信息里可以看出,当后面的SYN报文的TimeStamp值小于前面成功响应的SYN报文的TimeStamp值,系统默认就会不响应该SYN请求。

通过上面分析,问题明显和tcp timestmap有关,发现tcp_tw_recycle/tcp_timestamps都开启的条件下,60秒内同一源ip主机的socket connect请求中的timestamp必须是递增的。

源码函数:tcp_v4_conn_request(),该函数是tcp层三次握手syn包的处理函数(服务端);
    源码片段:
       if (tmp_opt.saw_tstamp &&
            tcp_death_row.sysctl_tw_recycle &&
            (dst = inet_csk_route_req(sk, req)) != NULL &&
            (peer = rt_get_peer((struct rtable *)dst)) != NULL &&
            peer->v4daddr == saddr) {
            if (get_seconds() < peer->tcp_ts_stamp + TCP_PAWS_MSL &&
                (s32)(peer->tcp_ts - req->ts_recent) >
                            TCP_PAWS_WINDOW) {
                NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSPASSIVEREJECTED);
                goto drop_and_release;
            }
        }
        
tmp_opt.saw_tstamp:该socket支持tcp_timestamp
sysctl_tw_recycle:系统开启tcp_tw_recycle选项
TCP_PAWS_MSL:60s,该条件判断表示该源ip的上次tcp通讯发生在60s内
TCP_PAWS_WINDOW:1,该条件判断表示该源ip的上次tcp通讯的timestamp大于本次tcp

Tcp_timestamp 是 RFC1323 定义的优化选项,主要用于 TCP 连接中 RTT(Round Trip Time) 的计算,开启 tcp_timestamp 有利于系统计算更加准确的 RTT,也就有利于 TCP 性能的提升。

tcp_tw_recycle (Boolean; default: disabled; since Linux 2.4)
              Enable fast recycling of TIME_WAIT sockets.  Enabling this option is not recommended since this causes problems when working with NAT (Network Address
              Translation).

开启tcp_tw_recycle会启用tcp time_wait的快速回收,这个参数不建议在NAT环境中启用,它会引起相关问题。

官方定义是在NAT环境中使用会引发问题,但是归根结底就是多个客户端使用同个地址访问服务端会出现该问题。我们的问题符合该场景。

解决方案

有两个方案可选:

由于客户端掌握在客户的手里,我们无法掌握到每个客户端的配置,所以还是需要服务端进行配置。

因为在tcp timestamp关闭的条件下,开启tcp_tw_recycle是不起作用的;而tcp timestamp可以独立开启并起作用。所以建议服务关闭tcp_tw_recycle.

服务端(RS端)关闭tcp_tw_recycle具体操作方法。

1、临时关闭方法:
echo "0" > /proc/sys/net/ipv4/tcp_tw_recycle

2、永久关闭方法:
在 /etc/sysctl.conf 文件中添加 net.ipv4.tcp_tw_recycle = 0
然后使用 sysctl -p 命令让配置文件生效

引伸

根据上面的原理,出现多个客户端同时使用同一个IP访问同一个服务端的场景要在服务端关闭tcp_tw_recycle。如以下场景:

1、同一个Client访问四层私网SLB的同时,还有绕过SLB直接访问SLB后端ECS

容器访问应用服务不通问题排查

2、相同的ECS同时挂在多个四层SLB之后,并且同一个客户端有同时或者连续访问多个SLB

容器访问应用服务不通问题排查

3、ECS通过公网地址,NAT网关和EIP直接提供服务的。因为由于目前IPV4地址枯竭,绝大部分的客户端都是使用SNAT进行访问。


附录

参考:

http://blog.sina.com.cn/s/blog_781b0c850101pu2q.html


推荐阅读:
  1. Web应用服务器如何实现并发访问控制
  2. 问题排查-jmap和MAT工具

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

ecs 容器 slb

上一篇:Django怎么在Model保存前记录日志

下一篇:MySQL explain怎么获取查询指令信息

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》