1) DNS超时相关问题
在云原生环境中,DNS服务超时问题会导致服务的访问失败,出现DNS访问超时的常见原因有:
● DNS服务响应的速度较慢,无法在用户程序的超时时间到达前完成一次DNS查询。
● 由于发送端的问题,没有顺利或者及时发送DNS Query报文。
● 服务端及时响应了报文,但是由于发送端本身的内存不足等问题出现了丢包。
您可以借助以下几个指标来帮助排查偶发的DNS超时问题:
指标名称 |
说明 |
inspector_pod_udpsndbuferrors |
UDP协议通过网络层方法发送时出现报错的次数 |
inspector_pod_udpincsumerrors |
UDP接收报文时出现CSUM校验错误的次数 |
inspector_pod_udpnoports |
网络层调用__udp4_lib_rcv收包时找不到对应端口的Socket的次数 |
inspector_pod_udpinerrors |
UDP接收报文时出现错误的次数 |
inspector_pod_udpoutdatagrams |
UDP协议通过网络层方法成功发送报文的数量 |
inspector_pod_udprcvbuferrors |
UDP在将应用层协议数据拷贝到Socket接收队列时由于队列不足导致的报错次数 |
由于云原生环境中很多服务依赖于CoreDNS提供域名解析服务,在出现DNS问题时,如果出现问题的DNS请求与CoreDNS有关,您需要同时观察CoreDNS相关Pod的上述指标的异常情况。
1) Nginx Ingress 499/502/503/504相关问题
云原生环境下,Ingress网关或者其他担任Proxy/Broker作用的代理服务出现偶发的异常是较为常见的疑难问题,对于Nginx Ingress及以Nginx为底座的其他代理服务中,499/502/503/504问题是最为常见的四类,他们各自表征的含义如下:
● 499,当请求Nginx的客户端在Nginx没有进行回复的时候就关闭了TCP连接,常见原因包括:
◦ 客户端连接建立之后,发送请求较晚,导致Nginx回复过程中就达到了Client Timeout,常见于Android客户端的异步请求框架中。
◦ 服务端在连接建立后,连接的处理较慢,需要深入排查。
◦ 服务端在向上游Upstream的后端发起请求时,后端处理较慢。
● 502,场景很多,多见于Nginx与Upstream后端之间连接层面的问题,例如连接建立失败,或者后端异常的关闭,常见原因包括:
◦ 后端配置的DNS域名解析失败,通常在使用Kubernetes Service作为后端时会出现。
◦ 与Upstream之间建立连接失败。
◦ Upstream的请求或者响应过大,无法分配到内存等干扰正常业务交互的现象。
● 503,在Nginx中,用于提示客户端,所有的Upstream均出现了不可用的情况,在云原生场景下,有一些特定的含义,常见原因包括:
◦ 没有可用的后端,这种情况通常出现较少。
◦ 流量过大,被Ingress的Limit Req所限制。
● 504,用于表征Nginx与Upstream相关的业务报文出现超时的问题,常见原因为Upstream返回的业务报文没有及时到达。
在遇到上述几类问题时,您需要先收集一些通用的信息用于界定问题发生的可能范围与下一步排查方向:
● Nginx提供的access_log信息,尤其是request_time、upstream_connect_time与upstrem_response_time。
● Nginx提供的error_log信息,在问题发生时是否有异常的报错信息出现。
● 如果配置了Liveness或者Readness健康检查,可查看健康检查。
在上述信息的基础上,您需要按照问题的具体现象关注以下指标的变化,在可能出现连接失败时:
指标名称 |
说明 |
inspector_pod_tcpextlistenoverflows |
当LISTEN状态的Sock接受连接时出现半连接队列溢出时会计数 |
inspector_pod_tcpextlistendrops |
当LISTEN状态的Sock创建SYN_RECV状态的Sock失败时会计数 |
inspector_pod_netdevtxdropped |
网卡发送错误并产生丢弃的次数 |
inspector_pod_netdevrxdropped |
网卡接收错误并产生丢弃的次数 |
inspector_pod_tcpactiveopens |
单个Pod内TCP成功发起SYN初次握手的次数,不包括SYN的重传,但是连接建立失败也会导致这个指标上升 |
inspector_pod_tcppassiveopens |
单个Pod内TCP完成握手并成功分配Sock的累积值,通常可以理解为成功新建连接的数量 |
inspector_pod_tcpretranssegs |
单个Pod内重传的总报文数,这里已经跟据TSO进行了提前的分片计算 |
inspector_pod_tcpestabresets |
单个Pod内异常关闭TCP连接的次数,这里仅仅从结果层面统计 |
inspector_pod_tcpoutrsts |
单个Pod内TCP发送的Reset报文次数 |
inspector_pod_conntrackinvalid |
在CT创建过程中由于各种原因无法建立,但是报文并未被丢弃的次数 |
inspector_pod_conntrackdrop |
由于CT创建过程中无法建立而丢弃报文的次数 |
针对出现了类似Nginx响应慢的情况时,例如虽然出现了超时,但是Nginx的request_time很短的情况,您可以关注以下指标的变化:
指标名称 |
说明 |
inspector_pod_tcpsummarytcpestablishedconn |
当前存在的ESTABLISHED状态的TCP连接数量 |
inspector_pod_tcpsummarytcptimewaitconn |
当前存在的TIMEWAIT状态的TCP连接数量 |
inspector_pod_tcpsummarytcptxqueue |
当前处ESTABLISHED状态的TCP连接的发送队列中存在的数据包的Bytes总数 |
inspector_pod_tcpsummarytcprxqueue |
当前处ESTABLISHED状态的TCP连接的接收队列中存在的数据包的Bytes总数 |
inspector_pod_tcpexttcpretransfail |
重传报文返回除了EBUSY之外的报错时计数,说明重传无法正常完成 |
3) TCP Reset报文相关问题
TCP Reset报文是TCP协议中用于对非预期情况做响应的动作,通常会对用户程序造成以下的影响:
● connection reset by peer报错,通常出现在nginx等C lib依赖的业务中。
● Broken pipe报错,通常出现在Java或Python等封装TCP连接的业务中。
云原生网络环境中,出现Reset报文的常见原因有很多,这一类现象的出现也很难快速排查,以下列举了几种常见的Reset报文成因:
● 服务端的异常,导致无法正常提供服务,例如配置的TCP使用的内存不足等原因,这一类情况通常会主动发送Reset。
● 在使用Service或负载均衡时,由于endpoint或者Conntrack等有状态的机制出现异常而转发到了非预期的后端。
● 安全原因导致的连接释放。
● 在NAT环境,高并发等场景下出现防止回绕序号(Protection Against Wrapped Sequence Numbers,以下简称PAWS)或者序号回绕现象。
● 使用TCP Keepalive进行连接保持,但是长时间没有进行正常业务通信的情况。
为了快速区分以上不同的根因,您可以收集一些基本的信息指标:
● 梳理Reset报文产生时网络的客户端和服务端之间的拓扑结构。
● 关注以下指标的变化:
指标名称 |
说明 |
inspector_pod_tcpexttcpabortontimeout |
由于keepalive/window probe/重传的调用超过上限发送Reset时会更新此计数 |
inspector_pod_tcpexttcpabortonlinger |
TCP的Linger2选项开启后,快速回收处于FIN_WAIT2的连接时发送Reset的次数 |
inspector_pod_tcpexttcpabortonclose |
状态机之外的原因关闭TCP连接时,仍有数据没有读取而发送Reset报文,则会进行指标计数 |
inspector_pod_tcpexttcpabortonmemory |
在需要分配tw_sock/tcp_sock等逻辑中有由于tcp_check_oom出发内存不足而发送Reset结束连接的次数 |
inspector_pod_tcpexttcpabortondata* |
由于Linger/Linger2选项开启而通过Reset进行连接的快速回收时发送Reset的计数 |
inspector_pod_tcpexttcpackskippedsynrecv |
在SYN_RECV状态的Sock不回复ACK的次数 |
inspector_pod_tcpexttcpackskippedpaws |
由于PAWS机制触发校正,但是OOW限速限制了ACK报文发送的次数 |
inspector_pod_tcpestabresets |
单个Pod内异常关闭TCP连接的次数,这里仅仅从结果层面统计 |
inspector_pod_tcpoutrsts |
单个Pod内TCP发送的Reset报文次数 |
如果Reset偶发的现象按照一定的频率您可以参考上文打开ACK Net Exporter的监控事件功能,采集对应的事件信息:
事件 |
事件信息 |
TCP_SEND_RST |
发送了TCP Reset报文,排除下方两个常见场景,其余发送Reset报文均会出发此事件 |
TCP_SEND_RST_NOSock |
由于本地没有Sock而发送了TCP Reset报文 |
TCP_SEND_RST_ACTIVE |
由于资源,用户态关闭等原因主动发送了TCP Reset报文 |
TCP_RCV_RST_SYN |
在握手阶段收到了Reset报文 |
TCP_RCV_RST_ESTAB |
在连接已建立状态下收到Reset报文 |
TCP_RCV_RST_TW |
在挥手阶段收到了Reset报文 |
4) 偶发网络延迟抖动相关问题
网络偶发延迟抖动类问题是云原生环境中最为常见和最难以定位的一类问题,成因的现象极多,同时出现延迟可能会导致上述的三种问题的产生,容器网络场景下,节点内部出现的网络延迟通常包含以下几种原因:
● 出现某个RT调度器管理的实时进程执行时间过久,导致用户业务进程或网络内核线程出现排队较长或者处理较慢的现象。
● 用户进程本身出现了偶发外部调用耗时久的现象,如云盘响应慢,RDS的RTT偶发增加等常见原因,导致请求处理较慢。
● 节点本身配置问题导致节点内不同CPU/不同NUMA Node之间负载不均,高负载的系统出现卡顿。
● 内核的有状态机制引发的延迟,如Conntrack的Confirm操作,大量Orphan Socket影响了正常的Socket查找等。
面对此类问题,尽管表现为网络问题,其最终的原因通常是由于OS的其他原因导致,您可以关注以下指标来缩小排查的范围:
指标名称 |
说明 |
inspector_node_netsoftirqshed |
从软中断发起到ksoftirqd进程开始执行之间的耗时分布 |
inspector_node_netsoftirq |
从ksoftirqd开始执行软中断内容到执行完成进入offcpu状态的耗时分布 |
inspector_pod_ioioreadsyscall |
进程进行文件系统读操作,如read,pread的次数 |
inspector_pod_ioiowritesyscall |
进程进行文件系统写操作,如write,pwrite的次数 |
inspector_pod_ioioreadbytes |
进程从文件系统,通常是块设备中读取的Bytes数量 |
inspector_pod_ioiowritebyres |
进程向文件系统进行写入的Bytes数量 |
inspector_node_virtsendcmdlat |
网卡操作虚拟化调用的耗时分布 |
inspector_pod_tcpexttcptimeouts |
CA状态并未进入recovery/loss/disorder时触发,当SYN报文未得到回复时进行重传会计数 |
inspector_pod_tcpsummarytcpestablishedconn |
当前存在的ESTABLISHED状态的TCP连接数量 |
inspector_pod_tcpsummarytcptimewaitconn |
当前存在的TIMEWAIT状态的TCP连接数量 |
inspector_pod_tcpsummarytcptxqueue |
当前处ESTABLISHED状态的TCP连接的发送队列中存在的数据包的Bytes总数 |
inspector_pod_tcpsummarytcprxqueue |
当前处ESTABLISHED状态的TCP连接的接收队列中存在的数据包的Bytes总数 |
inspector_pod_softnetprocessed |
单个Pod内所有CPU处理的从网卡放入CPU的Backlog的报文数量 |
inspector_pod_softnettimesqueeze |
单个Pod内所有CPU处理的单次收包没有全部获取或者出现超时的次数 |