LoginSignup
10
10

More than 3 years have passed since last update.

Vagrantで容量が膨れ上がったvmdkを圧縮する方法(Vagrant + VirtualBox)

Last updated at Posted at 2019-11-06

対象

  • Windows上でVagrant + VirtualBoxを使用して、Linuxを稼働させている。
  • 容量を使用していないのに、なぜかvmdkのファイル容量が大きい。
  • 既存のデータやソフトウェアを削除せずに容量を軽くしたい。

原因

VirtualBoxで仮想ディスク(vmdkファイル)を「可変サイズのストレージ」に設定している場合、一度増えた容量は使っていなくても増えたままになってしまう。
そのため、本来のサイズよりもvmdkファイルで確保している領域が大きくなってしまい、ディスクをひっ迫する原因となる。

対処

仮想ディスクで使用されていないリソースを解放してあげればよい。
ただし、vmdk形式のままでは圧縮できないので、複製したvmdkをvdiに変換してから圧縮する。
最後に、vdiをvmdkに変換しなおして、VirtualBox上の仮想マシンにvmdkファイルを割り当てれば設定完了。

※ 2回ほど仮想ディスクを複製するため、仮に10GBの仮想ディスクであれば20GB程度の空き容量が必要になります。場合によっては外付けハードディスクなどの利用をおススメします。

手順

  1. VirtualBoxのインストールフォルダにPathを通す
  2. Linux(ゲストOS)で使用していない領域をクリア
  3. Windows(ホストOS)で仮想ディスクを変換・圧縮
  4. VirtualBox上の仮想マシンにvmdkファイルを割り当て
  5. 変換元になった仮想ディスクとそれに紐づいた仮想マシンを解放

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の仮想マシンとの紐付けの直し方

以上

10
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
10