最佳实践:在 Linux 虚拟机上使用永久性设备名称


本文档介绍如何在 Linux 虚拟机上使用永久性设备命名。

对于使用 Linux 操作系统的虚拟机,当您执行如下过程后,设备名称(例如 /dev/sda)可能会发生变化:

  • 启动和停止虚拟机
  • 分离和重新挂接磁盘
  • 更改机器类型

设备名称变化的原因是,在虚拟机启动或挂接设备后,系统从可用范围分配设备名称。分离设备或停止虚拟机会释放设备名称。当设备重新挂接或虚拟机重启时,系统会从可用范围中分配新的设备名称。Linux 内核不保证每次重新启动后设备顺序相同。

设备名称变化可能会导致依赖于原始设备名称的应用或脚本无法正常运行,也可能导致虚拟机在重启后无法启动。

在 Linux 虚拟机上引用磁盘和分区时,建议您使用永久性设备命名,以避免此问题。 您也可以使用符号链接

准备工作

  • 查看您的 Linux 操作系统的设备管理:
  • 如果您尚未设置身份验证,请进行设置。身份验证是通过其进行身份验证以访问 Google Cloud 服务和 API 的过程。如需从本地开发环境运行代码或示例,您可以按如下方式向 Compute Engine 进行身份验证。

    Select the tab for how you plan to use the samples on this page:

    Console

    When you use the Google Cloud console to access Google Cloud services and APIs, you don't need to set up authentication.

    gcloud

    1. Install the Google Cloud CLI, then initialize it by running the following command:

      gcloud init
    2. Set a default region and zone.

Linux 虚拟机上的设备命名

挂接到虚拟机的磁盘的 Linux 设备名称取决于您在创建磁盘时选择的接口。使用 lsblk 操作系统命令查看磁盘设备时,它会显示通过 NVMe 接口连接的磁盘的前缀 nvme,以及通过 SCSI 接口连接的磁盘的前缀 sd

磁盘编号或 NVMe 控制器的顺序在虚拟机重启后是无法预测的,也可能不会保持一致。首次启动时,永久性磁盘可能是 nvme0n1(或 sda,对于 SCSI)。第二次启动时,同一永久性磁盘的设备名称可能是 nvme2n1nvme0n3(或 sdc,对于 SCSI)。

访问挂接的磁盘时,您应改用在 /dev/disk/by-id/ 中创建的符号链接。这些名称会在重新启动后保留。如需详细了解符号链接,请参阅挂接到虚拟机的磁盘的符号链接

SCSI 设备名称

对于第一个挂接的磁盘,使用 SCSI 挂接的磁盘设备的格式为 sda。磁盘分区显示为 sda1。每个额外的磁盘都使用顺序字母,例如 sdbsdc。达到 sdz 后,后续添加的磁盘的名称为 sdaasdabsdac,最多为 sddx

NVMe 设备名称

在 Linux 操作系统中,NVMe 挂接磁盘设备的格式为 nvmenumbernnamespacenumber 表示 NVMe 磁盘控制器编号,namespace 是由 NVMe 磁盘控制器分配的 NVMe 命名空间 ID。对于分区,pn 附加到设备名称,其中 n 是一个数字,从 1 开始,表示第 nth 个分区。

控制器编号从 0 开始。挂接到计算实例的单个 NVMe 磁盘的设备名称为 nvme0n1。大多数机器类型使用单个 NVMe 磁盘控制器。因而 NVMe 设备名称为 nvme0n1nvme0n2nvme0n3,依此类推。

对于挂接到第三代机器系列或更高版本实例的本地 SSD 磁盘,每个磁盘都有一个单独的 NVMe 控制器。在这些虚拟机上,本地 SSD NVMe 挂接设备的名称类似于 nvme0n1nvme1n1nvme2n1。挂接的本地 SSD 磁盘的数量取决于虚拟机的机器类型。

基于第三代机器系列或更高版本的计算实例将 NVMe 用于 Persistent Disk 和 Google Cloud Hyperdisk 以及本地 SSD 磁盘。每个虚拟机的 Persistent Disk 和 Hyperdisk 有 1 个 NVMe 控制器,每个本地 SSD 磁盘有 1 个 NVMe 控制器。Persistent Disk 和 Hyperdisk NVMe 控制器对所有挂接的磁盘使用单一的 NVMe 命名空间。因此,具有 1 个 Persistent Disk 和 1 个 Hyperdisk(各自有 2 个分区)和 2 个未格式化的本地 SSD 磁盘的第三代机器系列实例使用以下设备名称:

  • nvme0n1 - Persistent Disk
  • nvme0n1p1
  • nvme0n1p2
  • nvme0n2 - Hyperdisk
  • nvme0n2p1
  • nvme0n2p2
  • nvme1n1 - 第一个本地 SSD
  • nvme2n1 - 第二个本地 SSD

使用永久性设备命名

