我的编程空间,编程开发者的网络收藏夹
学习永远不晚

如何排查Kubernetes机器内核问题

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

如何排查Kubernetes机器内核问题

本篇内容主要讲解“如何排查Kubernetes机器内核问题”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何排查Kubernetes机器内核问题”吧!

具体现象

在线上环境中的某个应用出现了接口缓慢的问题!

就凭这个现象,能列出来的原因数不胜数。本篇博客主要叙述一下几次排查以及最后如何确定原因的过程,可能不一定适用于其他集群,就当是提供一个参考吧。排查过程比较冗长,过去太久了,我也不太可能回忆出所有细节,希望大家见谅。

网络拓扑结构

网络请求流入集群时,对于我们集群的结构:

用户请求=> Nginx => Ingress => uwsgi

不要问为什么有了 Ingress 还有 Nginx,这是历史原因,有些工作暂时需要由 Nginx 承担。

初次定位

请求变慢一般马上就会考虑,程序是不是变慢了,所以在发现问题后,首先在 uwsgi  中增加简单的小接口,这个接口是处理快并且马上返回数据,然后定时请求该接口。在运行几天之后,确认到该接口的访问速度也很慢,排除程序中的问题,准备在链路中查找原因。

再次定位 – 简单的全链路数据统计

由于我们的 Nginx 有 2  层,需要针对它们分别确认,看看究竟是哪一层慢了。请求量是比较大的,如果针对每个请求去查看,效率不高,而且有可能掩盖真正原因,所以这个过程采用统计的方式。统计的方式是分别查看两层  Nginx 的日志情况。由于我们已经在 ELK 上接入了日志,ELK 中筛选数据的脚本简单如下:

{ "bool": { "must": [   {     "match_all": {}   },   {     "match_phrase": {       "app_name": {         "query": "xxxx"       }     }   },   {     "match_phrase": {       "path": {         "query": "/app/v1/user/ping"       }     }   },   {     "range": {       "request_time": {         "gte": 1,         "lt": 10       }     }   },   {     "range": {       "@timestamp": {         "gt": "2020-11-09 00:00:00",         "lte": "2020-11-12 00:00:00",         "format": "yyyy-MM-dd HH:mm:ss",         "time_zone": "+08:00"       }     }   } ] } }

数据处理方案

根据 trace_id 可以获取到 Nignx 日志以及 Ingress 日志,通过 ELK 的 API 获得。

# 这个数据结构用来记录统计结果, # [[0, 0.1], 3]表示落在 0~0.1 区间的有 3 条记录 # 因为小数的比较和区间比较麻烦,所以采用整数,这里的 0~35 其实是 0~3.5s 区间 # ingress_cal_map = [ #     [[0, 0.1], 0], #     [[0.1, 0.2], 0], #     [[0.2, 0.3], 0], #     [[0.3, 0.4], 0], #     [[0.4, 0.5], 0], #     [[0.5, 1], 0], # ] ingress_cal_map = [] for x in range(0, 35, 1): ingress_cal_map.append(     [[x, (x+1)], 0] ) nginx_cal_map = copy.deepcopy(ingress_cal_map) nginx_ingress_gap = copy.deepcopy(ingress_cal_map) ingress_upstream_gap = copy.deepcopy(ingress_cal_map)   def trace_statisics(): trace_ids = [] # 这里的 trace_id 是提前查找过,那些响应时间比较久的请求所对应的 trace_id with open(trace_id_file) as f:     data = f.readlines()     for d in data:         trace_ids.append(d.strip())  cnt = 0 for trace_id in trace_ids:     try:         access_data, ingress_data = get_igor_trace(trace_id)     except TypeError as e:         # 继续尝试一次         try:             access_data, ingress_data = get_igor_trace.force_refresh(trace_id)         except TypeError as e:             print("Can't process trace {}: {}".format(trace_id, e))             continue     if access_data['path'] != "/app/v1/user/ping":  # 过滤脏数据         continue     if 'request_time' not in ingress_data:         continue      def get_int_num(data):  # 数据统一做 *10 处理         return int(float(data) * 10)      # 针对每个区间段进行数据统计,可能有点罗嗦和重复,我当时做统计够用了     ingress_req_time = get_int_num(ingress_data['request_time'])     ingress_upstream_time = get_int_num(ingress_data['upstream_response_time'])     for cal in ingress_cal_map:         if ingress_req_time >= cal[0][0] and ingress_req_time < cal[0][1]:             cal[1] += 1             break      nginx_req_time = get_int_num(access_data['request_time'])     for cal in nginx_cal_map:         if nginx_req_time >= cal[0][0] and nginx_req_time < cal[0][1]:             cal[1] += 1             break      gap = nginx_req_time - ingress_req_time     for cal in nginx_ingress_gap:         if gap >= cal[0][0] and gap <= cal[0][1]:             cal[1] += 1             break      gap = ingress_req_time - ingress_upstream_time     for cal in ingress_upstream_gap:         if gap >= cal[0][0] and gap <= cal[0][1]:             cal[1] += 1             break

