排查 Linux VM 设备名称更改问题

本文介绍了重启 Linux VM 或重新附加数据磁盘后设备名称发生更改的原因。 本文还提供了此问题的解决方案。

症状

在 Microsoft Azure 中运行 Linux VM 时,可能会遇到以下问题:

  • 重启后 VM 无法启动。
  • 分离并重新附加数据磁盘时,磁盘设备名称将更改。
  • 使用设备名称引用磁盘的应用程序或脚本失败,因为设备名称已更改。

原因

Linux 中的设备路径不能保证在重启时保持一致。 设备名称由主要数字 (字母) 和次要数字组成。 当 Linux 存储设备驱动程序检测到新设备时,驱动程序会将可用范围中的主要和次要数字分配给设备。 删除设备后,将释放设备编号以供重复使用。

出现此问题的原因是,SCSI 子系统计划 Linux 中的设备扫描以异步方式进行。 因此,设备路径名称可能因重启而异。

解决方案

若要解决此问题,请使用持久命名。 有四种方法可以使用持久命名:按文件系统标签、按 UUID、按 ID 或按路径。 建议对 Azure Linux VM 使用文件系统标签或 UUID。

大多数分布区提供 fstabnofailnobootwait 参数。 当磁盘在启动时无法装载时,这些参数使系统能够启动。 有关这些参数的详细信息,请查看分发文档。 有关如何将 Linux VM 配置为在添加数据磁盘时使用 UUID 的信息,请参阅 连接到 Linux VM 以装载新磁盘

在 VM 上安装 Azure Linux 代理时,代理使用 Udev 规则在 /dev/disk/azure 路径下构造一组符号链接。 应用程序和脚本使用 Udev 规则来标识附加到 VM 的磁盘,以及磁盘类型和磁盘 LUN。

如果已以无法启动 VM 且无法通过 SSH 连接到 VM 的方式编辑 fstab,则可以使用 VM 串行控制台 进入 单用户模式 并修改 fstab。

标识磁盘 LUN

应用程序使用 LUN 查找所有附加的磁盘并构造符号链接。 Azure Linux 代理包括设置从 LUN 到设备的符号链接的 Udev 规则:

$ tree /dev/disk/azure

/dev/disk/azure
├── resource -> ../../sdb
├── resource-part1 -> ../../sdb1
├── root -> ../../sda
├── root-part1 -> ../../sda1
└── scsi1
    ├── lun0 -> ../../../sdc
    ├── lun0-part1 -> ../../../sdc1
    ├── lun1 -> ../../../sdd
    ├── lun1-part1 -> ../../../sdd1
    ├── lun1-part2 -> ../../../sdd2
    └── lun1-part3 -> ../../../sdd3

使用 lsscsi 或类似工具检索 Linux 来宾帐户中的 LUN 信息:

$ sudo lsscsi

[1:0:0:0] cd/dvd Msft Virtual CD/ROM 1.0 /dev/sr0

[2:0:0:0] disk Msft Virtual Disk 1.0 /dev/sda

[3:0:1:0] disk Msft Virtual Disk 1.0 /dev/sdb

[5:0:0:0] disk Msft Virtual Disk 1.0 /dev/sdc

[5:0:0:1] disk Msft Virtual Disk 1.0 /dev/sdd

来宾 LUN 信息与 Azure 订阅元数据一起使用,用于在 Azure 存储中查找包含分区数据的 VHD。 例如,可以使用 az CLI:

$ az vm show --resource-group testVM --name testVM | jq -r .storageProfile.dataDisks
[
{
"caching": "None",
  "createOption": "empty",
"diskSizeGb": 1023,
  "image": null,
"lun": 0,
"managedDisk": null,
"name": "testVM-20170619-114353",
"vhd": {
  "uri": "https://testVM.blob.core.windows.net/vhd/testVM-20170619-114353.vhd"
}
},
{
"caching": "None",
"createOption": "empty",
"diskSizeGb": 512,
"image": null,
"lun": 1,
"managedDisk": null,
"name": "testVM-20170619-121516",
"vhd": {
  "uri": "https://testVM.blob.core.windows.net/vhd/testVM-20170619-121516.vhd"
  }
  }
]

使用 blkid 发现文件系统 UUID

应用程序和脚本读取 的输出 blkid或类似的信息源,以在 /dev 路径中构造符号链接。 输出显示附加到 VM 的所有磁盘的 UUID 及其关联的设备文件:

$ sudo blkid -s UUID

/dev/sr0: UUID="120B021372645f72"
/dev/sda1: UUID="52c6959b-79b0-4bdd-8ed6-71e0ba782fb4"
/dev/sdb1: UUID="176250df-9c7c-436f-94e4-d13f9bdea744"
/dev/sdc1: UUID="b0048738-4ecc-4837-9793-49ce296d2692"

Azure Linux 代理 Udev 规则在 /dev/disk/azure 路径下构造一组符号链接:

$ ls -l /dev/disk/azure

total 0
lrwxrwxrwx 1 root root  9 Jun  2 23:17 resource -> ../../sdb
lrwxrwxrwx 1 root root 10 Jun  2 23:17 resource-part1 -> ../../sdb1
lrwxrwxrwx 1 root root  9 Jun  2 23:17 root -> ../../sda
lrwxrwxrwx 1 root root 10 Jun  2 23:17 root-part1 -> ../../sda1

应用程序使用这些链接来标识启动磁盘设备和资源 (临时) 磁盘。 在 Azure 中,应用程序应查找 /dev/disk/azure/root-part1 或 /dev/disk/azure-resource-part1 路径来发现这些分区。

列表中的任何其他分区 blkid 都驻留在数据磁盘上。 应用程序维护这些分区的 UUID,并使用路径在运行时发现设备名称:

$ ls -l /dev/disk/by-uuid/b0048738-4ecc-4837-9793-49ce296d2692

lrwxrwxrwx 1 root root 10 Jun 19 15:57 /dev/disk/by-uuid/b0048738-4ecc-4837-9793-49ce296d2692 -> ../../sdc1

获取最新的 Azure 存储规则

若要获取最新的 Azure 存储规则,请运行以下命令:

# sudo curl -o /etc/udev/rules.d/66-azure-storage.rules https://raw.githubusercontent.com/Azure/WALinuxAgent/master/config/66-azure-storage.rules
# sudo udevadm trigger --subsystem-match=block

另请参阅

有关详细信息,请参阅以下文章:

联系我们寻求帮助

如果你有任何疑问或需要帮助,请创建支持请求联系 Azure 社区支持。 还可以向 Azure 反馈社区提交产品反馈。