Vagrantのスナップショット機能とVirtualBox

本記事では、Vagrantのスナップショット機能とその利用についてVirtualBoxとあわせて見ていきます。

【目次】

[1]はじめに

VirtualBoxのスナップショット機能は、仮想マシンの特定の時点の状態(構成、ディスク、メモリなど)を記録します。 これにより、仮想マシンをスナップショットをとった時の状態に戻す(復元)することができます。

Vagrantには、Vagrantらしいシンプルで使いやすいコマンドからVirtualBoxのスナップショットを制御する機能があります。

一方で、製品コンセプトの違いからか、動作が微妙に異なるところや制限事項もあり、注意が必要なところもあります。

個人的には、Vagrantのスナップショット機能を利用する場合、必要に応じてVirtualBoxと併用するのがよいと思っています。

そこで本記事では、VirtualBoxの機能とあわせて、Vagrantのスナップショット機能を見ていきます。
なお、以下に記載しているVagrantのスナップショットに関するコマンドは、カレントディレクトリをVagrantのプロジェクトディレクトリにして実行する必要があります。

(参考)
VirtualBoxのスナップショット機能については、記事『VirtualBoxのスナップショット機能』を参照してください。

[2]スナップショットの一覧(list)

まずは、Vagrantからスナップショットの一覧を表示するコマンドから見ていきます。

vagrant snapshot list


作成済みのスナップショット名のリストを表示します。
  • 表示されるスナップショット名は、VirtualBoxのスナップショット画面と同じです。
    • Vagrantから作成したスナップショットだけでなく、VirtualBoxから作成したスナップショットも表示されます。
    • 同様にVagrantから作成したスナップショットもVirtualBoxのスナップショット画面に表示されます。
  • スナップショットは名前でソートされて表示されます。
    • VirtualBoxのスナップショット画面では、作成したスナップショットの分岐が木構造のように表示されますが、Vagrantでは、スナップショット名がソートされてフラットにリストされます。(コマンド名が list になっている通りです。)
    • スナップショット間の依存関係は表示されません。
  • スナップショットの「説明」を見ることはできません。
    • VirtualBoxのスナップショットには「説明」を記載でき、これをスナップショット画面から参照できますが、Vagrantのコマンドから「説明」を表示する機能は無いようです。
    • もっとも、Vagrantからスナップショットを作成する際に「説明」を設定することはできないため、表示も不要、ということだと思います。

以下で、Vagrantのコマンドの結果表示とVirtualBoxの画面を具体的に対比してみます。

例として、スナップショットの作成と復元を以下のように行ったとします。
  1. スナップショット「snap_1」を作成(save)
  2. スナップショット「snap_2」を作成(save)
  3. スナップショット「snap_1」を復元(restore)
  4. スナップショット「snap_3」を作成(save)
  5. スナップショット「snap_2」を復元(restore)
  6. スナップショット「snap_4」を作成(save)
この状態でvagrant snapshot list を実行すると、以下のように表示されます。
>vagrant snapshot list
==> default:
snap_1
snap_2
snap_3
snap_4

作成(save)した4つのスナップショットが名前でソートされて表示されています。但し、それぞれのスナップショットの依存関係はわかりません。

一方、VirtualBoxのスナップショット画面では以下のように表示されます。


こちらはスナップショットが木構造のように表示されて分岐関係を把握することができます。(但し、全ての作成順序までは把握できませんので、スナップショット名に日付や連番を付けるなどの規則を決めておくとよいかもしれません。)

ところで、Vagrantを利用している場合、VirtualBox側でスナップショットを作成することは殆どないと思いますが、例えば、以下のようにVirtualBox側でスナップショットを作成しているとします。(「スナップショット 1」に説明を追加しています。)


これは以下のようにvagrant snapshot list からも確認することができますが、説明内容を見ることはできません。
>vagrant snapshot list
==> default:
スナップショット 1
スナップショット 2

Vagrantのスナップショットのリスト表示は、名前でソートされて表示されるので分かりやすい点やコマンドラインから利用できることなど良い点もありますが、スナップショットの依存関係などを確認できない問題もあります。

これらを考えると、必要に応じてVirtualBoxのスナップショット画面とあわせて確認するのがよいと思います。

[3]スナップショットの作成/復元/削除方法(save/restore/delete)

Vagrantでスナップショットを管理(作成/復元/削除)する方法として、
  • save/restore/deleteコマンドを利用する方法(VirtualBoxの管理方法と類似)
  • push/popコマンドを利用する方法(Vagrant固有の方法)
が用意されています。
ここでは、save/restore/deleteを利用してスナップショットを作成、復元、削除する方法を見ていきます。

(1)作成(保存):save

VirtualBoxスナップショット画面の「作成」にあたるコマンドです。
vagrant snapshot save NAME

