16、主机故障排查指南

主机故障排查指南

1. 高 I/O 等待问题

当 I/O 请求阻塞进程执行其他工作时,会出现显著的 I/O 等待(iowait)。通常,高 iowait 会导致主机负载增加,CPU 使用率可能高于正常水平。因为当 CPU 等待磁盘响应时,它为系统其他部分服务的时间就会减少。

高 iowait 可能由以下原因导致:

- 磁盘老化、速度慢或出现故障。

- 应用程序进行大量的磁盘读写操作。

- 在虚拟化环境中,网络附属存储速度慢。

所有系统都会有一定的 iowait,而且现代 CPU 的速度比存储设备快。不过,单独的高 iowait 并不一定意味着存在问题,有些高 iowait 的系统仍能正常运行,而有些则会出现明显的瓶颈。一般将持续超过 30% 的 iowait 视为高 iowait。

可以使用

iostat

iotop

这两个命令行工具来排查高 iowait 问题。

1.1 iostat 工具

iostat

用于报告设备的 CPU 和 I/O 统计信息,可帮助判断系统是否存在 iowait。若未默认安装,可使用包管理器安装

sysstat

包。

为了更好地观察问题,需要在一段时间内对系统进行轮询。示例命令如下:

$ iostat -xz 1 20

示例输出:

avg-cpu: %user %nice %system %iowait %steal %idle

6.25 0.00 27.08 66.67 0.00 0.00

Device r/s rkB/s w/s wkB/s %util ...

vda 0.00 0.00 1179.00 712388.00 100.00 ...

-xz

标志:以扩展统计格式显示仅活动的设备。

w/s

列:显示

vda

设备每秒执行大量写请求(1179.00)。

%iowait

:CPU 约 66.67% 的时间在等待未完成的磁盘请求。

%util

:磁盘利用率为 100%,表明磁盘非常繁忙。

由此可判断主机存在持续的高 iowait 问题,且问题出在

vda

设备上。接下来可使用

iotop

工具查找可能导致 iowait 增加的进程。

1.2 iotop 工具

iotop

以类似

top

的格式显示 I/O 使用情况,能提供主机 I/O 的概述,并深入到进程级别查找可能导致大量磁盘 I/O 的进程。多数发行版未默认包含该工具,需使用包管理器进行安装。

运行

iotop

时,可使用以下命令限制输出,仅显示执行 I/O 的活动进程,并使用批量模式持续轮询,使输出简洁,揭示可能的 I/O 模式。此命令需要提升权限,可使用

sudo

或特权用户运行:

$ sudo iotop -oPab

示例输出:

Total DISK READ: 15.04 M/s | Total DISK WRITE: 446.28 M/s

Current DISK READ: 15.04 M/s | Current DISK WRITE: 321.58 M/s

PID PRIO USER DISK READ DISK WRITE SWAPIN IO COMMAND

88576 be/4 bob 512.00 M 616.81 M 0.00 % 83.26% heavy-io

469 rt/4 root 0.00 B 0.00 B 0.00 % 0.00% multipathd -d -s

--snip--

-oPab

标志:使

iotop

在批量模式下仅显示执行 I/O 的进程,并显示累积统计信息。

IO

列:

heavy-io

命令的 I/O 使用率为 83.26%,其进程 ID(PID)为 88576。由于报告中其他进程的 I/O 使用量不大,可推测

heavy-io

进程是高 iowait 的部分原因。

1.3 后续步骤

在检查统计信息并找到导致高 iowait 的进程 ID 后,可以:

- 了解该应用程序的用途。若有源代码或配置文件,检查进程可访问的磁盘操作或文件。

- 若使用云服务提供商的虚拟机,检查磁盘是否有足够的 I/O 操作配额,可通过检查磁盘指标进行确认,并调整配额以平衡负载。

- 若上述方法都无效,可使用

lsof

检查打开的文件,

strace

跟踪进程的系统调用,

dmesg

查看硬件内核错误。

2. 主机名解析失败问题

当服务需要连接另一个服务时,通常会使用域名系统(DNS)查找目标服务的 IP 地址。DNS 就像一个主机 IP 地址映射目录,让我们可以使用像

google.com

这样的域名,而无需记住具体的 IP 地址。

假设一个应用程序尝试连接本地环境中的 Postgres 数据库,日志中出现如下错误:

psql: error: could not translate host name "db.smith.lab" to address: Temporary failure in name resolution

这表明应用程序无法解析

