縮減Azure上Linux虛擬機器系統盤容量

大魔王mAysWINd發表於2021-08-09

【話在前頭】

這麼些年微軟 Azure 建立虛擬機器一直不能修改系統盤大小,但很多時候實際又用不了這麼大的作業系統磁碟。微軟自己甚至還針對 Windows 伺服器映象推出一個 smalldisk 的映象版本(https://azure.microsoft.com/en-us/blog/new-smaller-windows-server-iaas-image/),在原有 127GB 的映象外提供一個 32GB 版本的作業系統映象,可以根據自己的需要進行擴容。但是 Azure 提供的 Linux 伺服器映象卻都是 30GB 的版本,網上其他人的解決辦法通常是下載磁碟 vhd 檔案,然後本地開啟後用 Hyper-V 進行縮小後再上傳,或者直接用 Azure 的儲存賬戶進行線上編輯 vhd 檔案(見相關連結12)。本文通過建立小容量磁碟,直接複製磁碟分割槽的方式來解決這個問題。

 

【文章索引】

  1. 縮減作業系統分割槽容量
  2. 複製分割槽到小容量磁碟
  3. 修改小容量磁碟配置
  4. 相關連結

 

【一、縮減作業系統分割槽容量】

Azure 支援修改託管磁碟的容量,但是隻支援擴大,不支援縮小,如果調整磁碟大小時設定了比之前更小的容量,則會提示下圖所示的內容。

首先,與其他方案相同,需要先準備一份已縮減分割槽容量的系統盤。Linux 不像 Windows 提供了磁碟管理工具,可以線上縮減系統盤容量,需要建立一個當前作業系統磁碟的副本並掛載到系統上進行調整。這裡先對當前系統盤建立一份快照,如下圖。

然後對這個快照建立磁碟,如下圖。

完成後就可以將建立好的系統盤副本附加到虛擬機器中,同時再附加一個小容量的空磁碟用於建立最終的小容量系統盤。

由於複製後的磁碟分割槽的Uuid與之前的磁碟分割槽完全一樣,所以如果在虛擬機器啟動前附加的磁碟,虛擬機器啟動後根目錄(/)掛載點會被後附加的這塊磁碟掛載,所以如果要縮減分割槽需要對第一塊磁碟(/dev/sda)進行操作;反之如果是虛擬機器啟動後附加的磁碟,根目錄掛載點還是第一塊磁碟(/dev/sda1),如果要縮減分割槽需要對後掛載的磁碟(/dev/sdc 或 /dev/sdd)進行操作。

這裡以啟動後附加磁碟為例,小容量空磁碟是 /dev/sdc,作業系統副本磁碟是 /dev/sdd。首先需要縮減檔案系統容量,分別執行“e2fsck”和“resize2fs”,其中“resize2fs”設定的大小不能大於後續分割槽的大小,如果不確認後續使用的各個工具的單位,這裡也可以故意設定小一些,如下

root@xxx-vm:/tmp# e2fsck -f /dev/sdd1
e2fsck 1.44.5 (15-Dec-2018)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/sdd1: 26148/1957888 files (0.2% non-contiguous), 365215/7831547 blocks
root@xxx-vm:/tmp# resize2fs /dev/sdd1 3G
resize2fs 1.44.5 (15-Dec-2018)
Resizing the filesystem on /dev/sdd1 to 786432 (4k) blocks.
The filesystem on /dev/sdd1 is now 786432 (4k) blocks long.

然後可以使用 parted 或 fdisk 進行分割槽的調整,個人覺得 parted 更簡單一些,一條命令即可修改,不像 fdisk 需要還需要先刪除再建立,如下

root@xxx-vm:/tmp# parted /dev/sdd
GNU Parted 3.2
Using /dev/sdd
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) print
Warning: Not all of the space available to /dev/sdd appears to be used, you can fix the GPT to use all of the space (an extra 4194304 blocks) or continue with the current setting?
Fix/Ignore? Ignore
Model: Msft Virtual Disk (scsi)
Disk /dev/sdd: 34.4GB
Sector size (logical/physical): 512B/4096B
Partition Table: gpt
Disk Flags:

Number  Start   End     Size    File system  Name  Flags
14      1049kB  4194kB  3146kB                     bios_grub
15      4194kB  134MB   130MB   fat16              boot, esp
 1      134MB   32.2GB  32.1GB  ext4

(parted) resizepart 1 4G
Warning: Shrinking a partition can cause data loss, are you sure you want to continue?
Yes/No? Yes
(parted)
Information: You may need to update /etc/fstab.