我分别针对 request_time(Nginx),request_time(Ingress)以及 requet_time(nginx) -  request_time(Ingress)做了统计。

最后的统计结果大概如下:

如何排查Kubernetes机器内核问题

如何排查Kubernetes机器内核问题

如何排查Kubernetes机器内核问题

结果分析

我们总共有约 3000 条数据!

图一:超过半数的请求落在 1 ~ 1.1s 区间,1s ~ 2s 的请求比较均匀,之后越来越少了。

图二:大约 1/4 的请求其实已经在 0.1s 内返回了,但是 1 ~ 1.1s 也有 1/4 的请求落上去了,随后的结果与图一类似。

从图 1 图 2 结合来看,部分请求在 Ingress 侧处理的时间其实比较短的。

图三:比较明显了,2/3 的请求在响应时间方面能够保持一致,1/3 的请求会有 1s 左右的延迟。

小结

从统计结果来看,Nginx => Ingress 以及 Ingress => upstream,都存在不同程度的延迟,超过 1s  的应用,大约有 2/3 的延迟来自 Ingress => upstream,1/3 的延迟来自 Nginx => Ingress。

再深入调查 - 抓包处理

抓包调查主要针对 Ingress =>  uwsgi,由于数据包延迟的情况只是偶发性现象,所以需要抓取所有的数据包再进行过滤&hellip;&hellip;这是一条请求时间较长的数据,本身这个接口返回应该很快。

{ "_source": { "INDEX": "51", "path": "/app/v1/media/", "referer": "", "user_agent": "okhttp/4.8.1", "upstream_connect_time": "1.288", "upstream_response_time": "1.400", "TIMESTAMP": "1605776490465", "request": "POST /app/v1/media/ HTTP/1.0", "status": "200", "proxy_upstream_name": "default-prod-XXX-80", "response_size": "68", "client_ip": "XXXXX", "upstream_addr": "172.32.18.194:6000", "request_size": "1661", "@source": "XXXX", "domain": "XXX", "upstream_status": "200", "@version": "1", "request_time": "1.403", "protocol": "HTTP/1.0", "tags": ["_dateparsefailure"], "@timestamp": "2020-11-19T09:01:29.000Z", "request_method": "POST", "trace_id": "87bad3cf9d184df0:87bad3cf9d184df0:0:1" } }

Ingress 侧数据包

如何排查Kubernetes机器内核问题

uwsgi 侧数据包

如何排查Kubernetes机器内核问题

数据包流转情况

回顾一下 TCP 三次握手:

如何排查Kubernetes机器内核问题

首先从 Ingress 侧查看,连接在 21.585446 开始,22.588023 时,进行了数据包重新发送的操作。

从 Node 侧查看,Node 在 Ingress 数据包发出后不久马上就收到了 syn,也立刻进行了 syn 的返回,但是不知为何 1s 后才出现在  Ingress 处。

