ACK Net Exporter是部署在集群内部的网络可观测性增强组件,能够提供容器网络相关的详尽监控数据,帮助您快速发现和定位网络问题。本文介绍Kubernetes使用ACK Net Exporter的最佳实践,帮助您快速上手并解决实际问题。
前提条件
已创建ACK托管版集群。详细信息,请参见创建ACK托管集群。
背景信息
ACK Net Exporter通过守护进程Pod的方式运行在节点上,借助eBPF技术,采集节点的信息并聚合到具体的Pod中,提供标准化的接口,实现对网络高阶信息的观测。ACK Net Exporter的核心架构如下图所示。
安装与配置ACK Net Exporter组件
安装ACK Net Exporter组件
登录容器服务管理控制台,在左侧导航栏选择 。
在应用市场页面搜索ack-net-exporter,然后单击搜索到的组件。
在ack-net-exporter组件页面右上角单击一键部署。
在基本信息配置向导中选择需要部署组件的集群,命名空间,然后单击下一步。
在参数配置配置向导中设置参数,然后单击确定。
参数
描述
默认值
name
ACK Net Exporter组件的名称。
ack-net-exporter-default
namespace
ACK Net Exporter组件的命名空间。
kube-system
config.enableEventServer
是否开启事件追踪服务。取值:
false:不开启事件追踪服务。
true:开启事件追踪服务。
false
config.enableMetricServer
是否开启指标采集服务。取值:
false:不开启指标采集服务。
true:开启指标采集服务。
true
config.remoteLokiAddress
推送事件的远端Grafana Loki服务地址
默认为空。
config.metricLabelVerbose
是否开启指标的详情功能。取值:
false:不开启指标的详情功能。
true:开启指标的详情功能。开启后会额外将Pod的IP以及重要的标签信息作为指标的标签信息。
false
config.metricServerPort
指标服务的端口,提供HTTP服务。
9102
config.eventServerPort
事件服务的端口,提供GRPC Stream的事件流服务。
19102
config.metricProbes
需要开启的指标探针。详细信息,请参见下文ACK Net Exporter指标列表。
默认为空,不配置任何指标探针的情况下,会默认启动必需探针。
config.eventProbes
需要开启的事件探针。详细信息,请参见下文ACK Net Exporter事件详解。
默认为空,不配置任何指标探针的情况下,会默认启动必需探针。
配置ACK Net Exporter组件
您可以执行如下命令,通过ConfigMap方式配置ACK Net Exporter组件。
kubectl edit cm inspector-config -n kube-system
您也可以通过控制台配置ACK Net Exporter组件。
登录容器服务管理控制台,在左侧导航栏单击集群。
在集群列表页面,单击目标集群名称,然后在左侧导航栏,选择
。在配置项页面,设置命名空间为kube-system,然后搜索kubeskoop-config,单击kubeskoop-config右侧操作列下的编辑。
在编辑面板配置参数,然后单击确定。
ACK Net Exporter支持的配置项及其含义如下:
参数
描述
默认值
debugmode
是否开启调试模式。取值:
false:不开启调试模式。
true:开启调试模式。开启后,支持DEBUG级别的日志,调试接口,Go pprof和gops诊断工具。
false
event_config.loki_enable
是否开启事件向远端Grafana Loki服务推送的功能。详细信息,请参见下文使用Grafana Loki收集监控事件并可视化。取值:
false:不开启事件向远端Grafana Loki服务推送的功能。
true:开启事件向远端Grafana Loki服务推送的功能。
false
event_config.loki_address
远端Grafana Loki服务的地址,默认会自动发现相同命名空间下的名为grafana-loki的服务。
默认为空。
event_config.probes
需要开启的事件探针。详细信息,请参见下文ACK Net Exporter事件详解。
默认为空,不配置任何指标探针的情况下,会默认启动必需探针。
event_config.port
事件服务的端口,提供GRPC Stream的事件流服务。
19102
metric_config.verbose
是否开启指标的详情功能。取值:
false:不开启指标的详情功能。
true:开启指标的详情功能。开启后会额外将Pod的IP以及重要的标签信息作为指标的标签信息。
false
metric_config.port
指标服务的端口,提供HTTP服务。
9102
metric_config.probes
需要开启的指标探针。详细信息,请参见下文ACK Net Exporter指标列表。
默认为空,不配置任何指标探针的情况下,会默认启动必需探针。
metric_config.interval
指标采集的事件间隔。由于指标采集存在一定性能损耗,因此ACK Net Exporter会定期采集后缓存在内存中。
5
在v0.2.3版本及更新版本的ACK Net Exporter中,已经支持了配置的热更新,如果您使用较早期的版本,在修改配置之后需要触发ACK Net Exporter所有容器的重建来使配置变更生效。
ACK Net Exporter使用说明
在Alinux以外的操作系统上使用ACK Net Exporter
ACK Net Exporter的部分核心功能依赖于eBPF程序进行采集。为了满足使用不同操作系统内核的需求,ACK Net Exporter采用CO-RE的方式实现eBPF程序的分发。在启动过程中,依赖于与操作系统内核关联的BTF文件(操作系统内核的调试信息元数据的文件)进行加载。如果没有适配的BTF文件,这部分功能将不可用。在高版本的操作系统中,一般都会内置BTF文件的支持。关于操作系统的更多信息,请参见BPF Type Format。
目前我们为在Alinux2和Alinux3节点上运行的ACK Net Exporter提供了适配服务。该功能需要满足以下条件:
操作系统内核为4.10以上版本。
至少安装了以下任意一项文件。
已安装对应的kernel-debuginfo文件(内核调试信息的数据文件)。
具有携带debug信息的vmlinux文件(操作系统内核编译后且未经过压缩的原始文件)。
已安装操作系统提供的对应的BTF文件。
更新ACK Net Exporter为0.2.9或以上版本,并在安装时将config.enableLegacyVersion设置为false。
在符合上述条件的情况下,您可以按照以下步骤使用ACK Net Exporter提供的高级功能:
将具备BTF信息的文件放在节点的/boot/路径下。
如果您安装了完整的vmlinux文件,您可以将vmlinux文件放置到操作系统的/boot/路径中。
如果您安装了kernel-debuginfo包,在安装了kernel-debuginfo包之后,您可以在节点上/usr/lib/debug/lib/modules/路径中根据对应的内核版本查找到带有调试信息的vmlinux文件,然后将其复制到/boot/路径中。
执行以下命令,验证是否已经具备有效的BTF信息和是否支持ACK Net Exporter的运行。
# 您可以使用docker/podman/ctr等类似命令运行测试 nerdctl run -it -v /boot:/boot registry.cn-hangzhou.aliyuncs.com/acs/btfhack:latest -- btfhack discover
如果以上测试命令成功输出了您准备好的BTF信息文件路径,则已经完成了配置,您可以触发ACK Net Exporter的重建,等待一段时间后即可查看到更多指标和事件。
ACK Net Exporter的监控指标及格式
ACK Net Exporter提供适配Prometheus格式的监控数据,在安装完ACK Net Exporter后,您可以通过访问任意一个ACK Net Exporter的Pod实例的服务端口获取到全部的指标信息:
如果您通过应用市场安装了ACK Net Exporter,可执行如下命令获取到所有ACK Net Exporter实例。
kubectl get pod -l app=net-exporter -n kube-system -o wide
预期输出:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES anp-*** 1/1 Running 0 32s 10.1.XX.XX cn-*** <none> <none>
执行如下命令,获取指标信息,需要将命令中的
10.1.XX.XX
替换为上一步中获取到的ACK Net Exporter实例的地址。curl http://<10.1.XX.XX>:9102/metrics
ACK Net Exporter提供的监控指标数据格式如下:
inspector_pod_udprcvbuferrors{namespace="elastic-system",netns="ns402653****",node="iZbp179u0bgzhofjupc****",pod="elastic-operator-0"} 0 1654487977826
不同字段代表的含义如下:
inspector_pod_udprcvbuferrors
表示这是一个由ACK Net Exporter提供的指标,它的作用范围是Pod(指标作用范围包含Pod与Node,代表指标表征的数据是Pod或者Node级别有效),它的名称是udprcvbuferrors
,表示单个Pod内出现的UDP报文因为收包队列满而导致的错误。namespace
、pod
、node
和netns
均为指标可用的Label,您可以使用PromQL对指标的Label进行过滤。其中namespace
、pod
与Kubernetes中的含义一致,node
是您的节点的主机名,一般默认为/etc/hostname文件中保存的主机名,netns
是某个Pod的容器所在的Linux网络命名空间的ID,用于标记单个容器独立的网络空间。指标后方的
0
与1654487977826
分别代表指标的有效数据和指标产生的时间,时间是UNIX时间戳的格式。
ACK Net Exporter的监控事件及格式
ACK Net Exporter支持采集节点上发生的网络相关的异常事件。根据长期处理网络问题中的经验,我们归纳了几种常见的网络疑难问题。这些问题往往在集群中难以无法复现,以偶然发生的方式干扰正常的业务,缺乏有效的定位手段,其中部分如下:
网络数据报文被丢弃引发的连接失败,响应超时等问题。
网络数据处理耗时久引发的偶发性能问题。
TCP、conntrack等状态机制异常引发的业务异常问题。
针对无法快速复现和难以获取现场的网络问题,ACK Net Exporter提供了基于eBPF的操作系统内核上下文观测能力。在问题发生的现场捕获操作系统的实时状态,并输出事件日志。关于ACK Net Exporter支持的事件和相关的探针信息,请参见ACK Net Exporter事件详解。
在事件日志的信息中,可以查看到事件现场的相关信息.。以tcp_reset探针为例,当出现Pod收到了一个访问未知端口的正常报文时,ACK Net Exporter会捕获以下事件信息。
type=TCPRESET_NOSOCK pod=storage-monitor-5775dfdc77-fj767 namespace=kube-system protocol=TCP saddr=100.103.42.233 sport=443 daddr=10.1.17.188 dport=33488
type=TCPRESET_NOSOCK
:出现了一次TCPRESET_NOSOCK类型的事件。这属于tcpreset探针捕获的一种事件,表明有访问未知端口的报文被本地发送RST报文拒绝,拒绝的原因是没有根据报文找到相应的Socket。通常在NAT失效后会发生这个事件,例如IPVS定时器超时等原因发生后。pod/namespace
:ACK Net Exporter根据发送报文的网络命名空间,系统在匹配IP地址和网络设备序号后关联给事件的Pod元信息。saddr/sport/daddr/dport
:ACK Net Exporter在内核获取到的异常报文的信息。随着事件的不同获取的异常报文信息也会有差异,例如net_softirq探针的事件信息中没有IP地址,取而代之的是中断发生的CPU序号,产生的延迟时长等。
对于需要有效的操作系统内核堆栈信息的事件,ACK Net Exporter会捕获事件发生时在操作系统内核中的堆栈上下文信息。例如以下事件信息。
type=PACKETLOSS pod=hostNetwork namespace=hostNetwork protocol=TCP saddr=10.1.17.172 sport=6443 daddr=10.1.17.176 dport=43018 stacktrace:skb_release_data+0xA3 __kfree_skb+0xE tcp_recvmsg+0x61D inet_recvmsg+0x58 sock_read_iter+0x92 new_sync_read+0xE8 vfs_read+0x89 ksys_read+0x5A
ACK Net Exporter支持多种事件查看方式,详细介绍,请参见下文的从ACK Net Exporter收集监控数据。
从ACK Net Exporter收集监控数据
场景一:使用Prometheus或Grafana收集监控数据并可视化
ACK Net Exporter支持输出到Prometheus Server实例,如果您使用自行搭建的Prometheus Server,您可以通过添加一组scrape_config
的方式来使您的Prometheus Server实例主动抓取ACK Net Exporter的数据,类似如下配置:
# 只包含一个要抓取的端点的抓取配置。
scrape_configs:
# "net-exporter_sample"将作为“job=<job_name>”标签添加到从此配置中抓取的任何时间序列中。
- job_name: "net-exporter_sample"
static_configs:
- targets: ["{kubernetes pod ip}:9102"]
如果您的Prometheus Server实例运行在ACK集群中,您也可以通过Prometheus服务发现功能自动获取到所有正常提供服务的ACK Net Exporter实例,您可以通过在Prometheus Server的配置中添加以下内容:
apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus-server-conf
labels:
name: prometheus-server-conf
namespace: kube-system
data:
prometheus.yml: |-
# 将以下内容添加到Promethes Server配置中。
- job_name: 'net-exporter'
kubernetes_sd_configs:
- role: endpoints
relabel_configs:
- source_labels: [__meta_kubernetes_endpoints_name]
regex: 'net-exporter'
action: keep
- job_name: 'kubernetes-pods'
kubernetes_sd_configs:
- role: pod
relabel_configs:
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
action: keep
regex: true
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
action: replace
target_label: __metrics_path__
regex: (.+)
- source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]
action: replace
regex: ([^:]+)(?::\d+)?;(\d+)
replacement: $1:$2
target_label: __address__
- action: labelmap
regex: __meta_kubernetes_pod_label_(.+)
- source_labels: [__meta_kubernetes_namespace]
action: replace
target_label: kubernetes_namespace
- source_labels: [__meta_kubernetes_pod_name]
action: replace
target_label: kubernetes_pod_name
添加完成后,可以在Prometheus Server的
界面看到已经生效的ACK Net Exporter实例,或者在Prometheus Server的Graph界面的搜索栏中输入inspector,即可看到自动补全的ACK Net Exporter指标。您可以通过配置Grafana将Prometheus采集到的数据进行可视化操作:
打开Grafana页面,在左侧导航栏中选择 。
在New dashboard页面单击Add an empty panel。
进入Edit Panel页面,在下方Data source中输入Prometheus,然后选择已经完成Prometheus Server的接口地址。
单击Metric browser, 然后输入inspector,Grafana会自动补全ACK Net Exporter所有就绪的Metric,单击右上角Save,在弹出框中单击Save,然后会出现可视化的数据,效果如下:
对于使用Grafana进行可视化图形显示的配置,可以参照上述的指标格式,对指标的显示格式进行调整,例如
inspector_pod_tcppassiveopens
指标,表征系统自开机或者Pod所属的容器创建后,归属于这个网络命名空间内的所有TCP连接由于接受客户端的握手请求创建的Socket总数变化,通常可以认为是表征TCP总连接数量的增长,为了更加直观的反应增长的速率变化,可以参考以下配置:// 使用PromQL提供的rate()方法配置Metrics。 rate(inspector_pod_tcppassiveopens[1m]) // 使用net-exporter提供的标签来配置Legend,直观显示Metrics。 {{namespace}}/{{pod}}/{{node}}
场景二:使用应用实时监控服务ARMS收集监控数据并可视化
ACK Net Exporter支持通过应用实时监控服务ARMS进行数据可视化操作,步骤如下:
配置ACK Net Exporter自定义指标。
登录ARMS控制台,在左侧导航栏中选择 。
登录ARMS控制台。
在页面顶部,选择容器服务ACK集群所在的地域
在左侧导航栏选择 ,进入可观测监控 Prometheus 版的实例列表页面。
- 单击目标Prometheus实例名称,进入集成中心页面。
在实例列表页面,单击目标实例名称(一般是集群名称)进入对应实例页面。
在左侧导航栏中单击服务发现,然后单击Targets页签,在页面下方的kubernetes-pods选项页可以看到ACK Net Exporter的指标已经配置成功。
如果没有找到相关的Pod,则需要您在配置页签下手动开启默认服务发现的选项。
在左侧导航栏中单击大盘列表,单击目标大盘进入Grafana,然后单击添加Panel,选择Graph类型,在Data source中选择开启ACK Net Exporter的集群相关的数据源。
单击Metric browser, 然后输入inspector,Grafana会自动补全ACK Net Exporter所有就绪的Metric,单击右上角Save,在弹出框中单击Save,然后会出现可视化的数据,效果如下:
场景三:使用Grafana Loki收集监控事件并可视化
ACK Net Exporter采集的异常事件类型的数据,支持通过预先配置的Grafana Loki服务,由ACK Net Exporter向Loki进行实时推送,从而达到将分布式的异常事件进行集中式的串型查看分析,使用ACK Net Exporter配合Grafana Loki的服务步骤如下:
- 说明
服务需要位于ACK Net Exporter的Pod可以访问的网络中,ACK Net Exporter会主动向已经配置并就绪的Grafana Loki服务推送事件日志信息。
在安装ACK Net Exporter的配置页面中,将enableEventServer配置为true,将lokiServerAddress配置为Grafana Loki服务的地址。您可以配置Grafana Loki服务的IP地址,也可以配置Grafana Loki 服务的域名。
执行以下命令,访问Grafana Loki的服务地址来检验Grafana Loki服务是否已就绪。
curl http://[Grafana Loki实例的地址]:3100/ready
待Grafana Loki服务就绪后,添加Grafana Loki作为Grafana的数据源。
打开Grafana页面,在左侧导航栏中选择
,输入Grafana Loki的接口地址,单击Save&test。在左侧导航栏单击Explore,在页面顶部设置数据源为Loki,查看输出到Grafana Loki的事件信息。
您可以在Label filters下拉框中选择过滤某个Node的事件,也可以在Line containers中输入事件相关的信息来查看具体的事件。
您可以单击页面顶部的Add to dashboard,将配置好的事件Panel添加到大盘中。
ACK Net Exporter提供的事件根据事件的类型携带了不同的信息,单击事件的详情后,可以查看到详细的事件发生时的信息。
Grafana Loki服务支持通过LogQL语法查询信息,详细介绍,请参见LogQL。
场景四:使用ACK Net Exporter Cli工具收集监控事件
ACK Net Exporter Cli(以下简称inspector-cli)是ACK容器网络团队基于ACK Net Exporter既有的能力,提供场景化的问题排查辅助分析,获取即时内核异常事件日志的工具,针对云原生场景设计,帮助用户快速定位常见问题的深层次原因。
您可以通过在本地启动容器的方式运行inspector-cli。
# 启动临时容器用于使用incpector-cli,您可以更换镜像的版本来使用更新版本的特性。
docker run -it --name=inspector-cli --network=host registry.cn-hangzhou.aliyuncs.com/acs/inspector:v0.0.1-12-gff0558c-aliyun
which inspector
# /bin/inspector 是inspector-cli的执行路径,您可以直接在容器中使用inspector-cli。
例如,您可以通过以下方式使用inspector-cli获取到某个节点的ACK Net Exporter捕获的事件。
# 通过‘-e’指定需要获取事件的远端ACK Net Exporter事件服务地址。
inspector watch -e 10.1.16.255
# 以下为结果示例。
INFO TCP_RCV_RST_ESTAB Namespace=kube-system Pod=kube-proxy-worker-tbv5s Node=iZbp1jesgumdx66l8ym8j8Z Netns=4026531993 10.1.16.255:43186 -> 100.100.27.15:3128
...
您也可以选择登录到ACK Net Exporter的inspector容器中排查问题。
# 执行命令时,需要将-n参数指定为net-exporter安装的命名空间,同时执行需要登入的节点上的net-exporter实例。
kubectl exec -it -n kube-system -c inspector net-exporter-2rvfh -- sh
# 通过以下命令可以查看到当前节点上的网络数据面分布情况。
inspector list entity
# 通过以下命令可以监听本地的网络异常事件日志及其信息。
inspector watch -d -v
#{"time":"2023-02-03T09:01:03.402118044Z","level":"INFO","source":"/go/src/net-exporter/cmd/watch.go:63","msg":"TCPRESET_PROCESS","meta":"hostNetwork/hostNetwork node=izbp1dnsn1bwv9oyu2gaupz netns=ns0 ","event":"protocol=TCP saddr=10.1.17.113 sport=6443 daddr=10.1.17.113 dport=44226 state:TCP_OTHER "}
# 通过指定多个远端的ACK Net Exporter实例,也可以观察到不同节点上发生的时间。
inspector watch -s 10.1.17.113 -s 10.1.18.14 -d -v
如何使用ACK Net Exporter定位容器网络常见偶发疑难问题
以下内容提供了针对部分云原生典型问题的排查指南,结合ACK Net Exporter,帮助您快速获取与问题有关的信息。
DNS超时相关问题
在云原生环境中,DNS服务超时问题会导致服务的访问失败,出现DNS访问超时的常见原因有:
DNS服务响应的速度较慢,无法在用户程序的超时时间到达前完成一次DNS查询。
由于发送端的问题,没有顺利或者及时发送DNS Query报文。
服务端及时响应了报文,但是由于发送端本身的内存不足等问题出现了丢包。
您可以借助以下几个指标来帮助排查偶发的DNS超时问题:
指标名称 | 说明 |
inspector_pod_udpsndbuferrors | UDP协议通过网络层方法发送时出现报错的次数 |
inspector_pod_udpincsumerrors | UDP接收报文时出现CSUM校验错误的次数 |
inspector_pod_udpnoports | 网络层调用 |
inspector_pod_udpinerrors | UDP接收报文时出现错误的次数 |
inspector_pod_udpoutdatagrams | UDP协议通过网络层方法成功发送报文的数量 |
inspector_pod_udprcvbuferrors | UDP在将应用层协议数据拷贝到Socket接收队列时由于队列不足导致的报错次数 |
由于云原生环境中很多服务依赖于CoreDNS提供域名解析服务,在出现DNS问题时,如果出现问题的DNS请求与CoreDNS有关,您需要同时观察CoreDNS相关Pod的上述指标的异常情况。
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之外的报错时计数,说明重传无法正常完成 |
在上述指标信息的基础上,根据指标在对应问题时间点的变化,可以缩小排查的范围,如果凭借指标无法定位到问题,您可以提交工单,在发起工单时提供上述的信息,来帮助客服同学快速了解情况,避免无效沟通。
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报文
偶发网络延迟抖动相关问题
网络偶发延迟抖动类问题是云原生环境中最为常见和最难以定位的一类问题,成因的现象极多,同时出现延迟可能会导致上述的三种问题的产生,容器网络场景下,节点内部出现的网络延迟通常包含以下几种原因:
出现某个RT调度器管理的实时进程执行时间过久,导致用户业务进程或网络内核线程出现排队较长或者处理较慢的现象。
用户进程本身出现了偶发外部调用耗时久的现象,如云盘响应慢,RDS的RTT偶发增加等常见原因,导致请求处理较慢。
节点本身配置问题导致节点内不同CPU/不同NUMA Node之间负载不均,高负载的系统出现卡顿。
内核的有状态机制引发的延迟,如Conntrack的Confirm操作,大量Orphan Socket影响了正常的Socket查找等。
面对此类问题,尽管表现为网络问题,其最终的原因通常是由于OS的其他原因导致,您可以关注以下指标来缩小排查的范围:
指标名称 | 说明 |
inspector_pod_netsoftirqshed | 从软中断发起到ksoftirqd进程开始执行之间的耗时分布 |
inspector_pod_netsoftirq | 从ksoftirqd开始执行软中断内容到执行完成进入offcpu状态的耗时分布 |
inspector_pod_ioioreadsyscall | 进程进行文件系统读操作,如read,pread的次数 |
inspector_pod_ioiowritesyscall | 进程进行文件系统写操作,如write,pwrite的次数 |
inspector_pod_ioioreadbytes | 进程从文件系统,通常是块设备中读取的Bytes数量 |
inspector_pod_ioiowritebyres | 进程向文件系统进行写入的Bytes数量 |
inspector_pod_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处理的单次收包没有全部获取或者出现超时的次数 |
客户案例分析
以下为部分容器网络客户借助ACK Net Exporter进行疑难问题排查分析的案例,您可以比对现象进行参考。
案例一:某客户偶发DNS Timeout问题
客户现象
客户A发起工单,现象为有偶发的DNS解析超时,用户业务采用PHP,DNS服务为配置CoreDNS。
排查过程
根据客户描述,与客户沟通后获取客户监控中的DNS相关数据。
分析客户报错时间点内数据,发现以下问题。
报错时间内
inspector_pod_udpnoports
增加1,指标整体较小。inspector_pod_packetloss
中出现了符号__udp4_lib_rcv
的丢包加1,这个符号的丢包数变化较少。
客户反馈配置的DNS地址为公网某服务商地址,结合监控信息,判断客户报错根因为DNS请求返回较慢,用户态超时返回后,DNS回包到达。
案例二:某客户Java应用偶发连接失败问题
客户现象
客户B发起工单,现象为出现偶发的Tomcat不可用,每次出现持续时间约为5~10s。
排查过程
经过日志分析,确认现象发生时,客户的Java Runtime正在进行GC操作。
ACK Net Exporter监控部署后发现客户在问题的时间点
inspector_pod_tcpextlistendrops
指标有明显的上升。经过分析后得出结论,客户的Java Runtime进行GC操作时,处理请求的速度变慢,导致请求的释放变慢,但是请求的新建并没有被限制,因此产生了大量的链接,将Listen Socket的Backlog打满后产生溢出,导致
inspector_pod_tcpextlistendrops
上升。此问题中,客户的连接堆积持续时间短,且本身处理能力没有问题,因此建议客户调整Tomcat相关参数后,解决了客户问题。
案例三:某客户偶发网络延迟抖动问题
客户现象
客户C发起工单,现象为客户应用于Redis之间的请求出现了偶发的RTT增高导致业务超时,但是无法复现。
排查过程
经过日志分析,客户出现了偶发的Redis请求超过300ms的总响应时间的情况。
ACK Net Exporter部署后,从监控中发现了
inspector_node_virtsendcmdlat
指标在问题发生时有增长,增长的le(Prometheus监控中的Level)为18与15。经过换算得知此时出现过两次延迟较高的虚拟化调用,其中le为15的产生了36ms以上的延迟,而le为18的产生了200ms以上的延迟。由于内核的虚拟化调用执行时会占据CPU,无法被抢占,因此客户的偶发延迟是由于Pod的批量增删过程中有一些虚拟化调用执行过久导致。
案例四:某客户Ingress Nginx偶发健康检查失败问题
客户现象
客户D发起工单,现象为客户的Ingress机器有偶发的健康检查失败并伴随着业务请求失败的问题。
排查过程
ACK Net Exporter部署监控后发现客户出现问题是多个指标有异常的变化。
inspector_pod_tcpsummarytcprxqueue
与inspector_pod_tcpsummarytcptxqueue
均出现了上升。inspector_pod_tcpexttcptimeouts
出现了上升。inspector_pod_tcpsummarytcptimewaitconn
下降,inspector_pod_tcpsummarytcpestablishedconn
上升。
经过分析后确认在问题发生的时间点,内核工作正常,连接的建立正常,但是用户进程的运行出现了异常,包括处理收取Socket中的报文以及实际执行报文的发送操作,推测此时用户进程存在调度问题或者限制问题。
建议用户查看Cgroup的监控后发现客户在问题时间点出现了CPU Throttled现象,证明此时出现了偶发的用户进程由于Cgroup原因无法得到调度的现象。
按照文档CPU Burst性能优化策略,为Ingress配置CPU Burst功能后,解决了这一类问题。
相关内容
ACK Net Exporter指标列表
在ACK Net Exporter更新过程中指标会有新增或变更,详细信息请参考应用市场组件页面的说明。除net_softirq/virtcmdlat等与Pod本身无关的逻辑外,所有的指标与事件均提供Pod粒度的详细信息。
指标名称 | 描述 | 探针名称 |
inspector_pod_netdevrxbytes | 网卡设备接收的总字节数。 | netdev |
inspector_pod_netdevtxbytes | 网卡设备发送的总字节数。 | netdev |
inspector_pod_netdevtxerrors | 网卡设备出现发送错误的次数。 | netdev |
inspector_pod_netdevrxerrors | 网卡设备出现接受错误的次数。 | netdev |
inspector_pod_netdevtxdropped | 网卡发送错误并产生丢弃的次数。 | netdev |
inspector_pod_netdevrxdropped | 网卡接收错误并产生丢弃的次数。 | netdev |
inspector_pod_netdevtxpackets | 网卡发送成功的报文数。 | netdev |
inspector_pod_netdevrxpackets | 网卡接受成功的报文数。 | netdev |
inspector_pod_softnetprocessed | 单个Pod内所有CPU处理的从网卡放入CPU的backlog的报文数量。 | softnet |
inspector_pod_softnetdropped | 单个Pod内所有CPU处理的从网卡放入CPU的backlog失败并丢弃报文数量。 | softnet |
inspector_pod_softnettimesqueeze | 单个Pod内所有CPU处理的单次收包没有全部获取或者出现超时的次数。 | softnet |
inspector_pod_tcpactiveopens | 单个Pod内TCP成功发起SYN初次握手的次数,不包括SYN的重传,但是连接建立失败也会导致这个指标上升。 | tcp |
inspector_pod_tcppassiveopens | 单个Pod内TCP完成握手并成功分配sock的累积值,通常可以理解为成功新建连接的数量。 | tcp |
inspector_pod_tcpretranssegs | 单个Pod内重传的总报文数,这里已经跟据tso进行了提前的分片计算。 | tcp |
inspector_pod_tcpestabresets | 单个Pod内异常关闭TCP连接的次数,这里仅仅从结果层面统计。 | tcp |
inspector_pod_tcpoutrsts | 单个Pod内TCP发送的reset报文次数。 | tcp |
inspector_pod_tcpcurrestab | 单个Pod内TCP当前存在的活跃连接数。 | tcp |
inspector_pod_tcpexttcpabortontimeout | 由于keepalive/window probe/重传的调用超过上限发送reset时会更新此计数。 | tcpext |
inspector_pod_tcpexttcpabortonlinger | tcp的linger2选项开启后,快速回收处于FIN_WAIT2的连接时发送reset的次数。 | tcpext |
inspector_pod_tcpexttcpabortonclose | 状态机之外的原因关闭TCP连接时,仍有数据没有读取而发送reset报文,则会进行指标计数。 | tcpext |
inspector_pod_tcpexttcpabortonmemory | 在需要分配tw_sock/tcp_sock等逻辑中有由于tcp_check_oom出发内存不足而发送reset结束连接的次数。 | tcpext |
inspector_pod_tcpexttcpabortondata* | 由于linger/linger2选项开启而通过reset进行连接的快速回收时发送reset的计数。 | tcpext |
inspector_pod_tcpextlistenoverflows | 当LISTEN状态的sock接受连接时出现半连接队列溢出时会计数。 | tcpext |
inspector_pod_tcpextlistendrops | LISTEN状态的sock创建SYN_RECV状态的sock失败时会计数。 | tcpext |
inspector_pod_tcpexttcpackskippedsynrecv | 在SYN_RECV状态的sock不回复ACK的次数。 | tcpext |
inspector_pod_tcpexttcpackskippedpaws | 由于paws机制触发校正,但是oow限速限制了ACK报文发送的次数。 | tcpext |
inspector_pod_tcpexttcpackskippedseq | 由于序号在窗口外触发较正,但是被oow限速限制了ACK报文发送的次数。 | tcpext |
inspector_pod_tcpexttcpackskippedchallenge | 在需要发送challenge ack(通常用于确认reset报文)时被oow限速的次数。 | tcpext |
inspector_pod_tcpexttcpackskippedtimewait | 在fin_wait_2状态下,对于oow报文发送ack,但是因为限速而忽略发送的次数。 | tcpext |
inspector_pod_tcpexttcpackskippedfinwait2 | 在fin_wait_2状态下,对于oow报文发送ack,但是因为限速而忽略发送的次数。 | tcpext |
inspector_pod_tcpextpawsestabrejected* | TCP入方向的报文因为PAWS防回绕机制被丢弃的次数。 | tcpext |
inspector_pod_tcpexttcprcvqdrop | 当TCP的recv队列出现堆积,并且无法正常分配到内存时,会进行这项计数。 | tcpext |
inspector_pod_tcpexttcpretransfail | 重传报文返回除了EBUSY之外的报错时计数,说明重传无法正常完成。 | tcpext |
inspector_pod_tcpexttcpsynretrans | 重传的SYN报文次数。 | tcpext |
inspector_pod_tcpexttcpfastretrans | CA状态部位loss时进行的重传均会进行计数。 | tcpext |
inspector_pod_tcpexttcptimeouts | CA状态并未进入recovery/loss/disorder时触发,当SYN报文未得到回复时进行重传会计数。 | tcpext |
inspector_pod_tcpsummarytcpestablishedconn | 当前存在的ESTABLISHED状态的TCP连接数量。 | tcpsummary |
inspector_pod_tcpsummarytcptimewaitconn | 当前存在的TIMEWAIT状态的TCP连接数量。 | tcpsummary |
inspector_pod_tcpsummarytcptxqueue | 当前处ESTABLISHED状态的TCP连接的发送队列中存在的数据包的bytes总数。 | tcpsummary |
inspector_pod_tcpsummarytcprxqueue | 当前处ESTABLISHED状态的TCP连接的接收队列中存在的数据包的bytes总数。 | tcpsummary |
inspector_pod_udpindatagrams | UDP成功接收报文的数量。 | udp |
inspector_pod_udpsndbuferrors | UDP协议通过网络层方法发送时出现报错的次数。 | udp |
inspector_pod_udpincsumerrors | UDP接收报文时出现csum校验错误的次数。 | udp |
inspector_pod_udpignoredmulti | UDP忽略的多播报文的数量。 | udp |
inspector_pod_udpnoports | 网络层调用__udp4_lib_rcv收包时找不到对应端口的socket的次数。 | udp |
inspector_pod_udpinerrors | UDP接收报文时出现错误的次数。 | udp |
inspector_pod_udpoutdatagrams | UDP协议通过网络层方法成功发送报文的数量。 | udp |
inspector_pod_udprcvbuferrors | UDP在将应用层协议数据拷贝到socket接收队列时由于队列不足导致的报错次数。 | udp |
inspector_pod_conntrackentries* | 这个指标表征当前存在的entry的数量。 | conntrack |
inspector_pod_conntrackfound | 成功查找到ct记录的次数。 | conntrack |
inspector_pod_conntrackinsert | 目前不会计数。 | conntrack |
inspector_pod_conntrackinvalid | 在ct创建过程中由于各种原因无法建立,但是报文并未被丢弃的次数。 | conntrack |
inspector_pod_conntrackignore | 由于ct已经建立或者协议不需要维护ct而跳过的次数。 | conntrack |
inspector_pod_conntrackinsertfailed | 目前不会计数。 | conntrack |
inspector_pod_conntrackdrop | 由于ct创建过程中无法建立而丢弃报文的次数。 | conntrack |
inspector_pod_conntrackearlydrop | 目前不会计数。 | conntrack |
inspector_pod_conntracksearchrestart | 查找ct过程中由于查找失败而进行重试的次数。 | conntrack |
inspector_pod_fdopenfd | 单个Pod内所有进程的文件描述符数量之和。 | fd |
inspector_pod_fdopensocket | 单个Pod内socket类型的文件描述符之和。 | fd |
inspector_pod_slabtcpslabobjperslab | TCP slab中单个page所包含的object数量。 | slab |
inspector_pod_slabtcpslabpagesperslab | TCP slab中的总page数量。 | slab |
inspector_pod_slabtcpslabobjactive | TCP slab中活跃状态的object数量。 | slab |
inspector_pod_slabtcpslabobjnum | TCP slab中的object数量。 | slab |
inspector_pod_slabtcpslabobjsize | TCP slab中的object的大小,不同的内核版本会有差异。 | slab |
inspector_pod_ioioreadsyscall | 进程进行文件系统读操作,如read,pread的次数。 | io |
inspector_pod_ioiowritesyscall | 进程进行文件系统写操作,如write,pwrite的次数。 | io |
inspector_pod_ioioreadbytes | 进程从文件系统,通常是块设备中读取的bytes数量。 | io |
inspector_pod_ioiowritebyres | 进程向文件系统进行写入的bytes数量。 | io |
inspector_pod_net_softirq_schedslow100ms | 网络软中断出发后等待调度的时间超过100ms的次数。 | net_softirq |
inspector_pod_net_softirq_excuteslow100ms | 网络软中段执行时间超过100ms的次数。 | net_softirq |
inspector_pod_abnormalloss(inspector_pod_packetloss_abnormal) | 内核丢弃报文,并且丢弃的报文是正常报文,即没有出现报文完整性,校验失败等情况的次数。 | packetloss |
inspector_pod_totalloss(inspector_pod_packetloss_total) | 内核总丢包数量。 | packetloss |
inspector_pod_virtcmdlatency100ms | 网卡操作虚拟化消息通信执行超过100ms的次数。 | virtcmdlat |
inspector_pod_socketlatencyread100ms | 用户程序操作读取网络socket文件中的内容,耗时超过100ms的情况统计。 | socketlatency |
inspector_pod_socketlatencywrite100ms | 用户程序操作写入网络socket文件中后,超过100ms没有产生网络报文的情况统计。 | socketlatency |
kernellatency_rxslow100ms | 操作系统内核在接收网络报文过程中耗时超过100ms的情况统计。 | kernellatency |
kernellatency_txslow100ms | 操作系统内核在发送网络报文过程中耗时超过100ms的情况统计。 | kernellatency |
ACK Net Exporter事件详解
ACK Net Exporter当前最新版本支持实时捕获以下操作系统网络相关的异常事件。
探针名称 | 描述 |
netiftxlat | 探测网络数据包发送时在tc qdisc等待延迟高的事件。 |
packetloss | 操作系统内核丢弃正常的网络数据包的事件。 |
net_softirq | 操作系统软中断内核进程关于NET_RX/NET_TX中断下半部的调度或执行延迟高的事件。 |
socketlatency | Pod中的进程进行socket相关的读写操作的耗时久的事件。 |
kernellatency | 内核在网络层处理报文耗时久的事件。 |
virtcmdlatency | Virtio-net与宿主机通信耗时久的事件。 |
tcpreset | 接收或发出TCP协议中带有RST标记的报文的事件。 |
tcptwrcv | TCP协议在TIMEWAIT状态下收到了报文并处理的事件。 |
推荐使用的Grafana配置文件
如果您使用的是v8.4.0以上版本的Grafana,请单击ACK Net Exporter-0.2.9.json链接获取Grafana配置文件。
如果您使用的是v8.4.0及以下版本的Grafana,请单击ACK Net Exporter-legacy.json链接获取Grafana配置文件。