如需配置永久性设备名称,请在 fstab 文件中为磁盘设备分配装载点名称。您可以通过三种方式配置永久性设备名称。

  • 通过使用标签。此选项要求文件系统支持标签,并且您需要向磁盘分区添加标签。
  • 使用分区或磁盘 UUID。当使用分区表创建磁盘时,系统会生成 UUID,并且每个分区的 UUID 都是唯一的。
  • 通过为 Persistent Disk 或 Google Cloud Hyperdisk 使用永久性磁盘 ID (/dev/disk/by-id),或使用基于磁盘资源名称的symlink

我们建议将分区 UUID 或符号链接用于 Linux 虚拟机。

分区 UUID

如需查找磁盘的 UUID,请执行以下步骤:

  1. 连接到您的虚拟机。
  2. 如果您不知道磁盘的设备名称,则可以使用符号链接查找磁盘设备名称。

    ls -l /dev/disk/by-id/google-*
    

    输出类似于以下内容:

      lrwxrwxrwx 1 root root  9 Oct 23 15:58 /dev/disk/by-id/google-my-vm -> ../../sda
      lrwxrwxrwx 1 root root 10 Oct 23 15:58 /dev/disk/by-id/google-my-vm-part1 -> ../../sda1
      lrwxrwxrwx 1 root root 11 Oct 23 15:58 /dev/disk/by-id/google-my-vm-part15 -> ../../sda15
      lrwxrwxrwx 1 root root  9 Oct 23 15:58 /dev/disk/by-id/google-my-vm-app-data -> ../../nvme0n1
      

  3. 通过运行以下命令之一,检索磁盘分区的 UUID:

    • blkid

      sudo  blkid -s UUID
      

      输出类似于以下内容:

      /dev/sda1: UUID="4f570f2d-fffe-4c7d-8d8f-af347af7612a"
      /dev/sda15: UUID="E0B2-DFAF"
      /dev/nvme0n1: UUID="9e617251-6a92-45ff-ba40-700a9bdeb03e"
      
    • ls -l

      sudo ls -l /dev/disk/by-uuid/
      

      输出类似于以下内容:

      lrwxrwxrwx 1 root root 10 Sep 22 18:12 4f570f2d-fffe-4c7d-8d8f-af347af7612a -> ../../sda1
      lrwxrwxrwx 1 root root 13 Sep 22 18:15 9e617251-6a92-45ff-ba40-700a9bdeb03e -> ../../nvme0n1
      lrwxrwxrwx 1 root root 11 Sep 22 18:12 E0B2-DFAF -> ../../sda15
      
  4. /etc/fstab 文件中为设备的 UUID 添加一个条目。

    UUID=9e617251-6a92-45ff-ba40-700a9bdeb03e /data ext4 defaults 0 0
    

    在此示例中,/data 是装载点,ext4 是文件系统类型。

  5. 运行 mount -av 以验证设备已正确装载。

    sudo mount -av

    如果设备已成功装载,则输出类似于以下内容:

    /                           : ignored
    /boot/efi                : already mounted
    mount: /data does not contain SELinux labels.
    You just mounted an file system that supports labels which does not
    contain labels, onto an SELinux box. It is likely that confine
    applications will generate AVC messages and not be allowed access to
    this filesystem.  For more details see restorecon(8) and mount(8).
    /data                    : successfully mounted
    

永久性磁盘 ID

如需使用永久性磁盘 ID 或符号链接查找磁盘设备名称,请完成以下步骤:

  1. 连接到您的虚拟机。
  2. 通过运行以下命令来检索磁盘上的 ID:

    sudo  ls -lh /dev/disk/by-id/google-*

    输出类似于以下内容:

    lrwxrwxrwx. 1 root root  9 May 16 17:34 google-disk-2 -> ../../sdb
    lrwxrwxrwx. 1 root root  9 May 16 09:09 google-persistent-disk-0 -> ../../sda
    lrwxrwxrwx. 1 root root 10 May 16 09:09 google-persistent-disk-0-part1 -> ../../sda1
    lrwxrwxrwx. 1 root root 10 May 16 09:09 google-persistent-disk-0-part2 -> ../../sda2
    

    对于 NVME 磁盘,输出类似于以下内容:

    lrwxrwxrwx 1 root root 13 Jun  1 10:27 google-disk-3 -> ../../nvme0n2
    lrwxrwxrwx 1 root root 13 Jun  1 10:25 google-t2a -> ../../nvme0n1
    lrwxrwxrwx 1 root root 15 Jun  1 10:25 google-t2a-part1 -> ../../nvme0n1p1
    lrwxrwxrwx 1 root root 16 Jun  1 10:25 google-t2a-part15 -> ../../nvme0n1p15
    
  3. 将符号链接添加到 /etc/fstab 文件。

    /dev/disk/by-id/google-disk-2 /data ext4 defaults 0 0
    
  4. 运行 mount -av 以验证设备已正确装载。

    sudo mount -av

    如果设备已成功装载,则输出类似于以下内容:

    /                           : ignored
    /boot/efi                : already mounted
    mount: /data does not contain SELinux labels.
    You just mounted an file system that supports labels which does
    not contain labels, onto an SELinux box. It is likely that confine
    applications will generate AVC messages and not be allowed access to this
    file system.  For more details see restorecon(8) and mount(8).
    /data                    : successfully mounted