如何排查Kubernetes机器内核问题

如何排查Kubernetes机器内核问题

有一点比较令人在意,即便是数据包发生了重传,但是也没有出现丢包的问题,从两台机器数据包的流转来看,此次请求中,大部分的时间是因为数据包的延迟到达造成的,重传只是表面现象,真正的问题是发生了数据包的延迟。

不止是 ACK 数据包发生了延迟

从随机抓包的情况来看,不止是 SYN ACK 发生了重传:

如何排查Kubernetes机器内核问题

有些 FIN ACK 也会,数据包的延迟是有概率的行为!

小结

单单看这个抓包可能只能确认是发生了丢包,但是如果结合 Ingress 与 Nginx 的日志请求来看,如果丢包发生在 TCP 连接阶段,那么在  Ingress 中,我们就可以查看 upstream_connect_time 这个值来大致估计下超时情况。当时是这么整理的记录:

我初步猜测这部分时间主要消耗在了 TCP 连接建立时,因为建立连接的操作在两次 Nginx 转发时都存在,而我们的链路全部使用了短连接,下一步我准备增加  $upstream_connect_time 变量,记录建立连接花费的时间。http://nginx.org/en/docs/http/ ...  .html

后续工作

既然可以了解到 TCP 连接的建立时间比较久,我们可以用它来作为一个衡量指标,我把 wrk  也修改了下,增加了对于连接时间的测量,具体的PR见这里,我们可以利用这一项指标衡量后端的服务情况。

如何排查Kubernetes机器内核问题

寻找大佬,看看是否遇到类似问题

上面的工作前前后后我进行了几次,也没有什么头绪,遂找到公司的其他 Kubernetes 大佬咨询问题,大佬提供了一个思路:

宿主机延迟也高的话,那就暂时排除宿主机到容器这条路径。我们这边此前排查过一个延迟问题, 是由于 Kubernetes 的监控工具定期 cat proc  系统下的 cgroup 统计信息, 但由于 Docker 频繁销毁重建以及内核 cache 机制,使得每次 cat 时间很长占用内核导致网络延迟,  可否排查一下你们的宿主机是否有类似情形? 不一定是 cgroup,其他需要频繁陷入到内核的操作都可能导致延迟很高。

这个跟我们排查的 cgroup 太像了,宿主机上有一些周期性任务,随着执行次数增多,占用的内核资源越来越多,达到一定程度就影响了网络延迟。

大佬们也提供了一个内核检查工具(可以追踪和定位中断或者软中断关闭的时间):https://github.com/bytedance/trace-irqoff

有问题的 Ingress 机器的 latency 特别多,好多都是这样的报错,其他机器没有这个日志:

如何排查Kubernetes机器内核问题

如何排查Kubernetes机器内核问题

而后,我针对机器中的 kubelet 进行了一次追踪,从火焰图中可以确认,大量的时间耗费在了读取内核信息中。

如何排查Kubernetes机器内核问题

其中具体的代码如下:

如何排查Kubernetes机器内核问题

小结

根据大佬所给的方向,基本能够确定问题发生的真正原因:机器上定时任务的执行过多,内核缓存一直增加,导致内核速度变慢了。它一变慢,引发了 TCP  握手时间变长,最后造成用户体验下降。既然发现了问题,解决方案也比较容易搜索到了,增加任务,检查内核是否变慢,慢了的话就清理一次:

sync && echo 3 > /proc/sys/vm/drop_caches

到此,相信大家对“如何排查Kubernetes机器内核问题”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

如何排查Kubernetes机器内核问题

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

kubernetes k8s常用问题如何排查

这篇文章主要介绍了kubernetes k8s常用问题如何排查的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇kubernetes k8s常用问题如何排查文章都会有所收获,下面我们一起来看看吧。Pod 的那些状态
2023-07-02

java内存溢出问题如何排查

