文档目录

问题说明

本文用于排查备份、快照或主机管理请求返回 408 Request Timeout,尤其是 MN 到 KVM Agent 的 HTTP 请求在约 15 秒后失败的场景。关联研发项提供的是大规模主机重连中的相邻 socket-timeout 证据,不是本文备份/快照场景的直接根因或修复证明。

现象

  • 管理节点日志出现 Async POST request ... resulted in 408 或 408 Request Timeout: [no body]。
  • Veeam/云祺备份在 takesnapshot、SharedBlock 检查或 host capacity 请求阶段失败。
  • KVM Agent 业务日志可能没有对应 URI 的入口记录,但同一时间还能处理其他请求。
  • 统计到多个主机、多个 URI 均有约 15 秒的 408;不能仅凭一次快照失败认定为 LVM 命令失败。

适用环境

  • 产品:ZVF ZSphere
  • 版本:4.10.19.3(事故日志包提供的现场构建;4.10.19~4.10.28 的代码核对只用于确认相关默认值未变,不扩展本文适用范围)
  • 组件:ZSphere 管理节点、KVM Agent HTTP 服务、主机管理网络
  • 部署形态:管理节点通过 TCP 7070 访问 KVM Agent;同一时间可能存在并发备份、快照或容量查询

可能原因

  1. CherryPy server.socket_timeout=15 在业务 handler 之前返回空 body 408。
  2. Agent 默认线程池为 10,请求排队或主机网络抖动使请求无法及时被读取。
  3. MN 到多台 Agent 的网络链路异常;这是与线程池竞争的另一分支,需要抓包区分。
  4. 业务存储操作慢但已成功完成;不能把“耗时超过 15 秒”直接等同于命令失败。

排查步骤

1. 先确认 408 是谁返回的

  • 检查对象:management-server.log 中失败请求的 URI、目标主机、开始时间、返回时间和响应正文。
  • 操作位置:按以下顺序查询,不要只搜索 408 后就直接改 Agent 参数。
  1. 在 ZSphere UI 打开失败任务详情,记录 apiId、故障时间、虚拟机 UUID 和所在主机。SSH 登录管理节点,把实际 apiId 粘贴到变量中:
     KB_API_UUID='将任务详情中的apiId粘贴到这里'
     cd /usr/local/zstack/apache-tomcat/logs || exit 1
     ls -lh management-server.log*
     zgrep -a -n -C 3 "$KB_API_UUID" management-server.log*
     zgrep -a -n "$KB_API_UUID" management-server.log* | grep -E 'json POST|http response|408 Request Timeout'

json POST 行可看到请求 URI、目标 KVM Agent IP 和 taskuuid;http response 行可看到同一个 taskUuid 的返回。记录两行时间差以及响应是否为 [no body]。若无结果,先确认管理节点、UUID 和故障日期,并检查 management-server-日期-序号.log.gz 归档是否仍在。

  1. SSH 登录请求 URL 中的 ZSphere 主机,用该请求的 taskuuid 查当前和归档 Agent 日志:
     KB_TASK_UUID='将management-server日志中的taskuuid粘贴到这里'
     cd /var/log/zstack || exit 1
     ls -lh zstack-kvmagent.log*
     zgrep -a -n -C 5 "$KB_TASK_UUID" zstack-kvmagent.log*

如果 KVM Agent 日志完全没有该 taskuuid,必须同时确认主机 IP、时间窗和归档日志都正确;这些条件满足后,“管理节点已发请求但业务日志无入口”才支持请求在 handler 前超时的分支。

  1. 如果任务详情没有可用的 apiId,使用虚拟机 UUID 和准确到分钟的失败时间先在管理节点日志定位请求,再从请求行取得 taskuuid;不要把另一台虚拟机或另一轮重试的响应拼到当前任务。
  2. 需要查看上下文时执行 vim -R management-server.log 或 vim -R /var/log/zstack/zstack-kvmagent.log,输入 / 后粘贴 UUID 并按 Enter,按 n 看下一处,输入 :q! 退出。
  • 预期结果:管理节点收到业务响应,或错误能够关联到明确的 KVM Agent handler 日志。
  • 异常处理:若是空 body HTTP 408 且约 15 秒返回,进入 Agent/CherryPy 分支;若表现为连接拒绝、读取超时或 I/O exception,转入管理网络/客户端超时分支。

2. 对照当前版本的 KVM Agent HTTP 配置

  • 检查对象:与现场安装包版本一致的 zstacklib/zstacklib/utils/http.py。
  • 操作位置:只读核对与现场安装包一致的 HTTP server 构建逻辑。现场 4.10.19 包分析中可见:
  site_config['server.thread_pool'] = int(os.getenv('POOLSIZE', '10'))
  site_config['server.socket_timeout'] = 15
  • 预期结果:代码事实与现场错误的 15 秒特征一致,但这只能解释 408 的产生机制,不能区分线程池占满还是网络丢包。
  • 异常处理:现场包的值不一致时,以现场包为准,记录准确包版本和值,不沿用本文数值。

