本文介绍了有关在 Azure 中创建的虚拟机(VM)上对临时非易失性内存 Express(NVMe)磁盘的支持的一些常见问题。 在本文中,术语“临时磁盘”指的是在本地 SSD 上创建的临时磁盘。
为 VM 创建使用 NVMe 接口的临时磁盘的先决条件是什么?
对本地临时磁盘的 NVMe 支持在虚拟机(VM)系列级别有所不同。 所有具有本地磁盘的新 v6 VM 都支持 NVMe 临时磁盘,但 v5 VM 和早期版本可能不支持 NVMe 本地临时磁盘,因为这些大小中的大多数本地磁盘都位于 SCSI 接口上。 某些 VM 系列(如 L 系列)从 Lsv2 代 VM 开始本地附加 NVMe SSD。 请参阅 VM 系列概述,确定 NVMe 临时磁盘是否受支持。 此外,请注意,来宾 OS 需要提供 NVMe 驱动程序支持才能使用本地 NVMe,默认情况下,大多数最新的 OS 版本都有。
我的 Dl/D/E_v6 VM 中的临时 NVMe 磁盘与远程 NVMe 磁盘有何不同?
临时 NVMe 磁盘和远程 NVMe 磁盘之间的主要差异在于,前者是暂时性的,VM 上的数据可能会消失,但后者上的数据会保留。 选择 VM 的存储选项时,请考虑到这种差异。
与以前的 D/E 系列 VM 不同,新的 v6 VM 附带原始的未格式化 NVMe 磁盘。 客户应在 VM 启动后将磁盘初始化并格式化为他们首选的文件系统。
Dl/D/E v6 系列 VM 经过优化,可使用直接附加到 VM 的节点上的本地临时 NVMe 磁盘,而不是以前使用的本地小型计算机系统接口 (SCSI) 磁盘。 此方法允许每秒执行更高的输入/输出操作,并为工作负荷提供更高的吞吐量。
使用临时 NVMe 磁盘配置 VM 时,应为哪些更改做好准备?
启动 VM 后,应初始化和格式化磁盘。 用户启动停止、解除分配或计划内维护和 Azure 启动的自动恢复事件后,VM 将仅使用原始临时 NVMe 磁盘启动。 在初始化和格式化应用程序之前,应用程序不会看到任何临时 NVMe 磁盘。
可以在 VM 启动时根据需要将单独的 NVMe 驱动器跨入一个驱动器。
Windows 页面文件放置在永久性 OS 磁盘上(除非使用临时 OS 功能),但可以在 VM 启动时根据需要将其移动到临时 NVMe 磁盘。
如果使用了临时 OS 功能,则它会将一个或多个 NVMe 磁盘(具体取决于 VM 和图像大小)转换为基于 SCSI/VHD 的较慢磁盘,类似于它在 v5 和更旧的 VM 上的样子。 对于更大的 VM 大小,剩余驱动器将保持为原始未格式化 NVMe。
REST API 中的资源库存保留单位(SKU)列表公开了虚拟机的多个功能。 VM 大小的下一次迭代使用更快、更高效的 NVMe 协议进行本地存储,而不是早期 VM 大小使用的 SCSI 协议。
对于 Azure 虚拟机,基于 SCSI 的本地存储是临时资源磁盘,
MaxResourceVolumeMB
值会指定此磁盘的大小。 相比之下,NVMeDiskSizeInMiB
值会指定基于 NVMe 的本地存储的大小。
Azure 为临时 NVMe 磁盘提供的最低加密是什么?
默认情况下,Azure 虚拟机(VM)上的所有本地 NVMe 磁盘都启用了内置加密以实现数据保护。 临时 NVMe 磁盘支持静态数据加密功能。 唯一的数据加密密钥 (DEK) 对分配给 VM 的每个临时 NVMe 磁盘的数据进行加密。 密钥加密密钥 (KEK) 有助于保护 DEK。 删除 VM 时,会加密擦除其临时 NVMe 磁盘上的数据。 在 2024 年及之后引入的所有 v6 VM 默认使用基于硬件的加密和平台管理的密钥加密其本地 NVME 驱动器。
- 使用 XTS-AES-256、AES-256-GCM 或更强的密码对数据进行加密。
- 设备为 VM 中的每个磁盘生成唯一的媒体加密密钥(MEK)。
- MEK 为:
- 生成并完全存储在设备硬件中。
- 从不向主机、VM 或任何外部组件(包括作员或 Azure 系统)公开。
- 所有加密和解密作都使用 MEK 在设备中进行。
- 删除 VM 时,MEK 会销毁,确保之后没有组件可以访问数据。
什么是静态增强加密?
增强静态加密是 Azure V6 系列和 Lsv4 系列 VM 上通过对 TCG-OPAL 标准的支持提供的另一层保护。 无需对此功能执行任何作,这是这些 VM 类型的默认值。
- PIN 值由 Azure 基础结构为每个 MEK 生成并安全地存储。
- PIN 通过存储设备中的密钥派生函数(KDF)传递,以生成密钥加密密钥(KEK)。 PIN 充当平台管理密钥(PMK)。
- MEK 使用 KEK 进行加密,并存储在存储设备内部。
- KEK 不会存储在任何位置,并且当 PIN 用于成功对其进行身份验证时,由存储设备动态生成。 如果没有此 PIN,设备将无法解密其自己的存储数据,即使以物理方式访问也是如此。
- 当 VM 启动并锁定 VM 时,存储设备会进行身份验证,从而确保仅在 VM 运行时访问数据才可用。
如何将具有临时磁盘的 v5 或更早的 VM 重设为 v6 的大小?
如何识别临时 NVMe 磁盘?
可以在 Windows 上运行以下命令:
Get-PhysicalDisk | where { $_.FriendlyName.contains("NVMe Direct Disk")}
可以在 Linux 上运行以下命令:
sudo nvme id-ns /dev/nvme0n1 -b | dd bs=1 skip=384 status=none | sed 's/\x00*$//'
如何在创建 VM 时格式化和初始化 Windows 中的临时 NVMe 磁盘?
可以使用 GUI 或 Azure PowerShell。
图形用户界面
提示
下面的 GUI 示例用于说明目的。 建议创建脚本以自动执行此工作流以用于生产部署。
选择 Windows 徽标键 + R 以打开“运行”对话框。 键入 diskmgmt.msc 并选择 Enter 键。
选择分区样式(MBR 或 GPT)和要初始化的磁盘,然后选择“确定”。
右键单击要分区的磁盘,然后选择“新建简单卷”。
要指定卷大小、驱动器号、文件系统、卷标签等项,请遵循“新建简单卷向导”。 选择“下一步”按钮以继续执行向导。
若要完成分区和格式设置,请查看设置,并选择“完成”。
确认格式化和初始化的 NVMe 磁盘显示在 Windows 磁盘管理工具中,这与本示例中 新卷 (E:) 的显示方式类似。
Azure PowerShell 脚本
提示
以下脚本初始化、格式化和分配驱动器号。 但是,它会擦除磁盘上的所有数据。 在生产环境中部署之前,应在 VM 上对其进行全面测试。
# Select the raw NVMe disks to partition and format
$RawNvmeDisks = Get-PhysicalDisk -CanPool $True | where { $_.FriendlyName.contains("NVMe Direct Disk")}
# Create a pool of the existing disks
New-StoragePool -FriendlyName NVMePool -StorageSubsystemFriendlyName "Windows Storage*" -PhysicalDisks $RawNvmeDisks -ResiliencySettingNameDefault Simple
#Create a new disk, initialize, partition, and format
$Disk = New-VirtualDisk -FriendlyName NVMeTemporary -StoragePoolFriendlyName NVMePool -NumberOfColumns @($RawNvmeDisks).count -PhysicalDiskRedundancy 0 -ResiliencySettingName "Simple" -UseMaximumSize
$Disk | Initialize-Disk
#Create a partition and format. Ignore the pop-up.
New-Partition -DiskId $Disk.UniqueId -AssignDriveLetter -UseMaximumSize | Format-Volume
如何在 Linux 中格式化和初始化临时 NVMe 磁盘?
以下脚本提供了在 Linux 中初始化临时 NVMe 磁盘的示例。 该脚本会枚举 VM 上的所有临时 NVMe 磁盘,将磁盘合并为单个 RAID 0 阵列,并创建指定文件系统的格式化分区。
临时 NVMe 磁盘可以按模型号进行区分,它显示为来宾 OS 的“Microsoft NVMe Direct Disk
”。 此脚本使用 nvme-cli id-ctrl
命令查询每个 NVMe 设备的型号。
该脚本首先检查任何已创建的临时 NVMe 磁盘卷(由 filesystem
标签标识)。 如果数组似乎存在,脚本将验证数组的完整性,并在必要时重复初始化过程。 在以下情况下,将重新初始化数组:
- 缺少一个或多个数组临时磁盘。
- 有尚未合并到数组中的临时磁盘。
- 磁盘数组处于无效或未知状态。
- 关联的配置文件缺失或无效。
#!/bin/bash
# Script requirements:
# nvme-cli
# mdadm
# gdisk
readonly USAGE="Usage: $(basename "$0") <filesystem> <filesystem mount point (optional)>"
# Label used to identify the NVMe array file system and associated disks
# Can't exceed 16 characters
readonly RAID0_FILESYSTEM_LABEL="azure_nvme_temp"
# Device path used for the RAID 0 NVMe array
# Choose any unoccupied device path of format /dev/mdX (X = 0 to 99)
readonly RAID0_DEVICE_PATH="/dev/md0"
# Formatted RAID 0 partition is mounted here
readonly DEFAULT_MOUNT_POINT="/mnt/${RAID0_FILESYSTEM_LABEL}"
filesystem="$1"
if [ ! "$filesystem" ]; then
printf "No filesystem specified. Usage: $USAGE\n"
exit 1
fi
if ! [ -x "$(command -v mkfs.$filesystem)" ]; then
printf "Filesystem \"$filesystem\" not supported by mkfs\n$USAGE\n"
exit 1
fi
mount_point="$2"
if [ ! "$mount_point" ]; then
printf "No mount point specified. Using default: $DEFAULT_MOUNT_POINT\n"
mount_point=$DEFAULT_MOUNT_POINT
fi
# Make sure mdadm.conf is present
mdadm_conf_path=""
if [ -e "/etc/mdadm/mdadm.conf" ]; then
mdadm_conf_path="/etc/mdadm/mdadm.conf"
elif [ -e "/etc/mdadm.conf" ]; then
mdadm_conf_path="/etc/mdadm.conf"
else
print "Couldn't find mdadm.conf file"
exit 1
fi
# Enumerate unmounted NVMe direct disks
devices=$(lsblk -p -o NAME,TYPE,MOUNTPOINT | grep "nvme" | awk '$2 == "disk" && $3 == "" {print $1}')
nvme_direct_disks=()
for device in $devices
do
if nvme id-ctrl "$device" | grep -q "Microsoft NVMe Direct Disk"; then
nvme_direct_disks+=("$device")
fi
done
nvme_direct_disk_count=${#nvme_direct_disks[@]}
printf "Found $nvme_direct_disk_count NVMe Direct Disks\n"
# Check if there's already an NVMe Direct Disk RAID 0 disk (or remnant data)
if grep "$RAID0_FILESYSTEM_LABEL" /etc/fstab > /dev/null; then
fstab_entry_present=true
fi
if grep "$RAID0_FILESYSTEM_LABEL" $mdadm_conf_path > /dev/null; then
mdadm_conf_entry_present=true
fi
if [ -e $RAID0_DEVICE_PATH ]; then
nvme_raid0_present=true
fi
if [ "$fstab_entry_present" = true ] || [ "$mdadm_conf_entry_present" = true ] || [ "$nvme_raid0_present" = true ]; then
# Check if the RAID 0 volume and associated configurations are still intact or need to be reinitialized
#
# If reinitialization is needed, clear the old RAID 0 information and associated files
reinit_raid0=false
if [ "$fstab_entry_present" = true ] && [ "$mdadm_conf_entry_present" = true ] && [ "$nvme_raid0_present" = true ]; then
# Check RAID 0 device status
if ! mdadm --detail --test $RAID0_DEVICE_PATH &> /dev/null; then
reinit_raid0=true
# Test the NVMe direct disks for valid mdadm superblocks
else
for device in "${nvme_direct_disks[@]}"
do
if ! mdadm --examine $device &> /dev/null; then
reinit_raid0=true
break
fi
done
fi
else
reinit_raid0=true
fi
if [ "$reinit_raid0" = true ]; then
echo "Errors found in NVMe RAID 0 temp array device or configuration. Reinitializing."
# Remove the file system and partition table, and stop the RAID 0 array
if [ "$nvme_raid0_present" = true ]; then
if [ -e ${RAID0_DEVICE_PATH}p1 ]; then
umount ${RAID0_DEVICE_PATH}p1
wipefs -a -f ${RAID0_DEVICE_PATH}p1
fi
sgdisk -o $RAID0_DEVICE_PATH &> /dev/null
mdadm --stop $RAID0_DEVICE_PATH
fi
# Remove any mdadm metadata from all NVMe Direct Disks
for device in "${nvme_direct_disks[@]}"
do
printf "Clearing mdadm superblock from $device\n"
mdadm --zero-superblock $device &> /dev/null
done
# Remove any associated entries in fstab and mdadm.conf
sed -i.bak "/$RAID0_FILESYSTEM_LABEL/d" /etc/fstab
sed -i.bak "/$RAID0_FILESYSTEM_LABEL/d" $mdadm_conf_path
else
printf "Valid NVMe RAID 0 array present and no additional Direct Disks found. Skipping\n"
exit 0
fi
fi
if [ "$nvme_direct_disk_count" -eq 0 ]; then
printf "No NVMe Direct Disks found\n"
exit 1
elif [ "$nvme_direct_disk_count" -eq 1 ]; then
additional_mdadm_params="--force"
fi
# Initialize enumerated disks as RAID 0
printf "Creating RAID 0 array from:\n"
printf "${nvme_direct_disks[*]}\n\n"
if ! mdadm --create $RAID0_DEVICE_PATH --verbose $additional_mdadm_params --name=$RAID0_FILESYSTEM_LABEL --level=0 --raid-devices=$nvme_direct_disk_count ${nvme_direct_disks[*]}; then
printf "Failed to create RAID 0 array\n"
exit 1
fi
# Create a GPT partition entry
readonly GPT_PARTITION_TYPE_GUID="0FC63DAF-8483-4772-8E79-3D69D8477DE4"
printf "\nCreating GPT on $RAID0_DEVICE_PATH..\n"
sgdisk -o $RAID0_DEVICE_PATH &> /dev/null
if ! sgdisk --new 1::0 --typecode 1:$GPT_PARTITION_TYPE_GUID $RAID0_DEVICE_PATH &> /dev/null; then
printf "Failed to create partition on $RAID0_DEVICE_PATH\n"
exit 1
fi
# Format the partition
partition_path="${RAID0_DEVICE_PATH}p1"
printf "\nCreating $filesystem filesystem..\n"
if ! mkfs.$filesystem -q -L $RAID0_FILESYSTEM_LABEL $partition_path; then
printf "Failed to create $filesystem filesystem\n"
exit 1
fi
printf "The operation has completed successfully.\n"
# Add the partition to /etc/fstab
echo "LABEL=$RAID0_FILESYSTEM_LABEL $mount_point $filesystem defaults,nofail 0 0" >> /etc/fstab
# Add RAID 0 array to mdadm.conf
mdadm --detail --scan >> $mdadm_conf_path
update-initramfs -u
# Mount the partition
printf "\nMounting filesystem to $mount_point..\n"
mkdir $mount_point &> /dev/null
if ! mount -a; then
printf "Failed to automount partition\n"
exit 1
fi
printf "The operation has completed successfully.\n"
exit 0
如何将 Windows 页面文件从 OS 磁盘移动到临时 NVMe 磁盘?
可以使用 GUI 或 Azure PowerShell。
图形用户界面
提示
下面的 GUI 示例用于说明目的。 建议创建脚本以自动执行此工作流以用于生产部署。
选择 Windows 徽标键 + R 以打开“运行”对话框。 键入 sysdm.cpl 并选择 Enter 键。
选择“高级”选项卡,然后选择“性能”部分中的“设置”按钮。
在“性能选项”对话框中,选择“高级”选项卡,然后选择“虚拟内存”部分中的“更改”按钮。
清除“自动管理所有驱动器的页面文件大小”复选框。 如果页面文件设置为 OS 磁盘,请选择 OS 磁盘,选择“无分页文件”选项,然后选择“设置”按钮。 选择本地临时 NVMe 驱动器,选择“系统托管大小”选项,然后选择“设置”按钮。 选择“确定”关闭所有对话框。
你可能需要重启 VM 才能使这些更改生效。
Azure PowerShell 脚本
$OsDisk = "C:"
# This value can vary, depending on which drive letter is assigned to the disk
$NVMeDisk = "E:"
# Disable automatic pagefile management
$Computer = Get-WmiObject Win32_computersystem -EnableAllPrivileges
$Computer.AutomaticManagedPagefile = $false
$Computer.Put()
# Delete the pagefile on the OS disk
$PageFile = Get-WmiObject -Query "select * from Win32_PageFileSetting where name='$OsDisk\\pagefile.sys'"
$PageFile.Delete()
# Create a new pagefile on the NVMe drive with system-managed size
Set-WMIInstance -Class Win32_PageFileSetting -Arguments @{name="$NVMeDisk\\pagefile.sys"; InitialSize=0; MaximumSize=0} -EnableAllPrivileges
你可能需要重启 VM 才能使这些更改生效。
如何将 Linux 交换文件从 OS 磁盘移动到临时 NVMe 磁盘?
选择用于交换空间的 NVMe 磁盘:
root@D2adsv6:/ # lsblk -p NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT /dev/nvme1n1 259:0 0 30G 0 disk ├─/dev/nvme1n1p1 259:1 0 29.9G 0 part / └─/dev/nvme1n1p15 259:3 0 106M 0 part /boot/efi /dev/nvme0n1 259:4 0 75G 0 disk
在磁盘上创建交换空间:
root@D2adsv6:/ # mkswap /dev/nvme0n1 Setting up swapspace version 1, size = 75 GiB (80530632704 bytes) no label, UUID=064bdcfb-86ae-49f3-bf9d-b956493e2a1d
启用交换空间:
root@D2adsv6:/ # swapon /dev/nvme0n1
检查交换空间是否已正确设置:
root@D2adsv6:/ # swapon -s Filename Type Size Used Priority /dev/nvme0n1 partition 78643196 0 -2
将交换空间追加到
/etc/fstab
使其在重启后保持持久:root@D2adsv6:/ # echo '/dev/nvme0n1 swap swap defaults 0 0' >> /etc/fstab
对于维护事件、VM 重新部署和 VM 重启,需要注意哪些事项?
附加到 V6 VM 的临时 NVMe 磁盘是暂时性的,类似于其他 VM 系列上的临时驱动器。 这意味着在重新部署之后或维护事件期间,VM 上所有数据都将丢失。 有关维护事件和停机时间的详细信息,请参阅“了解 VM 重启:维护与停机”。
如果 VM 移动到新硬件,则备份时,这些驱动器会向操作系统显示卸载磁盘和新卸载的磁盘。 如果 VM 未更改硬件,则临时 NVMe 磁盘可能仍然存在。 在尝试装载驱动器之前,用于装载驱动器的上述脚本会检查未装载的驱动器。
最佳做法是每次 VM 启动时自动运行装载脚本,并延迟任何其他需要驱动器的启动脚本,直到装载脚本完成运行。