问题描述
Linux系统的阿里云ECS实例使用NVMe系统盘后,出现非预期的慢IO读写,导致系统或者应用程序对于NVMe磁盘的IO操作失败。NVMe磁盘上的文件系统从原来挂载的可读、写的状态,切换为只读不可写的状态,后续的写操作均失败,从而导致系统和应用程序异常或者业务中断。
问题原因
造成该问题的原因如下:
受多种原因影响,读写NVMe磁盘的IO操作可能会出现较大的延迟。NVMe驱动中的
io_timeout
参数控制了最大能够容忍的IO超时时间,在大部分Linux发行版本中默认配置为30秒。如果IO读写操作的延迟过高,超过了该参数的配置值,则NVMe驱动会返回IO失败。在特定情况下,系统或者应用程序可以对IO操作进行重试。但在某些情况下,可能导致NVMe磁盘上的文件系统从原来挂载的可读、写的状态,切换为只读不可写的状态,后续的写操作均失败,从而导致系统和应用程序异常或者业务中断。为了减少NVMe磁盘的IO操作超时出现的异常情况,通常会将
io_timeout
参数设置为可能的最大值,提高对于IO延迟的容忍度。在新版本的内核中,io_timeout
参数的最大值为4,294,967,295,较早版本中为255。不同的版本的内核中,NVMe驱动的内核模块也有所不同,部分内核模块为nvme.ko
,或者部分内核模块为nvme_core.ko
,从而完整的参数名称也存在nvme.io_timeout
和nvme_core.io_timeout
两种可能。阿里云的NVMe磁盘的Linux系统镜像中均已进行该配置,详情请参见Linux自定义镜像如何适配NVMe系统盘。如果设置被修改或者没有配置该项,就有可能出现上述问题。
您可以通过执行以下命令,查看NVMe驱动中的IO超时参数io_timeout
是否为默认的30秒。
cat /sys/module/nvme_core/parameters/io_timeout
内核版本较低的Linux发行版本,NVMe驱动的内核模块只有nvme.ko
而没有nvme_core.ko
,可通过执行以下命令,查看NVMe驱动中的IO超时参数io_timeout
是否为默认的30秒。
cat /sys/module/nvme/parameters/io_timeout
解决方案
您可以根据实际情况,选择临时配置或者固化配置io_timeout
参数的值。此外,阿里云云助手提供了自动化插件,如果您的操作系统符合云助手插件的支持范围,则您也可以使用云助手插件自动进行NVMe相关的配置操作。具体操作,请参见使用云助手插件自动化配置。
临时配置io_timeout参数的值
登录ECS实例。
具体操作,请参见连接方式概述。
检查io_timeout参数所在的内核模块路径。
执行以下命令,检查
/sys/module/nvme_core/parameters/io_timeout
路径是否存在,如果存在则表示完整的参数名称为nvme_core.io_timeout
。cat /sys/module/nvme_core/parameters/io_timeout
如果不存在以上路径,请执行以下命令,检查
/sys/module/nvme/parameters/io_timeout
路径是否存在,如果存在则表示完整的参数名称为nvme.io_timeout
。cat /sys/module/nvme/parameters/io_timeout
检查
io_timeout
参数是否可以接受4,294,967,295的最大值。执行以下命令,尝试将最大值写入到上述步骤获取的路径。echo 4294967295 > /sys/module/nvme_core/parameters/io_timeout
如果写入成功且没有报错,表明写入成功,其最大值为4,294,967,295。若出现类似于
Numerical result out of range
的错误,请使用255作为最大值,重新执行该步骤。
固化配置手动修改GRUB中的内核启动参数
Linux系统存在不同的发行版本,不同发行版本中修改GRUB中的内核启动参数方法不同,请根据现场环境匹配下列发行版本的操作命令。
CentOS
执行以下命令,查看系统内核是否已经加载了NVMe驱动。
cat /boot/config-`uname -r` | grep -i nvme | grep -v "^#"
系统显示类似如下,如果存在
CONFIG_BLK_DEV_NVME=y
,则表示该镜像已经加载NVMe驱动。CONFIG_NVME_CORE=m CONFIG_BLK_DEV_NVME=m CONFIG_NVME_MULTIPATH=y CONFIG_NVME_FABRICS=m CONFIG_NVME_RDMA=m CONFIG_NVME_FC=m CONFIG_NVME_TCP=m CONFIG_NVME_TARGET=m CONFIG_NVME_TARGET_LOOP=m CONFIG_NVME_TARGET_RDMA=m CONFIG_NVME_TARGET_FC=m CONFIG_NVME_TARGET_FCLOOP=m CONFIG_NVME_TARGET_TCP=m CONFIG_RTC_NVMEM=y CONFIG_NVMEM=y
在GRUB中添加NVMe相关的
nvme timeout
参数。执行以下命令,打开grub文件。
vi /etc/default/grub
按i键进入编辑模式,请参见临时配置io_timeout参数的值,确认
io_timeout
参数的完整参数名称和所能接受的最大值。例如,完整参数名称为nvme_core.io_timeout
,所能接受的最大值为 4,294,967,295。则请在GRUB_CMDLINE_LINUX=
一行中,添加nvme_core.io_timeout=4294967295 nvme_core.admin_timeout=4294967295
参数信息。 添加参数后,文件内容如下图所示:按Esc键退出编辑模式,输入:wq并按Enter键,保存退出文件。
根据操作系统的启动方式不同,执行以下适用于您的操作系统的命令,使配置的GRUB生效:
Legacy启动方式
grub2-mkconfig -o /boot/grub2/grub.cfg
UEFI启动方式
grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg
执行以下命令,重启实例,使配置生效。
reboot
执行以下命令,确认相关配置已正确传递给内核。
cat /proc/cmdline
系统显示类似如下。
... nvme_core.io_timeout=4294967295 nvme_core.admin_timeout=4294967295
执行以下命令,确认NVMe驱动参数已正确配置IO超时参数。
cat /sys/module/nvme_core/parameters/io_timeout
系统显示类似如下。
4294967295
Debian
执行以下命令,查看initrd中包含的NVMe驱动。
lsinitramfs /boot/initrd.img-`uname -r` | grep -i nvme
系统显示类似如下信息。 默认Debian操作系统的initrd中已经加载了NVMe驱动。
usr/lib/modules/4.19.0-18-amd64/kernel/drivers/nvme usr/lib/modules/4.19.0-18-amd64/kernel/drivers/nvme/host usr/lib/modules/4.19.0-18-amd64/kernel/drivers/nvme/host/nvme-core.ko usr/lib/modules/4.19.0-18-amd64/kernel/drivers/nvme/host/nvme-fabrics.ko usr/lib/modules/4.19.0-18-amd64/kernel/drivers/nvme/host/nvme-fc.ko usr/lib/modules/4.19.0-18-amd64/kernel/drivers/nvme/host/nvme-rdma.ko usr/lib/modules/4.19.0-18-amd64/kernel/drivers/nvme/host/nvme.ko usr/lib/modules/4.19.0-18-amd64/kernel/drivers/nvme/target usr/lib/modules/4.19.0-18-amd64/kernel/drivers/nvme/target/nvmet-fc.ko usr/lib/modules/4.19.0-18-amd64/kernel/drivers/nvme/target/nvmet-rdma.ko usr/lib/modules/4.19.0-18-amd64/kernel/drivers/nvme/target/nvmet.ko
在GRUB中添加NVMe相关的nvme timeout参数。
执行以下命令,打开grub文件。
vi /etc/default/grub
按i键进入编辑模式,请参见,确认
io_timeout
参数的完整参数名称和所能接受的最大值。例如,完整参数名称为nvme_core.io_timeout
,所能接受的最大值为 4,294,967,295。则请在GRUB_CMDLINE_LINUX=
一行中,添加nvme_core.multipath=n nvme_core.io_timeout=4294967295 nvme_core.admin_timeout=4294967295
参数信息。 添加参数后,文件内容如下所示:GRUB_DEFAULT=0 GRUB_TIMEOUT=1 GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian` GRUB_CMDLINE_LINUX_DEFAULT="quiet" GRUB_CMDLINE_LINUX=" vga=792 console=tty0 console=ttyS0,115200n8 net.ifnames=0 noibrs nvme_core.multipath=n nvme_core.io_timeout=4294967295 nvme_core.admin_timeout=4294967295"
按Esc键退出编辑模式,输入:wq并按Enter键,保存退出文件。
根据操作系统的启动方式不同,执行以下适用于您的操作系统的命令,使配置的GRUB生效。
Legacy启动方式
grub-mkconfig -o /boot/grub/grub.cfg
UEFI启动方式
grub-mkconfig -o /boot/efi/EFI/debian/grub.cfg
说明除以上方式外,您还可以选择Debian系统提供的脚本使配置的GRUB生效,运行脚本的命令如下所示。该脚本不区分操作系统的启动方式,适用于Legacy或UEFI启动方式。
update-grub2
执行以下命令,重启实例,使配置生效。
reboot
执行以下命令,确认相关配置已正确传递给内核。
cat /proc/cmdline
系统显示类似如下。
... nvme_core.multipath=n nvme_core.io_timeout=4294967295 nvme_core.admin_timeout=4294967295
执行以下命令,确认NVMe驱动参数已正确配置IO超时参数,
cat /sys/module/nvme_core/parameters/io_timeout
系统显示类似如下。
4294967295
Ubuntu
执行以下命令,查看initrd中包含的NVMe驱动。
lsinitramfs /boot/initrd.img-`uname -r` | grep -i nvme
系统显示类似如下, 默认Ubuntu操作系统的initrd中已经加载了NVMe驱动。
usr/lib/modules/5.4.0-86-generic/kernel/drivers/nvme usr/lib/modules/5.4.0-86-generic/kernel/drivers/nvme/host usr/lib/modules/5.4.0-86-generic/kernel/drivers/nvme/host/nvme-core.ko usr/lib/modules/5.4.0-86-generic/kernel/drivers/nvme/host/nvme-fabrics.ko usr/lib/modules/5.4.0-86-generic/kernel/drivers/nvme/host/nvme-fc.ko usr/lib/modules/5.4.0-86-generic/kernel/drivers/nvme/host/nvme-rdma.ko usr/lib/modules/5.4.0-86-generic/kernel/drivers/nvme/host/nvme-tcp.ko usr/lib/modules/5.4.0-86-generic/kernel/drivers/nvme/host/nvme.ko usr/lib/modules/5.4.0-86-generic/kernel/drivers/nvme/target usr/lib/modules/5.4.0-86-generic/kernel/drivers/nvme/target/nvme-loop.ko usr/lib/modules/5.4.0-86-generic/kernel/drivers/nvme/target/nvmet-fc.ko usr/lib/modules/5.4.0-86-generic/kernel/drivers/nvme/target/nvmet-rdma.ko usr/lib/modules/5.4.0-86-generic/kernel/drivers/nvme/target/nvmet-tcp.ko usr/lib/modules/5.4.0-86-generic/kernel/drivers/nvme/target/nvmet.ko
在GRUB中添加NVMe相关的nvme timeout参数。
执行以下命令,打开grub文件。
vi /etc/default/grub
按i键进入编辑模式,请参见临时配置io_timeout参数的值,确认
io_timeout
参数的完整参数名称和所能接受的最大值。例如,完整参数名称为nvme_core.io_timeout
,所能接受的最大值为 4294967295。则请在GRUB_CMDLINE_LINUX=
一行中,添加nvme_core.multipath=n nvme_core.io_timeout=4294967295 nvme_core.admin_timeout=4294967295
参数信息。 添加参数后,文件内容如下所示:GRUB_DEFAULT=0 GRUB_TIMEOUT=1 GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian` GRUB_CMDLINE_LINUX_DEFAULT="quiet" GRUB_CMDLINE_LINUX=" vga=792 console=tty0 console=ttyS0,115200n8 net.ifnames=0 noibrs nvme_core.multipath=n nvme_core.io_timeout=4294967295 nvme_core.admin_timeout=4294967295"
按Esc键退出编辑模式,输入:wq并按Enter键,保存退出文件。
根据操作系统的启动方式不同,执行以下适用于您的操作系统的命令,使配置的GRUB生效:
Legacy启动方式
grub-mkconfig -o /boot/grub/grub.cfg
UEFI启动方式
grub-mkconfig -o /boot/efi/EFI/ubuntu/grub.cfg
说明除以上方式外,您还可以选择Ubuntu系统提供的脚本使配置的GRUB生效,运行脚本的命令如下所示。该脚本不区分操作系统的启动方式,适用于Legacy或UEFI启动方式。
update-grub2
执行以下命令,重启实例,使配置生效。
reboot
执行以下命令,确认相关配置已正确传递给内核。
cat /proc/cmdline
系统显示类似如下信息。
... nvme_core.multipath=n nvme_core.io_timeout=4294967295 nvme_core.admin_timeout=4294967295
执行以下命令,确认NVMe驱动参数已正确配置IO超时参数。
cat /sys/module/nvme_core/parameters/io_timeout
系统显示类似如下信息。
4294967295
OpenSUSE/SUSE Linux
执行以下命令,查看系统内核是否已经加载了内核驱动。
cat /boot/config-`uname -r` | grep -i nvme | grep -v "^#"
系统显示类似如下,如果存在CONFIG_BLK_DEV_NVME=y,则表示该镜像已经加载NVMe驱动。
CONFIG_NVME_CORE=m CONFIG_BLK_DEV_NVME=m CONFIG_NVME_MULTIPATH=y CONFIG_NVME_HWMON=y CONFIG_NVME_FABRICS=m CONFIG_NVME_RDMA=m CONFIG_NVME_FC=m CONFIG_NVME_TCP=m CONFIG_NVME_TARGET=m CONFIG_NVME_TARGET_PASSTHRU=y CONFIG_NVME_TARGET_LOOP=m CONFIG_NVME_TARGET_RDMA=m CONFIG_NVME_TARGET_FC=m CONFIG_NVME_TARGET_FCLOOP=m CONFIG_NVME_TARGET_TCP=m CONFIG_RTC_NVMEM=y CONFIG_NVMEM=y CONFIG_NVMEM_SYSFS=y
在GRUB中添加NVMe相关的nvme timeout参数。
执行以下命令,打开grub文件。
vi /etc/default/grub
按i键进入编辑模式,请参见临时配置io_timeout参数的值,确认
io_timeout
参数的完整参数名称和所能接受的最大值。例如,完整参数名称为nvme_core.io_timeout
,所能接受的最大值为 4,294,967,295。则请在GRUB_CMDLINE_LINUX=
一行中,添加nvme_core.multipath=n nvme_core.io_timeout=4294967295 nvme_core.admin_timeout=4294967295
参数信息。 添加参数后,文件内容如下所示:GRUB_DISTRIBUTOR= GRUB_DEFAULT=saved GRUB_HIDDEN_TIMEOUT=0 GRUB_HIDDEN_TIMEOUT_QUIET=true GRUB_TIMEOUT=1 GRUB_CMDLINE_LINUX_DEFAULT="splash=silent mitigations=auto quiet" GRUB_CMDLINE_LINUX=" net.ifnames=0 console=tty0 console=ttyS0,115200n8 nvme_core.multipath=n nvme_core.io_timeout=4294967295 nvme_core.admin_timeout=4294967295" GRUB_TERMINAL="console" GRUB_GFXMODE="auto" GRUB_BACKGROUND=/boot/grub2/themes/SLE/background.png GRUB_THEME=/boot/grub2/themes/SLE/theme.txt SUSE_BTRFS_SNAPSHOT_BOOTING="true" GRUB_DISABLE_OS_PROBER="true" GRUB_ENABLE_CRYPTODISK="n" GRUB_CMDLINE_XEN_DEFAULT="vga=gfx-1024x768x16"
按Esc键退出编辑模式,输入:wq并按Enter键,保存退出文件。
根据操作系统的启动方式不同,执行以下适用于您的操作系统的命令,使配置的GRUB生效。
Legacy启动方式
grub2-mkconfig -o /boot/grub2/grub.cfg
UEFI启动方式
grub2-mkconfig -o /boot/efi/EFI/sles/grub.cfg
执行以下命令,重启实例,使配置生效。
reboot
执行以下命令,确认相关配置已正确传递给内核。
cat /proc/cmdline
系统显示类似如下信息。
... nvme_core.multipath=n nvme_core.io_timeout=4294967295 nvme_core.admin_timeout=4294967295
执行以下命令,确认NVMe驱动参数已正确配置IO超时参数。
cat /sys/module/nvme_core/parameters/io_timeout
系统显示类似如下信息。
4294967295
使用云助手插件自动化配置
云助手提供了ecs_nvme_config
插件,帮助您快速完成操作系统内NVMe相关的配置。
ecs_nvme_config
插件目前支持以下操作系统:
Alibaba Cloud Linux
Anolis OS
CentOS/CentOS Stream
Debian
Ubuntu
OpenSUSE
SUSE Linux Enterprise Server
Red Hat Enterprise Linux
Fedora
Rocky Linux
AlmaLinux
ecs_nvme_config
插件不支持以下操作系统:
CentOS/Red Hat Enterprise Linux:低于6.6的操作系统版本
Debian:低于9的操作系统版本
Ubuntu:低于16的操作系统版本
OpenSUSE:42操作系统版本
SUSE Linux Enterprise Server:低于11.4的操作系统版本
登录ECS实例。
具体操作,请参见连接方式概述。
- 本页导读 (1)