db.smith.lab

的 DNS 记录。下面介绍一些排查此错误的工具。

2.1 resolv.conf 文件

在 Linux 主机上排查 DNS 问题,首先要查看

/etc/resolv.conf

文件,它提供了要查询的 DNS 服务器信息以及一些特殊选项(如超时或安全设置)。以下是一个典型 Ubuntu 主机的

resolv.conf

文件示例:

# This file is managed by man:systemd-resolved(8). Do not edit.

#

# This is a dynamic resolv.conf file for connecting local clients to the

# internal DNS stub resolver of systemd-resolved. This file lists all

# configured search domains.

#

# Run "resolvectl status" to see details about the uplink DNS servers

# currently in use.

#

# Third party programs must not access this file directly, but only through

# the symlink at /etc/resolv.conf. To manage man:resolv.conf(5) in a

# different way, replace this symlink by a static file or a different

# symlink.

#

# See man:systemd-resolved.service(8) for details about the supported

# modes of operation for /etc/resolv.conf.

nameserver 127.0.0.53

options edns0 trust-ad

该文件由

systemd-resolved

服务管理,不要手动编辑,否则下次主机或服务重启时会被覆盖。

nameserver

关键字指定要查询的 DNS 服务器 IP 地址,此例中为

127.0.0.53

,即本地解析器。若本地解析器不知道查询答案,会将请求转发到上游 DNS 服务器。

options

关键字用于修改解析器的特定属性。

edns0

选项启用 DNS 协议的扩展功能;

trust-ad

选项在所有出站 DNS 查询中包含认证数据,并在响应中保留认证数据,增强 DNS 安全性。

2.2 resolvectl 工具

由于使用了

systemd-resolver

,可以使用

resolvectl

工具与本地解析器交互。若未安装,可通过包管理器安装。

要查看本地 DNS 解析器(

127.0.0.53

)将未知请求转发到哪些上游 DNS 服务器,可使用以下命令:

$ resolvectl dns

示例输出:

Global:

--snip--

Link 2 (enp0s3): 10.0.2.3

结果显示,对于接口

enp0s3

,下游 DNS 服务器设置为

10.0.2.3

。主机上的应用程序尝试连接

db.smith.lab

时,会先向

127.0.0.53

发送 DNS 请求,若本地解析器不知道答案,会将请求转发到

10.0.2.3

。若

10.0.2.3

知道答案,会返回给本地解析器,再由本地解析器返回给用户;若不知道,会继续向上游转发,直到找到该域名的权威服务器。

2.3 dig 工具

dig

用于查询 DNS 服务器并显示结果,在排查 DNS 问题或获取主机 IP 地址时非常有用。只需将主机名传递给

dig

,它就会返回查询和响应服务器的相关信息。

查询本地解析器中

db.smith.lab

的 IP 地址:

$ dig db.smith.lab

示例输出:

; DiG 9.16.1-Ubuntu db.smith.lab

;; global options: +cmd

;; Got answer:

;; -HEADER- opcode: QUERY, status: SERVFAIL, id: 35816

;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:

; EDNS: version: 0, flags:; udp: 65494

;; QUESTION SECTION:

;db.smith.lab. IN A

;; Query time: 32 msec

;; SERVER: 127.0.0.53#53(127.0.0.53)

--snip--

- `status` 字段显示查询状态,`SERVFAIL` 表示无法给出答案,因为本地 DNS 不知道 `db.smith.lab` 的位置。

- `QUESTION SECTION` 显示发送给 DNS 服务器的查询,这里是查询 `db.smith.lab` 的 A 记录(将域名映射到 IP 地址的 DNS 记录类型)。

- `SERVER` 部分显示查询所使用的 DNS 服务器,即本地解析器 `127.0.0.53`。

查询上游服务器中

db.smith.lab

的 IP 地址:

$ dig @10.0.2.3 db.smith.lab

结果同样显示

SERVFAIL

,说明上游服务器也无法提供该主机名的答案。

为确保本地和上游 DNS 服务器正常工作,查询

google.com

的 A 记录:

$ dig google.com

示例输出:

;; -HEADER- opcode: QUERY, status: NOERROR, id: 15154

;; QUESTION SECTION:

;google.com. IN A

;; ANSWER SECTION:

google.com. 300 IN A 142.250.72.78

;; Query time: 36 msec

;; SERVER: 127.0.0.53#53(127.0.0.53)

状态为

NOERROR

,且在