ここで、NAMEにはスナップショットの名前を指定します。シングルクォート(’)で囲むと、空白が入った名前を指定することができます。「(4)スナップショット名に日本語を含む場合の注意」も参照して下さい。

(補足)
VirtualBoxのスナップショットの作成機能は、スナップショットの名前とともに「説明」を設定することができますが、Vagrantからスナップショットの「説明」を設定することはできません。
もし、Vagrantから作成したスナップショットに「説明」を設定しておきたい場合は、Vagrantからスナップショットを作成後にVirtualBoxのスナップショット画面から「説明」を設定します。ただし、Vagrantからは「説明」の内容を表示できませんので、VirtualBoxのスナップショット画面で行う必要があります。

(2)復元:restore

VirtualBoxスナップショット画面の「復元」にあたるコマンドです。
vagrant snapshot restore NAME

ここで、NAMEにはスナップショットの名前を指定します。シングルクォート(’)で囲むと、空白が入った名前を指定することができます。「(4)スナップショット名に日本語を含む場合の注意」も参照して下さい。

(補足)
  • 最新の状態の変更(差分)を破棄してスナップショットに記録されている状態を復元します。
    • VirtualBoxでは、もしスナップショットを復元する前に、差分があれば(「最新の状態(変更)」の表示であれば)、現在の状態をスナップショットに保存するかどうかの確認があります。一方、Vagrantは、確認は無く、差分を破棄して復元します(そして仮想マシンを起動します)。このため、変更(差分)を破棄したくない場合は、復元の前にスナップショットを作成しておく必要があります。
    • これは便利である一方で、意図せず差分を破棄してしまう可能性があるため、注意が必要です。
  • VirtualBoxの復元を実行しても仮想マシンを自動的に起動しませんが、vagrant snapshot restoreで復元を実行すると、仮想マシンが自動的に起動します。
    • 仮想マシンを自動起動したくない場合は、--no-start オプションを指定します。(vagrant snapshot restore --no-start NAME)
  • 復元した仮想マシンの状態には現在のVagrantfileの設定内容が反映されます。
    • スナップショットを復元した時点は、元のスナップショットの仮想マシンの構成が復元されます。しかし、次回のvagrant upの際に現在のVagrantfileの設定内容が仮想マシンに反映されますので注意が必要です。
      • 例えば、スナップショットを作成した時点のメモリ設定が1024MBで、現在のVagrantfileのメモリ設定が8192MBだったとします。スナップショットを復元すると、1024MBに戻りますが、その後vagrant upを実行すると、現在のVagrantfileのメモリ設定である8192MBに再設定されます。
    • つまり、スナップショットにVagrantfileは含まれないため、仮想マシンの構成を変更すると、スナップショットと現在のVagrantfileに齟齬が生じる場合があります。
      • 実際にはディスク内容が復元できれば問題ないことが多いとは思いますが、構成が重要な場合は、スナップショットとともにVagrantfileもバックアップして、セットで復元したほうがよいかもしれません。
      • 但し、この場合はスナップショットというよりはバックアップの運用と考えたほうが良い気がします。
  • Vagrantから作成したスナップショットだけでなく、VirtualBoxから作成したスナップショットも復元することができます。
    • 但し、「スナップショット 1」のような日本語を含んでいる場合は、VirtualBox側で名前を変更しておく必要があるかもしれません。「(4)スナップショット名に日本語を含む場合の注意」を参考にしてください。
    • もっとも、Vagrantを利用している場合は、VirutalBox側でスナップショットを作成することは殆ど無いと思います。

(3)削除:delete

VirtualBoxスナップショット画面の「削除」にあたるコマンドです。
vagrant snapshot delete NAME

ここで、NAMEにはスナップショットの名前を指定します。シングルクォート(’)で囲むと、空白が入った名前を指定することができます。「(4)スナップショット名に日本語を含む場合の注意」も参照して下さい。

VirtualBoxから作成したスナップショットも削除することができます。

スナップショットを削除できる条件は、VirtualBoxのスナップショット画面から削除を行う場合と同じです。これについては『VirtualBoxのスナップショット機能/[8]スナップショットの削除』を参照してください。

(4)スナップショット名に日本語を含む場合の注意

Vagrantからスナップショットを作成する場合、スナップショット名には半角英数記号を利用するのが安全だと思います。

以下の例のように、日本語を利用したスナップショットも作成できますが、エラーとなって、復元や削除ができないようです。
①「日本語」という名前でスナップショットを作成する=>成功
>vagrant snapshot save 日本語
==> default: Snapshotting the machine as '日本語'...
==> default: Snapshot saved! You can restore the snapshot at any time by
==> default: using `vagrant snapshot restore`. You can delete it using
==> default: `vagrant snapshot delete`.

