腾讯云 K8s 集群每晚21点诡异报错,原因竟是这个“定时炸弹”!

问题描述

最近我们生产环境的几个系统出现了很诡异的现象,每天晚上 21 点之后出现短暂的报错,或者响应超时。

例如,系统 A 在 21 点弹出微信预警,提示接口访问异常。

系统 B 在 21 点弹出钉钉预警,提示网关探测异常。

一开始我们怀疑是数据库、代码、xxl-job 等问题,但是这些想法很快就否决了。

  1. 各系统分别独立部署在腾讯云的 EKS 弹性集群,互不干扰。
  2. 各系统使用的数据库和 xxljob 都是分开的。
  3. 我们通过回退代码版本检查,也排除了这些系统近期的代码更新问题。

原因分析

经过时间线整理,各系统发生故障的时间点基本是同时触发的,如下。

时间范围 系统A 微信预警 系统B 钉钉预警 其他系统
2023-03-15 20:58-21:00 20:59:13 推送 499 访问异常 21:03 提示 APISIX 探测异常 ...
2023-03-16 21:03-21:06 21:03:04 推送 499 访问异常 21:03 提示 APISIX 探测异常 ...
2023-03-20 21:19-21:23 21:19:34 推送 499 访问异常 21:20 提示 APISIX 探测异常 ...
2023-03-21 21:43-21:45 21:41:50 推送 499 访问异常 21:43 提示 APISIX 探测异常 ...

网络故障?

我们某个系统的网络链路,可以简化如下。

用户访问 -> 腾讯云CLB -> 腾讯云EKS容器(K8s Service)-> Nginx(Pod) -> 业务网关(Pod)-> 业务服务集(Pod)

首先从入口检查,腾讯云负载均衡 CLB 当时的流量监控如下,以 2023-03-21 的监控数据为例,当时 21:42 的入包量为 39 个/秒。

到了 21:44,入包量为 9 个/秒,请求变少了。

往后一层检查 Nginx 的访问日志,得到 4434 条状态码为 499 的报错条数。

bash 复制代码
[root]# egrep "2023-03-21T21:4[0-9]" access.log | grep -w 499 | wc -1
4434

499 错误码表示 Nginx 的上游 upstream 服务端响应太慢了,微信(客户端)主动断开了连接,然后推送了相关预警。

我们检查了 Nginx 的上游服务,并没有发现任何报错。

不得不怀疑是不是腾讯云网络近期做了网络调整导致,我们联系了腾讯云团队协助检查。腾讯方的技术团队和我们制定了如下策略:

  1. 腾讯方负责监控容器、网络问题。
  2. 我方运维团队负责收集网络不通的 Pod ,通过脚本进行 PING 操作。
  3. 我方研发团队通过 Apifox 发起大量请求,查看持续请求是否出现异常。

由于运维脚本额操作的步骤太多,为了提高监控效率,笔者将运维脚本导入到 blackbox-exporter 监控,并展示到 Grafana 查看。代码片段如下。

yaml 复制代码
global:
  scrape_interval: 15s
  evaluation_interval: 15s
  
alerting:
  alertmanagers:
    - static_configs:
        - targets:
          - alertmanager:9093
  