ANSWER SECTION

中获得了

google.com

的 A 记录

142.250.72.78

,说明 DNS 服务器可以正常解析其他主机名,但不知道

db.smith.lab

的 A 记录。

2.4 后续步骤

若 DNS 能正常解析其他主机名,但特定主机名解析失败,问题可能出在 DNS 解析器缺少该主机名到 IP 地址的映射信息。

- 若使用 Amazon Route53 等服务托管 DNS,确保记录未被配置管理软件或人为错误删除。

- 若本地管理 DNS 服务器,检查 A 记录是否存在。若不存在,可能是配置文件存在语法错误,或者需要重启 DNS 服务器以读取新记录。

3. 磁盘空间不足问题

磁盘空间最终会耗尽,此时需要找出占用大量空间的原因,可能是应用程序异常、日志文件无限制增长或 Docker 镜像堆积等。

3.1 df 工具

df

用于显示主机上所有挂载文件系统的可用磁盘空间。通常使用

-h

标志以人类可读的格式显示结果。

$ df -h

示例输出:

Filesystem Size Used Avail Use% Mounted on

/dev/vda1 25G 25G 0 100% /

--snip--

此例中,

/dev/vda1

设备已使用了 25G 的全部磁盘空间,文件系统挂载在根目录

/

。若主机有多个挂载磁盘,输出中也会显示。

3.2 find 工具

find

可在文件系统中搜索目录和文件,并可根据特定条件或目录进行过滤,还能按文件大小查找。

由于运行

df

命令后知道根文件系统空间不足,可使用

find

命令在根文件系统中搜索大于 100M 的文件,并按大小排序,显示前 10 个结果。

$ sudo find / -type f -size +100M -exec du -ah {} + | sort -hr | head

示例输出:

10G /var/log/php7.2-fpm.log

5G /var/lib/docker/containers/.../...a3b76-json.log

--snip--

此输出显示

/var/log/php7.2-fpm.log

文件大小为 10G,

/var/lib/docker/containers

中的一个 Docker 容器日志文件大小为 5G,这两个文件共占用了 15GB 磁盘空间。通常,这类应用程序日志应该定期轮转,不应该变得如此之大。

3.3 lsof 工具

lsof

用于列出主机上打开的文件,可根据进程或用户进行搜索。使用

lsof

查找正在写入

/var/log/php7.2-fpm.log

文件的进程:

$ sudo lsof /var/log/php7.2-fpm.log

示例输出:

COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME

php-fpm7. 23496 root 2w REG 252,1 1048580000 1529 /var/log/php7.2-fpm.log

--snip--

结果显示,

php-fpm7

进程(PID 为 23496)正在写入该日志文件。文件描述符

2w

表示文件描述符为 2,且以写入模式打开。

3.4 后续步骤

当磁盘空间不足且找到占用大量空间的文件后,由于日志文件正在被使用,直接截断或删除可能导致进程崩溃或停止写入日志。可以:

- 查看日志输出,检查是否有错误信息,或者应用程序日志级别是否设置为调试模式。

- 检查 Docker 容器日志内容,看是否与该日志文件存在关联,可能该进程在容器内运行。

- 确保主机配置了

logrotate

命令,按计划压缩和轮转日志文件,避免日志文件无限制增长。Ubuntu 系统中,

logrotate

配置文件位于

/etc/logrotate.d/

目录。

综上所述,通过以上工具和方法,可以有效地排查主机的高 I/O 等待、主机名解析失败和磁盘空间不足等常见问题。在实际操作中,要根据具体情况灵活运用这些工具,逐步定位和解决问题。

主机故障排查指南(续)

4. 总结与流程梳理

为了更清晰地展示上述故障排查的流程,下面通过 mermaid 流程图进行梳理。

graph LR

classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px

classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px

classDef decision fill:#FFF6CC,stroke:#FFBC52,stroke-width:2px

A([开始排查]):::startend --> B{故障类型?}:::decision

B -->|高 I/O 等待| C(使用 iostat 检查):::process

C --> D{是否高 iowait?}:::decision

D -->|是| E(确定受影响设备):::process

E --> F(使用 iotop 查找进程):::process

F --> G(分析进程及后续处理):::process

B -->|主机名解析失败| H(查看 resolv.conf 文件):::process

H --> I(使用 resolvectl 查看上游 DNS):::process

I --> J(使用 dig 查询 DNS):::process

J --> K{解析是否失败?}:::decision