②作成したスナップショット「日本語」を復元できない=>失敗
>vagrant snapshot restore 日本語
The snapshot name `日本語` was not found for the
virtual machine `default`.

③作成したスナップショット「日本語」を削除できない=>失敗
>vagrant snapshot delete 日本語
The snapshot name `日本語` was not found for the
virtual machine `default`.

VirtualBoxからスナップショットを作成すると、デフォルトの名前は「スナップショット 1」のような日本語を含んでおり、そのままではVagrantから復元、削除できません。

このように、Vagrantから復元や削除ができないスナップショット名がある場合は、VatualBoxのスナップショット画面から、スナップショット名を半角英数記号の名前に変更すれば、Vagrantのコマンドを利用して制御(restore/delete)することができるようになります。
(削除だけなら、VirutalBoxのスナップショット画面から削除するだけでよいと思います。)


[4]もう一つのスナップショットの作成/復元方法(push/pop)


(1)概要

これまでVirtualBoxのスナップショット操作に対応するsave、restore、deleteコマンドによる管理方法を見てきましたが、Vagrantにはもう一つ、pushとpopコマンドによる管理方法があります。

pushとpopを利用すると、ちょっと変更して直ぐに戻したい、という時にとても便利です。例えば、開発ツールのバージョンアップを行って試してみて、直ぐにバージョンアップ前の状態に戻す、などです。

これはpushとpopというコマンド名からわかる通り、スナップショットの作成と復元をスタックに見立てた管理方法です。

スタックに見立てることで、pushとpopコマンドにはスナップショット名を指定する必要がありません(Vagrantが自動的に名前付けします)。さらに、popはrestoreとdeleteを組み合わせた動作(スナップショットを復元して、復元に利用したスナップショットを削除)になりますので、スナップショットを明示的に削除する操作も不要になります。

但し、pushとpopコマンドは厳密なスタックの実装というわけではありません。また、pushとpopによる管理方法とsave、restoreによる管理方法を併用する場合は注意が必要です。

(2)pushコマンド

vagrant snapshot push

現在の状態のスナップショットを作成します。
saveと違って、スナップショット名を指定する必要はありません。

Vagrantがスナップショット名を自動的に「push_XXXXXXXXXX_XXXX」(Xは半角数字)の形式で作成します。
この名前は、vagrant snapshot listコマンドやVirtualBoxのスナップショット画面から確認することができます。

(3)popコマンド

vagrant snapshot pop

直近のpushで作成したスナップショットを復元して仮想マシンを自動起動すると同時に、直近のスナップショット(復元したスナップショット「push_XXXXXXXXXX_XXXX」)を削除します。

このとき、restoreコマンドと同様に、復元したスナップショット以降の変更は破棄されます。また復元したスナップショットも削除されますので注意してください。
(つまり、pushする直前の状態に巻き戻される感じです。)

なお、pushしたスナップショットがない場合は、「No pushed snapshot found!」というエラーになります。

(4)利用上の注意など

pushとpopコマンドはスタックのえ方が元になっているため、pushとpopはペアで利用することが想定されていると思います。

pushの後にpopすれば元の状態に戻ります。また、push、pushと2回連続して保存し、その後、popを二回連続すれば元の状態に戻ります。pushとpopをペアで実行した後はスナップショットも残りません。

スナップショット「push_XXXXXXXXXX_XXXX」の数が、スタックの要素の数と考えることもできます。

試してみた感じでは、pushとpopの対象となるスタックの要素は、スナップショット名「push_XXXXXXXXXX_XXXX」の形式を元にしているようですので、名前の形式を変えるとスタック管理から外れるようです。(逆に、名前を元の「push_XXXXXXXXXX_XXXX」に戻すとスタックの要素になり、popが動作して「push_XXXXXXXXXX_XXXX」を復元後に削除されます。)

具体的な利用例として、「ちょっと変更して直ぐに元に戻す」という場合を考えてみます。
  1. vagrant snapshot push
    • =>現状が「push_XXX...」として保存される
  2. 変更を行って試してみる
  3. vagrant snapshot pop
    • =>「push_XXX...」を復元して削除される

このような用途には、push/popの組み合わせは、スナップショット名を指定する必要がなく、スナップショットの削除も組み込まれているため便利だと思います。

しかし、上記の例で、変更してみたら結果が良かったので元に戻したくない、(つまり、popしたくない)ということになると、pushとpopの対応関係が崩れます。