3. 用短时抓包区分 Agent 排队和网络路径

  • 检查对象:出现 408 的主机 TCP 7070 流量。经授权后在该主机执行:
  KB_MN_IP='将management-server日志中的管理节点IP粘贴到这里'
  timeout --signal=INT 3600 tcpdump -i any -nn -s0 -U -w /tmp/kvmagent-7070.pcap "tcp port 7070 and host $KB_MN_IP"
  ls -lh /tmp/kvmagent-7070.pcap
  • 抓包命令会在 3600 秒后自动停止。若问题提前复现,可按 Ctrl+C 停止;确认 pcap 文件非空后,在安装了 tshark 的授权分析机上执行:
  tshark -r /tmp/kvmagent-7070.pcap -Y 'http.response.code == 408' -T fields -e frame.number -e frame.time_relative -e tcp.stream
  tshark -r /tmp/kvmagent-7070.pcap -Y 'tcp.analysis.retransmission' -T fields -e frame.number -e frame.time_relative -e ip.src -e ip.dst -e tcp.stream
  KB_TCP_STREAM='将上一条408记录的tcp.stream数字粘贴到这里'
  tshark -r /tmp/kvmagent-7070.pcap -Y "tcp.stream == $KB_TCP_STREAM" -T fields -e frame.time_relative -e ip.src -e ip.dst -e _ws.col.Info
  • 预期结果:POST 完整到达后正常进入业务处理并返回,不出现固定约 15 秒的空 body 408。
  • 异常处理:POST 已完整到达、约 15 秒后才返回 408,优先检查 Agent 请求排队;POST 未完整到达或同一 stream 存在明显 TCP Retransmission,优先比较管理节点到受影响/未受影响主机的交换机、机柜和上联路径。pcap 含管理网络数据,只交给授权人员并按公司要求保管和清理。

4. 验证线程池是否被占满并做低并发对照

临时方案(Workaround)

  • 适用条件:408 与 7070 连接/线程池饱和或网络丢包在同一时间窗对应,且已排除 KVM Agent 进程退出、主机失联等其它故障;没有连续样本时不直接调并发。
  • 检查对象:KVM Agent 线程、7070 已建立连接数以及 D 状态线程。经授权后在受影响主机执行:
  KVMAGENT_PID="$(pgrep -o -f 'kvmagent')"
  ps -L -p "$KVMAGENT_PID" -o tid,stat,wchan:25,comm | grep -c 'CP Server'
  ss -tn state established '( sport = :7070 )' | wc -l
  ps -L -p "$KVMAGENT_PID" -o tid,stat,wchan:30 | awk '$2 ~ /D/'
  • 预期结果:线程和连接数不会持续顶住当前版本的池大小,也没有持续 D 状态线程;降低同时发起的备份/快照请求后,408 不再出现。
  • 临时执行:记录当前备份计划和并发配置,暂停同一批次的新备份/快照计划;等待已运行任务结束后,一次只对 1 台 虚拟机 发起备份,并在测试期间持续观察 7070 连接数、线程状态和管理节点 408。不要通过 kill 任务或 Agent 进程清空队列。
  • 分支处置:线程池持续占满时保留低并发调度并升级支持;网络分支先修复已确认的丢包、重传或交换路径问题。不要直接修改 POOLSIZE,该环境变量没有稳定配置入口,升级或重新部署 Agent 后还可能丢失。需要调参验证时,由 ZStack 技术支持提供准确版本的设置位置、原值、回滚值和观察指标。
  • 验证标准:相同虚拟机的备份/快照完成,管理节点与 KVM Agent 日志中不再出现同一 taskUuid 的空 body 408,抓包未再出现固定 15 秒返回的 408。
  • 回退:低并发只改变任务调度,不修改主机参数。若单 虚拟机 仍失败,停止继续重试并保持批量计划暂停;根因修复并验证后,按记录恢复原计划和并发。若支持人员另行修改参数,应使用其提供的原值和回滚步骤恢复,不把本文作为调参依据。

补充信息

  • 提交支持信息时,应包含准确时间窗、资源和任务 UUID、完整错误文本及相关组件日志。
  • 不能从单个现场结果外推所有版本;根因未闭合或操作可能影响业务、数据时,应停止自助处理并提交本文列出的证据。
备份或快照请求返回 408 Request Timeout | 故障排查 · KB | ZStack 资源中心