K -->|是| L(检查 DNS 记录及配置):::process

B -->|磁盘空间不足| M(使用 df 查看空间):::process

M --> N{是否空间不足?}:::decision

N -->|是| O(使用 find 查找大文件):::process

O --> P(使用 lsof 确定进程):::process

P --> Q(处理文件及配置 logrotate):::process

5. 工具使用对比

为了更直观地对比上述使用的工具,下面通过表格进行展示:

故障类型

工具名称

工具作用

使用示例

高 I/O 等待

iostat

报告设备的 CPU 和 I/O 统计信息

iostat -xz 1 20

高 I/O 等待

iotop

以类似 top 的格式显示 I/O 使用情况,定位进程

sudo iotop -oPab

主机名解析失败

resolv.conf

提供要查询的 DNS 服务器信息及特殊选项

查看

/etc/resolv.conf

文件

主机名解析失败

resolvectl

与本地解析器交互,查看上游 DNS 服务器

resolvectl dns

主机名解析失败

dig

查询 DNS 服务器并显示结果

dig db.smith.lab

dig @10.0.2.3 db.smith.lab

dig google.com

磁盘空间不足

df

显示主机上所有挂载文件系统的可用磁盘空间

df -h

磁盘空间不足

find

在文件系统中搜索符合条件的大文件

sudo find / -type f -size +100M -exec du -ah {} + | sort -hr | head

磁盘空间不足

lsof

列出主机上打开的文件,确定写入进程

sudo lsof /var/log/php7.2-fpm.log

6. 常见问题及注意事项

在使用这些工具进行主机故障排查时,可能会遇到一些常见问题,下面进行总结:

6.1 高 I/O 等待问题

工具安装问题

iostat

依赖

sysstat

包,

iotop

多数发行版未默认安装。在使用前,需通过包管理器进行安装,如

apt-get install sysstat

yum install sysstat

安装

sysstat

apt-get install iotop

yum install iotop

安装

iotop

数据准确性

iostat

首次输出的数据是自上次主机启动以来的统计信息,在当前排查场景中可能不相关,分析时需注意。

6.2 主机名解析失败问题

resolv.conf 文件修改

:该文件由

systemd-resolved

服务管理,手动修改可能会在主机或服务重启时被覆盖。若需自定义配置,可参考文件中的注释说明进行操作。

DNS 服务器配置

:本地解析器和上游 DNS 服务器的配置可能因网络环境不同而有所差异,需根据实际情况进行检查和调整。

6.3 磁盘空间不足问题

find 命令性能

:在大文件系统中使用

find

命令搜索大文件可能会消耗大量时间和系统资源。可根据实际情况调整搜索条件,如缩小搜索范围或调整文件大小阈值。

lsof 权限问题

lsof

命令需要提升权限才能运行,可使用

sudo

或特权用户执行。

7. 实际案例分析

下面通过一个实际案例,综合运用上述工具和方法进行故障排查。

假设某服务器出现响应缓慢的情况,初步怀疑是高 I/O 等待或磁盘空间不足问题。

第一步:检查磁盘空间

$ df -h

输出显示

/dev/vda1

设备已使用 100% 的 50G 磁盘空间,确定磁盘空间不足。

第二步:查找大文件

$ sudo find / -type f -size +100M -exec du -ah {} + | sort -hr | head

发现

/var/log/app.log

文件占用了 30G 空间。

第三步:确定写入进程

$ sudo lsof /var/log/app.log

得知

app-process

进程(PID 为 12345)正在写入该日志文件。

第四步:查看日志内容

$ tail -n 100 /var/log/app.log

发现日志中存在大量重复的错误信息,推测是应用程序异常导致日志文件不断增长。

第五步:处理问题

调整应用程序配置,修复导致错误的问题。

配置

logrotate

app.log

文件进行定期轮转和压缩。

经过上述处理,服务器响应恢复正常,磁盘空间问题得到解决。

8. 结论

主机故障排查是系统管理中的重要工作,通过合理运用

iostat

iotop

resolv.conf

resolvectl

dig

df

find

lsof

等工具,结合科学的排查流程和方法,可以有效地定位和解决高 I/O 等待、主机名解析失败和磁盘空间不足等常见问题。在实际操作中,要注意工具的安装和使用细节,根据具体情况灵活调整排查策略,确保系统的稳定运行。同时,定期对系统进行监控和维护,及时发现和处理潜在问题,也是保障系统性能的关键。