完成後可以用 mount 掛載一下分割槽進行驗證,看看是否能進行正常掛載以及檔案系統容量是否符合預期。

 

【二、複製分割槽到小容量磁碟】

在第一步確認沒問題後可以將上述磁碟內的內容複製到小容量磁碟中,這裡使用 fdisk 把調小分割槽容量的磁碟分割槽表備份下來,如下

root@xxx-vm:/tmp# fdisk /dev/sdd

Welcome to fdisk (util-linux 2.33.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

The backup GPT table is not on the end of the device. This problem will be corrected by write.

Command (m for help): O

Enter script file name: os-disk-pt

Script successfully saved.

Command (m for help): q

然後修改分割槽表備份檔案 os-disk-pt 檔案中 last-lba 的值為小容量磁碟的最後一個扇區,然後用 fdisk 對小容量磁碟匯入該分割槽表即可,如下

root@xxx-vm:/tmp# fdisk /dev/sdc

Welcome to fdisk (util-linux 2.33.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Device does not contain a recognized partition table.
Created a new DOS disklabel with disk identifier 0x99a32e79.

Command (m for help): I

Enter script file name: os-disk-pt

Created a new GPT disklabel (GUID: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX).
Created a new partition 1 of type 'Linux filesystem' and of size 3.6 GiB.
Created a new partition 14 of type 'BIOS boot' and of size 3 MiB.
Created a new partition 15 of type 'EFI System' and of size 124 MiB.
Script successfully applied.

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

完成後分別對所有分割槽使用 dd 命令複製即可,如下

root@xxx-vm:/tmp# dd if=/dev/sdd1 of=/dev/sdc1 bs=1M
3686+1 records in
3686+1 records out
3865782784 bytes (3.9 GB, 3.6 GiB) copied, 179.995 s, 21.5 MB/s
root@xxx-vm:/tmp# dd if=/dev/sdd14 of=/dev/sdc14 bs=1M
3+0 records in
3+0 records out
3145728 bytes (3.1 MB, 3.0 MiB) copied, 0.147453 s, 21.3 MB/s
root@xxx-vm:/tmp# dd if=/dev/sdd15 of=/dev/sdc15 bs=1M
124+0 records in
124+0 records out
130023424 bytes (130 MB, 124 MiB) copied, 5.775 s, 22.5 MB/s

完成後也可以用 mount 掛載一下新的分割槽進行驗證,沒問題後即可關閉該虛擬機器。

 

【三、修改小容量磁碟配置】

通過介面建立的磁碟是不帶有作業系統型別的,也沒法讓虛擬機器將該磁碟作為系統盤進行啟動,這裡需要使用 Azure 的命令列,例如使用 Azure Powershell,可以參考相關連結3進行安裝。

然後開啟 Powershell,輸入 “Connect-AzAccount”,即可彈出登入 Azure 的對話方塊,並進行確認,完成後會顯示賬戶的所有訂閱,如下圖

然後輸入下列命令設定以下幾個環境變數

$DiskID = "磁碟資源ID"
$VMName = "虛擬機器名稱"
$AzSubscription = "訂閱名"

其中“磁碟資源ID”需要進入磁碟頁面,並在“屬性”頁面中找到“資源ID”即為該內容,類似 “/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/xxxxxxxx/providers/Microsoft.Compute/disks/xxxxxxxx”,如下圖

然後再執行下列命令即可

# 指定訂閱
Select-AzSubscription -Subscription $AzSubscription

# 獲取虛擬機器資訊
$VM = Get-AzVm | ? Name -eq $VMName

# 獲取磁碟資訊
$Disk = Get-AzDisk | ? Id -eq $DiskID

# 修改磁碟作業系統型別
$Disk.OsType = "Linux"

# 修改磁碟 Hyper-V 代數(宿主機為V2時需要手動設定)
$Disk.HyperVGeneration = "V2"

# 更新磁碟設定
Update-AzDisk -ResourceGroupName $VM.ResourceGroupName -DiskName $Disk.Name -Disk $Disk

完成後即可在虛擬機器頁面中,選擇“磁碟” -> “交換 OS 磁碟”,剛剛建立的小容量磁碟即會出現在這個頁面中,確定後啟動虛擬機器即可。

 

【四、相關連結】

  1. How to shrink a managed disk:https://devblogs.microsoft.com/premier-developer/how-to-shrink-a-managed-disk/
  2. Shrink an Azure VMs OS Managed Disk using PowerShell:https://jrudlin.github.io/2019-08-27-shrink-azure-vm-osdisk/
  3. Install the Azure Az PowerShell module:https://docs.microsoft.com/en-us/powershell/azure/install-az-ps

相關文章