rule_files:
  - /etc/prometheus/rules/*.rules
  
scrape_configs:
  - job_name: "blackbox-ping"
    scrape_interval: 5s
    metrics_path: /probe
    params:
      module: [icmp]
    static_configs:
    # 网络不通的机器
    - targets: ['172.28.12.1','172.28.12.2','...']
    relabel_configs:
      - source_labels: [__address__]
        target_label: __param_target
      - source_labels: [__param_target]
        target_label: instance
      - target_label: __address__
        replacement: blackbox-exporter:9115

  - job_name: 'blackbox-tcp'
    scrape_interval: 5s
    metrics_path: /probe
    params:
      module: [tcp_connect]
    static_configs:
    - targets: ['172.28.12.101:2181','172.28.12.102:2181','...'] 
    relabel_configs:
      - source_labels: [__address__]
        target_label: __param_target
      - source_labels: [__param_target]
        target_label: instance
      - target_label: __address__
        replacement: blackbox-exporter:9115

  - job_name: 'blackbox-http'
    scrape_interval: 5s
    metrics_path: /probe
    params:
      module: [http_2xx]
    static_configs:
    - targets: ['http://172.28.20.1:9091/apisix/prometheus/metrics', '...']
    relabel_configs:
      - source_labels: [__address__]
        target_label: __param_target
      - source_labels: [__param_target]
        target_label: instance
      - target_label: __address__
        replacement: blackbox-exporter:9115

我们主动发起的请求,并没有出现任何异常。等到了 21:30 之后,我们不再模拟请求,故障又出现了,但是,腾讯方反馈,他们的网络是正常的。我们在 Grafana 监控也证实网络是正常的。

可疑后台进程?

排除网络问题,因为这些故障看起来是周期性的,感觉就像有一个后台进程定时执行某些工作,同时对这几个 K8s 集群造成了影响。

因为系统使用的是腾讯云 EKS 弹性集群,机器节点由腾讯方团队负责维护,我们让腾讯云协助检查我们使用的 K8s 集群节点,他们还是没找到原因。

我们内部做了复盘,回头看看事故的时间点,每隔一天同一时段发生一次,像是定时任务做了什么操作导致。有可能是 腾讯做了什么定时任务?我们的 xxljob?服务器上的定时任务?

好像算漏了 Linux 定时任务。经过盘点各服务器的定时脚本,发现有个 Linux 过期日志清理脚本执行卡死。这个脚本每天凌晨 4 点执行日志清理,发生问题的代码片段如下。

bash 复制代码
# 对 kafka-consumer 控制台输入的 out 文件压缩处理
tar czf kafka-consumer_${today}.tar.gz kafka-consumer.out
# 在压缩完成后通过 echo 重置内容
echo "-------${today} New Log-------" > kafka-consumer.out

日志文件通过腾讯云 CFS 文件系统挂载到我们的运维服务器,运维服务器运行这个清洗脚本对日志文件执行读写操作,如下图。

腾讯云对 CFS 做了存储效率优化,为了提高存储资源申请的分配效率,采用稀疏文件的方式,我们写入 kafka-consumer.out 每天大概就 5GBCFS 通过稀疏文件机制预占了 100 GB,甚至更多。

结果,脚本内的 tar 命令无法识别 spare 稀疏文件,按照稀疏文件给出的大小进行压缩,导致整个 CFS 的宿主机 IO 僵死。我们的系统 A、系统 B、系统 C 部分组件挂载了该 CFS 路径,产生了连锁故障。

做个实验,执行 ls 和 du 命令,如下图。

可以看到,我们只写入了 1.5M 的大小,结果在稀疏文件表现为 716G 。这是因为 ls 命令查到的是文件逻辑上占用的空间,而 du 命令查到的是文件物理上占用的块大小。

对于腾讯来说,如果使用稀疏文件来作为虚拟硬盘文件,那么只有当虚拟机实际写入数据时,才会消耗宿主机的存储空间,有利于他们的成本控制。

解决方案

责任已经明确,相应的解决方案如下。

腾讯方:同一个 CFS 路径没有做到真正的物理隔离,没有告知用户,用户在使用 CFS 的个数是有限制的,当时的做法只能共用。既然 CFS 解决不了这个问题,那就和腾讯申请更多的 CFS 盘,每套系统单独挂载,做到物理隔离。

我方:日志脚本有问题,去除 tar 命令,以防误读稀疏文件,并增加日志,邮件监控,应用层尽可能避免大量的控制台日志打印。

相关推荐
Doro再努力1 小时前
Vim 快速上手实操手册:从入门到生产环境实战
linux·编辑器·vim
wypywyp1 小时前
8. ubuntu 虚拟机 linux 服务器 TCP/IP 概念辨析
linux·服务器·ubuntu
Doro再努力2 小时前
【Linux操作系统10】Makefile深度解析:从依赖推导到有效编译
android·linux·运维·服务器·编辑器·vim
senijusene2 小时前
Linux软件编程:IO编程,标准IO(1)
linux·运维·服务器
忧郁的橙子.2 小时前
02-本地部署Ollama、Python
linux·运维·服务器
醇氧2 小时前
【linux】查看发行版信息
linux·运维·服务器
No8g攻城狮3 小时前
【Linux】Windows11 安装 WSL2 并运行 Ubuntu 22.04 详细操作步骤
linux·运维·ubuntu
XiaoFan0123 小时前
免密批量抓取日志并集中输出
java·linux·服务器
souyuanzhanvip3 小时前
ServerBox v1.0.1316 跨平台 Linux 服务器管理工具
linux·运维·服务器
HalvmånEver4 小时前
Linux:线程互斥
java·linux·运维