Java内存溢出问题的排查可以按照以下步骤进行:1. 观察错误信息:当Java发生内存溢出时,通常会抛出`java.lang.OutOfMemoryError`异常,并伴随有错误堆栈跟踪信息。仔细阅读错误信息,可以发现导致内存溢出的原因和位
2023-09-29

linux异常关机问题如何排查

要排查Linux异常关机问题,可以按照以下步骤进行:1. 检查系统日志:查看/var/log目录下的日志文件,特别是syslog和kern.log文件,看是否有任何异常或错误信息。可以使用命令如下:```sudo tail -n 100 /
2023-08-31

Rainbond云原生平台简化Kubernetes业务问题如何排查

本篇内容主要讲解“Rainbond云原生平台简化Kubernetes业务问题如何排查”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Rainbond云原生平台简化Kubernetes业务问题如何排
2023-07-05

java线上内存溢出问题如何排查

Java线上内存溢出问题的排查步骤如下:1. 查看错误日志:首先检查应用程序的错误日志,查找与内存溢出相关的异常信息。常见的内存溢出异常包括java.lang.OutOfMemoryError和java.lang.OutOfMemoryEr
2023-10-11

linux中如何排查Java问题

小编给大家分享一下linux中如何排查Java问题,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!Linux命令类tail最常用的tail -fgrepawk1 基
2023-06-16

maven依赖问题如何排查

在排查Maven依赖问题时,可以尝试以下几个步骤:1. 检查pom.xml文件:首先检查项目的pom.xml文件,确保依赖项正确地被添加到了标签中,并且没有任何拼写错误或者格式错误。2. 清理本地仓库:有时候Maven本地仓库中的依赖可能损
2023-09-17

mongo慢查询问题如何排查处理

这篇文章主要介绍了mongo慢查询问题如何排查处理的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇mongo慢查询问题如何排查处理文章都会有所收获,下面我们一起来看看吧。一、简单介绍mongo语句查询条件中出现n
2023-06-29

linux内核的安全问题如何解决

要解决Linux内核的安全问题,可以采取以下措施:1. 及时更新:及时更新Linux内核版本,以获取最新的安全补丁和修复程序。2. 强化访问控制:确保只有授权的用户和进程能够访问内核。使用强密码和多因素身份验证来保护内核。3. 配置安全策略
2023-10-18

java线程卡死问题如何排查

java线程卡死问题的排查可以遵循以下步骤:1. 查看线程堆栈:使用jstack命令或者在IDE中查看线程堆栈,定位到卡死的线程。查看线程的状态、持有的锁和调用栈信息,判断是否是由于死锁或者线程阻塞导致的卡死。2. 查看日志:检查应用程序的
2023-08-24

sql运行缓慢问题如何排查

要排查SQL运行缓慢的问题,可以尝试以下几个步骤:1. 检查查询语句:确保查询语句写得正确且优化良好。可以对查询进行优化,例如使用合适的索引、避免使用不必要的连接、减少子查询等。2. 检查索引:确保表中的列上有适当的索引。可以使用数据库的索
2023-10-21

Node.js子线程Crash问题如何排查

这篇文章主要介绍“Node.js子线程Crash问题如何排查”,在日常操作中,相信很多人在Node.js子线程Crash问题如何排查问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Node.js子线程Crash
2023-07-02

tomcat启动时卡住问题如何排查

本篇内容主要讲解“tomcat启动时卡住问题如何排查”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“tomcat启动时卡住问题如何排查”吧!正常项目无法访问(Linux 服务器),启动tomcat
2023-07-05

如何解决Linux内核编译失败的问题

本篇内容主要讲解“如何解决Linux内核编译失败的问题”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何解决Linux内核编译失败的问题”吧!内核常识我们先要了解一点.一个内核有哪些东西.比如我
2023-06-12

Kubernetes中如何使用临时容器进行故障排查

小编给大家分享一下Kubernetes中如何使用临时容器进行故障排查,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!前言容器及其周围的生态系统改变了工程师部署、维护
2023-06-29

编程热搜

目录