対象
- Windows上でVagrant + VirtualBoxを使用して、Linuxを稼働させている。
- 容量を使用していないのに、なぜかvmdkのファイル容量が大きい。
- 既存のデータやソフトウェアを削除せずに容量を軽くしたい。
原因
VirtualBoxで仮想ディスク(vmdkファイル)を「可変サイズのストレージ」に設定している場合、一度増えた容量は使っていなくても増えたままになってしまう。
そのため、本来のサイズよりもvmdkファイルで確保している領域が大きくなってしまい、ディスクをひっ迫する原因となる。
対処
仮想ディスクで使用されていないリソースを解放してあげればよい。
ただし、vmdk形式のままでは圧縮できないので、複製したvmdkをvdiに変換してから圧縮する。
最後に、vdiをvmdkに変換しなおして、VirtualBox上の仮想マシンにvmdkファイルを割り当てれば設定完了。
※ 2回ほど仮想ディスクを複製するため、仮に10GBの仮想ディスクであれば20GB程度の空き容量が必要になります。場合によっては外付けハードディスクなどの利用をおススメします。
手順
- VirtualBoxのインストールフォルダにPathを通す
- Linux(ゲストOS)で使用していない領域をクリア
- Windows(ホストOS)で仮想ディスクを変換・圧縮
- VirtualBox上の仮想マシンにvmdkファイルを割り当て
- 変換元になった仮想ディスクとそれに紐づいた仮想マシンを解放
1. VirtualBoxのインストールフォルダにPathを通す
VirtualBox.exeがあるインストールフォルダ(
初期設定であれば、C:\Program Files\Oracle\VirtualBox
)を環境変数に登録します。
以下のコマンドをPowershellで実行すれば、環境変数 Path
の末尾に、VirtualBoxのインストールディレクトリが追加されます。
※ インストールディレクトリが異なる場合は、addPath
を適宜変更してください。
function checkPath{
param($addPath, $systemPath)
if(!(Test-Path $addPath)){
Write-Host "Path does not exist."
return $false
}
if($systemPath.IndexOf($addPath) -ne -1){
Write-Host "Path already exists."
return $false
}
return $true
}
$oldSystemPath = [System.Environment]::GetEnvironmentVariable("Path", "Machine")
$addPath = 'C:\Program Files\Oracle\VirtualBox\'
if(checkPath $addPath $oldSystemPath){
$oldSystemPath += ";$addPath"
[System.Environment]::SetEnvironmentVariable("Path", $oldSystemPath, "Machine")
Write-Host $oldSystemPath
Write-Host "Adding Path is completed!"
}
2. Linux(ゲストOS)で使用していない領域をクリア
vagrant up
でインスタンスを起動してSSH接続後、以下のコマンドを入力実行。
(dd
コマンドは一歩間違えると、データが上書きされてしまう危険性があるので要注意)
sudo dd if=/dev/zero of=zero bs=4k; \rm zero
上記コマンドで、未使用の領域をゼロで上書きできる。
「/dev/zero」は常にNULL文字(0x00)を出力し続けるという特殊なデバイスで、今回はcountを指定していないため、空き容量すべて使用してNULL文字のファイルを作成している。 of
オプションには出力先を指定するが、今回の処理ではrm
で削除することで未使用の領域を解放している。
3. Windows(ホストOS)でVirtualBoxの仮想ディスクを変換・圧縮
仮想ディスク(vmdkファイル)の場所を探す
Powershellを開いて、以下のコマンド( VBoxManage.exe list hdds
)を実行してください。
>> VBoxManage.exe list hdds
UUID: 913bedef-edb0-420c-a364-35e900ac7110
Parent UUID: base
State: created
Type: normal (base)
Location: C:\Users\[userName]\VirtualBox VMs\instance1_default_1565318560385_64490\ubuntu-18.04-amd64-disk001.vmdk
Storage format: VMDK
Capacity: 65536 MBytes
Encryption: disabled
Locationに記載されたパスが、今回圧縮する予定のvmdkファイルの場所になります。
vmdkファイルを複製して、vdi形式に変換する
VBoxManage.exe clonehd [inputFile] [outputFile]
で、ファイルを複製することができます。[inputFile]
に先ほど見つけたlocationのパスを設定し、[outputFile]
には出力先およびファイル名を設定します。
今回はファイルを変換するので --format vdi
をオプションとして設定します。
VBoxManage.exe clonehd "C:\Users\[userName]\VirtualBox VMs\instance1_default_1565318560385_64490\ubuntu-18.04-amd64-disk001.vmdk" "C:\Users\[userName]\VirtualBox VMs\instance1_default_1565318560385_64490\clone.vdi" --format vdi
vdiファイルを圧縮する
先ほど作成したvdiファイルを、VBoxManage.exe modifyhd [inputFile] --compact
で圧縮する。
VBoxManage.exe modifyhd "C:\Users\[userName]\VirtualBox VMs\instance1_default_1565318560385_64490\clone.vdi" --compact
vdiファイルをvmdk形式に変換
先ほどとは逆に .\VBoxManage.exe clonehd [inputFile] [outputFile]
VDI形式からVMDK形式のクローンを作成します。
今度は --format vmdk
をオプションとして設定します。
※参照した記事にならって、2GB単位でファイルを分割して管理するオプションを指定しています。
VBoxManage.exe clonehd "C:\Users\[userName]\VirtualBox VMs\instance1_default_1565318560385_64490\clone.vdi" "C:\Users\[userName]\VirtualBox VMs\instance1_default_1565318560385_64490\box_disk.vmdk" --format vmdk --variant Split2G
4. VirtualBox上の仮想マシンにvmdkファイルを割り当て
仮想マシンの操作を行うため、 VBoxManage.exe list vms
でUUIDを取得します。
{}
内の16進数標記の文字列がUUIDです。
>> VBoxManage.exe list vms
"ubuntu_tensor_default_1570674600311_51555" {c3e4ce85-1a1f-4569-9cc8-13ef3da1b3eb}
仮想ディスクのアタッチとデタッチには storageattach
を使います。
(GUIをつかってもいいですが、あとでバッチ処理での実行を想定して、今回はCLIのみで操作します。)
既存の仮想ディスクをデタッチ
VBoxManage.exe storageattach [ VMs_UUID ] `
--storagectl "SATA Controller" `
--port 0 `
--type hdd `
--medium emptydrive
複製して圧縮した仮想ディスクをアタッチ
VBoxManage.exe storageattach [ VMs_UUID ] `
--storagectl "SATA Controller" `
--port 0 `
--device 0 `
--type hdd `
--medium "C:\Users\[userName]\VirtualBox VMs\instance1_default_1565318560385_64490\box_disk.vmdk"
5. 変換元になった仮想ディスクを解放
list hdds
で仮想ディスクの状態を確認します。
>> VBoxManage.exe list hdds
UUID: 913bedef-edb0-420c-a364-35e900ac7110
Parent UUID: base
State: created
Type: normal (base)
Location: C:\Users\[userName]\VirtualBox VMs\instance1_default_1570674600311_51555\ubuntu-18.04-amd64-disk001.vmdk
Storage format: VMDK
Capacity: 65536 MBytes
Encryption: disabled
UUID: fe9ab526-7500-46d7-aad8-a8f6ad394f98
Parent UUID: base
State: created
Type: normal (base)
Location: C:\Users\[userName]\VirtualBox VMs\instance1_default_1570674600311_51555\box_disk.vmdk
Storage format: VMDK
Capacity: 65536 MBytes
Encryption: disabled
不要になったhddsは、以下のコマンドで解放しておきます。
(解放する前に、locationのPathはメモしておく)
VBoxManage.exe closemedium disk [ DISKs_UUID ]
また、解放したhddsの元ファイルも削除します。
rm 'C:\Users\[userName]\VirtualBox VMs\instance1_default_1570674600311_51555\ubuntu-18.04-amd64-disk001.vmdk'
これで仮想マシンの圧縮は完了です。
(※これをバッチ処理で実行できるようにしたい…。)
参考
VirtualBoxの仮想ディスク容量を圧縮する方法
VirtualBox の仮想ディスクのサイズを変更する
【 dd 】コマンド――ブロック単位でファイルをコピー、変換する
Vagrantの仮想マシンとの紐付けの直し方
以上