このような場合、popはせず、スナップショット「push_XXX...」をそのまま残して運用する考え方もありますが、次のような対応方法もあります。
  • もし、pushしたスナップショット「push_XXX...」が不要な場合
    • スナップショット「push_XXX...」を削除して、スタックの要素を空にします。
    • 「push_XXX...」の削除は、vagrant snapshot delete またはVirtualBoxの画面から行うことができます。
  • もし、pushしたスナップショット「push_XXX...」を残して、後に復元ができるようにしておきたい場合
    • スナップショット名を変更(例えば、「push_XXX...」から「before_change」などに変更)してスタック要素を空にしますが、スナップショットは別名で残るので、save/restore/deleteで管理できます。
    • 残念ながら、スナップショット名を変更するコマンドはVagrantに無いため、VirtualBoxのスナップショット画面からスナップショット名の変更を行う必要があります。

push/popとsave/restore/deleteの管理方法を混在しても、pushによって作成されたスナップショット「push_XXXXXXXXXX_XXXX」の後に「最新の状態(変更)」があれば、popが動作しますので大きな問題は無いと思います。

問題となるのは、例えば、
push_XXXXXXXXXX_XXXX
  snap_x
のように、pushの後でsaveでスナップショットを作ってしまうケースです。

このような状況でpopを実行すると、以下のようなエラーが発生します。
Stderr: VBoxManage.exe: error: Snapshot 'push_XXXXXXXXXX_XXXX' of the machine 'YYYY' cannot be deleted, because it is the current snapshot and has one child snapshot
VBoxManage.exe: error: Details: code VBOX_E_INVALID_OBJECT_STATE (0x80bb0007), component SessionMachine, interface IMachine, callee IUnknown

そして、VirtualBoxのスナップショット画面は以下の状態になります。
push_XXXXXXXXXX_XXXX
  snap_x
  最新の状態

これは、popにより、「push_XXX...」の状態は復元しましたが、「push_XXX...」から派生した「snap_x」があったため、「push_XXX...」の下に分岐が生じて「push_XXX...」を削除できなかったという状態になっています。
つまり、pushした時の状態は復元しましたが、スタックが空でない状態です。

このような状態になっても、上述のように、必要に応じて、「push_XXX...」を放置するか、削除するか、名前を変更することで運用を継続できると思います。

[5]スナップショットとパッケージ(BOX)

記事『VirtualBoxのスナップショット機能/[9]エクスポート/インポートの注意事項』で、VirtualBoxのエクスポートは「最新の状態」(あるいは「最新の状態(変更)」)の内容をエクスポートするので、スナップショットの内容は含まれないことを書きました。

VagrantにはBOXとして利用できるパッケージ作成の機能がありますが、エクスポートと同様に、このパッケージデータにもスナップショットのデータは含まれません。

このため、記事『PC上の自分用Ubuntu日本語デスクトップ開発環境サービスを作る(Vagrant+VirtualBox)』で書いたようなBOXを作成する際に、スナップショットを利用して環境構築の試行錯誤しても、そのBOXを利用した仮想マシンには試行錯誤したスナップショットは含まれませんので、BOX作成時でも積極的にスナップショットを利用できると思います。

[6]私なりの使い方

save/restore/deleteので運用すべきか、push/popを使うべきか、など迷うところはありますが、これらは状況に応じて使い分ければよいと思っています。

基本的には、復元を前提とするスナップショットを作成する場合は、save/restore/deleteを利用して、元に戻すことを前提とする場合はpushとpopを利用することかと思います。

仮に、push/popとsave/restore/deleteを混在して利用して問題が生じたとしても、「(4)利用上の注意など」で書いたように、回避方法もあります。

pushはsaveと違ってスナップショット名を指定しなくても使えるので便利です。
また、pushで作成したスナップショットは、saveで作成したものと同じようにrestore、deleteも機能しますので、後で名前を変更して管理を切り替えることを頭に入れていれば、pushとpopの対応を深く考えなくても、pushを気楽に使えます。

VirtualBoxのスナップショット画面を併用すると、スナップショットの状態を把握しやすく、問題が生じたときの対策も考えやすいです。

何が正しいという使い方はないと思いますが、私の場合は、記事『PC上の自分用Ubuntu日本語デスクトップ開発環境サービスを作る(Vagrant+VirtualBox)』で書いたような使い方を基本としているため、運用環境でスナップショットをいっぱい作る、というよりは、運用環境で変更が必要になった場合は、BOXに反映させることが多いです。このため、運用環境でpush/popで試して元に戻し、試した結果が良ければBOXに反映することが多いので、push/popが中心です。
一方で、プロジェクトとして少し長期に運用する仮想環境では、戻せることが基本になるため、push/popはあまり使わず、save/restore/deleteを中心に使っています。

コメント

このブログの人気の投稿

VirtualBoxのスナップショット機能

Google Document AIで画像から表形式データを抽出する(Vision API OCRとの違い)

Ubuntu/Colab環境でPDFファイルのページを画像化する(pdf2image、pdftoppm、pdftocairo)