将磁盘添加到 Linux VM

本文介绍了如何将持久性磁盘附加到 VM 以便持久保存数据 - 即使 VM 由于维护或调整大小而重新预配。

Note

在 Azure 中国区使用 Azure CLI 2.0 之前,请先运行 az cloud set -n AzureChinaCloud 来改变云环境。如果想切回国际版 Azure,请再次运行 az cloud set -n AzureCloud

使用托管磁盘

Azure 托管磁盘通过管理与 VM 磁盘关联的存储帐户简化了 Azure VM 的磁盘管理。 你只需指定所需的类型(“高级”或“标准”)和磁盘大小,Azure 将创建和管理磁盘。 有关详细信息,请参阅托管磁盘概述

将新磁盘附加到 VM

如果只需要 VM 上的新磁盘,请使用 az vm disk attach 命令以及 --new 参数。 如果 VM 位于某个可用性区域中,则会自动在与 VM 相同的区域中创建磁盘。 以下示例创建一个名为 myDataDisk 且大小为 50 GB 的磁盘:

az vm disk attach -g myResourceGroup --vm-name myVM --disk myDataDisk \
  --new --size-gb 50

附加现有磁盘

在许多情况下, 你会附加已创建的磁盘。 若要附加现有磁盘,请查找磁盘 ID 并将该 ID 传递到 az vm disk attach 命令。 以下示例查询 myResourceGroup 中名为 myDataDisk 的磁盘,然后将其附加到名为 myVM 的 VM:

# find the disk id
diskId=$(az disk show -g myResourceGroup -n myDataDisk --query 'id' -o tsv)
az vm disk attach -g myResourceGroup --vm-name myVM --disk $diskId

输出类似于以下形式(可将 -o table 选项用于任何命令来设置输出格式):

{
  "accountType": "Standard_LRS",
  "creationData": {
    "createOption": "Empty",
    "imageReference": null,
    "sourceResourceId": null,
    "sourceUri": null,
    "storageAccountId": null
  },
  "diskSizeGb": 50,
  "encryptionSettings": null,
  "id": "/subscriptions/<guid>/resourceGroups/rasquill-script/providers/Microsoft.Compute/disks/myDataDisk",
  "location": "chinanorth",
  "name": "myDataDisk",
  "osType": null,
  "ownerId": null,
  "provisioningState": "Succeeded",
  "resourceGroup": "myResourceGroup",
  "tags": null,
  "timeCreated": "2017-02-02T23:35:47.708082+00:00",
  "type": "Microsoft.Compute/disks"
}

使用非托管磁盘

非托管磁盘需要额外的开销来创建和管理基础存储帐户。 非托管磁盘是在与 OS 磁盘相同的存储帐户中创建的。 若要创建并附加非托管磁盘,请使用 az vm unmanaged-disk attach 命令。 以下示例将一个 50GB 的非托管磁盘附加到名为 myResourceGroup 的资源组中名为 myVM 的 VM:

az vm unmanaged-disk attach -g myResourceGroup -n myUnmanagedDisk --vm-name myVM \
  --new --size-gb 50

连接到 Linux VM 以装入新磁盘

若要对新磁盘进行分区、格式化和装载,以便 Linux VM 可以使用它,请通过 SSH 登录到 Azure VM。 有关详细信息,请参阅如何在 Azure 中将 SSH 用于 Linux。 以下示例使用公共 DNS 条目 mypublicdns.chinanorth.cloudapp.chinacloudapi.cn 和用户名 azureuser 连接到一个 VM:

ssh azureuser@mypublicdns.chinanorth.cloudapp.chinacloudapi.cn

连接到 VM 后就可以附加磁盘了。 首先,使用 dmesg 来查找磁盘(用于发现新磁盘的方法可能各不相同)。 以下示例使用 dmesg 来筛选 SCSI 磁盘:

dmesg | grep SCSI

输出类似于以下示例:

[    0.294784] SCSI subsystem initialized
[    0.573458] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 252)
[    7.110271] sd 2:0:0:0: [sda] Attached SCSI disk
[    8.079653] sd 3:0:1:0: [sdb] Attached SCSI disk
[ 1828.162306] sd 5:0:0:0: [sdc] Attached SCSI disk

此处,sdc 是我们需要的磁盘。 使用 fdisk 对磁盘进行分区,将其设置为分区 1 中的主磁盘,并接受其他默认值。 以下示例在 /dev/sdc 上启动 fdisk 进程:

sudo fdisk /dev/sdc

输出类似于以下示例:

Device contains neither a valid DOS partition table, nor Sun, SGI or OSF disklabel
Building a new DOS disklabel with disk identifier 0x2a59b123.
Changes will remain in memory only, until you decide to write them.
After that, of course, the previous content won't be recoverable.

Warning: invalid flag 0x0000 of partition table 4 will be corrected by w(rite)

Command (m for help): n
Partition type:
   p   primary (0 primary, 0 extended, 4 free)
   e   extended
Select (default p): p
Partition number (1-4, default 1): 1
First sector (2048-10485759, default 2048):
Using default value 2048
Last sector, +sectors or +size{K,M,G} (2048-10485759, default 10485759):
Using default value 10485759

在提示符下键入 p 来创建分区,如下所示:

Command (m for help): p

Disk /dev/sdc: 5368 MB, 5368709120 bytes
255 heads, 63 sectors/track, 652 cylinders, total 10485760 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x2a59b123

   Device Boot      Start         End      Blocks   Id  System
/dev/sdc1            2048    10485759     5241856   83  Linux

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.
Syncing disks.

现在,使用 mkfs 命令将文件系统写入到该分区。 指定文件系统类型和设备名称。 以下示例在通过前面的步骤创建的 /dev/sdc1 分区中创建 ext4 文件系统:

sudo mkfs -t ext4 /dev/sdc1

输出类似于以下示例:

mke2fs 1.42.9 (4-Feb-2014)
Discarding device blocks: done
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
327680 inodes, 1310464 blocks
65523 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=1342177280
40 block groups
32768 blocks per group, 32768 fragments per group
8192 inodes per group
Superblock backups stored on blocks:
    32768, 98304, 163840, 229376, 294912, 819200, 884736
Allocating group tables: done
Writing inode tables: done
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done

现在,使用 mkdir 创建一个目录来装载文件系统。 以下示例在 /datadrive 处创建一个目录:

sudo mkdir /datadrive

然后,使用 mount 来装载文件系统。 以下示例将 /dev/sdc1 分区装载到 /datadrive 装入点:

sudo mount /dev/sdc1 /datadrive

若要确保在重新引导后自动重新装载驱动器,必须将其添加到 /etc/fstab 文件。 此外,强烈建议在 /etc/fstab 中使用 UUID(全局唯一标识符)来引用驱动器而不是只使用设备名称(例如 /dev/sdc1)。 如果 OS 在启动过程中检测到磁盘错误,使用 UUID 可以避免将错误的磁盘装载到给定位置。 然后为剩余的数据磁盘分配这些设备 ID。 若要查找新驱动器的 UUID,请使用 blkid 实用工具:

sudo -i blkid

输出与以下示例类似:

/dev/sda1: UUID="11111111-1b1b-1c1c-1d1d-1e1e1e1e1e1e" TYPE="ext4"
/dev/sdb1: UUID="22222222-2b2b-2c2c-2d2d-2e2e2e2e2e2e" TYPE="ext4"
/dev/sdc1: UUID="33333333-3b3b-3c3c-3d3d-3e3e3e3e3e3e" TYPE="ext4"

Note

错误地编辑 /etc/fstab 文件可能会导致系统无法引导。 如果没有把握,请参考分发的文档来获取有关如何正确编辑该文件的信息。 另外,建议在编辑前备份 /etc/fstab 文件。

接下来,在文本编辑器中打开 /etc/fstab 文件,如下所示:

sudo vi /etc/fstab

在此示例中,我们将使用在之前的步骤中创建的 /dev/sdc1 设备的 UUID 值并使用装入点 /datadrive。 将以下行添加到 /etc/fstab 文件的末尾:

UUID=33333333-3b3b-3c3c-3d3d-3e3e3e3e3e3e   /datadrive   ext4   defaults,nofail   1   2

Note

之后,在不编辑 fstab 的情况下删除数据磁盘可能会导致 VM 无法启动。 大多数分发版都提供 nofail 和/或 nobootwait fstab 选项。 这些选项使系统在磁盘无法装载的情况下也能启动。 有关这些参数的详细信息,请查阅分发文档。

即使文件系统已损坏或磁盘在引导时不存在, nofail 选项也能确保 VM 启动。 如果不使用此选项,可能会遇到 Cannot SSH to Linux VM due to FSTAB errors

Azure 中对 Linux 的 TRIM/UNMAP 支持

某些 Linux 内核支持 TRIM/UNMAP 操作以放弃磁盘上未使用的块。 此功能主要用于标准存储中,如果你创建大型文件后又将其删除,则该功能将通知 Azure 已删除的页不再有效并且可以丢弃,可以节省成本。

在 Linux VM 中有两种方法可以启用 TRIM 支持。 与往常一样,有关建议的方法,请参阅分发:

  • /etc/fstab 中使用 discard 装载选项,例如:

    UUID=33333333-3b3b-3c3c-3d3d-3e3e3e3e3e3e   /datadrive   ext4   defaults,discard   1   2
    
  • 在某些情况下,discard 选项可能会影响性能。 此处,还可以从命令行手动运行 fstrim 命令,或将其添加到 crontab 以定期运行:

    Ubuntu

    sudo apt-get install util-linux
    sudo fstrim /datadrive
    

    RHEL/CentOS

    sudo yum install util-linux
    sudo fstrim /datadrive
    

故障排除

将数据磁盘添加到 Linux VM 时,如果 LUN 0 位置没有磁盘,则你可能会遇到错误。 如果你使用 azure vm disk attach-new 命令并指定 LUN (--lun) 来手动添加磁盘,而不是让 Azure 平台确定适当的 LUN,则请注意,LUN 0 已经有磁盘或者将有磁盘。

请考虑以下示例,其中显示了 lsscsi 输出的代码片段:

[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 0 和 LUN 1(lsscsi 中的第一列输出了详细信息 [host:channel:target:lun])。 两个磁盘应该都是可从 VM 内部访问的磁盘。 如果你手动指定了要在 LUN 1 位置添加第一个磁盘并在 LUN 2 位置添加第二个磁盘,则可能无法从 VM 内部正常查看这些磁盘。

Note

在这些示例中,Azure host 值为 5,但此值可能根据所选存储类型的不同而异。

此磁盘行为不是 Azure 的问题,而是因为 Linux 内核遵循了 SCSI 规范。 当 Linux 内核在 SCSI 总线中扫描附加的设备时,必须能够在 LUN 0 位置找到设备,系统才能继续扫描是否有其他设备。 因此:

  • 在添加数据磁盘之后,请查看 lsscsi 的输出,验证 LUN 0 位置是否有磁盘。
  • 如果磁盘未在 VM 内正确显示,请验证 LUN 0 位置是否有磁盘。

后续步骤

  • 请记住,除非将该信息写入 fstab 文件,否则即使重新启动 VM,新磁盘也无法供 VM 使用。
  • 为确保正确配置 Linux VM,请查看有关优化 Linux 计算机性能的建议。
  • 可以添加更多的磁盘来扩展存储容量,配置 RAID 来提高性能。