Vagrant Tutorial(3)細說虛擬機生滅狀態 by William Yeh | CodeData
top

Vagrant Tutorial(3)細說虛擬機生滅狀態

分享:

Vagrant Tutorial(2)跟著流浪漢把玩虛擬機 << 前情

上回我們示範,只用兩行 Vagrant 指令,就能生出一個 Ubuntu 虛擬機。這一回,讓我們分解動作,慢慢分析這背後到底發生了什麼事。你將會瞭解 Vagrant 管理虛擬機(Vagrant 術語為 box)的邏輯,以及從 VirtualBox 角度來看,虛擬機實際上的生滅狀態。畢竟,最初 Vagrant 是站在 VirtualBox 的基礎,加工出一套可程式化介面。多瞭解「上層 Vagrant」是怎麼與「底層 VirtualBox」互動,會讓你更好駕馭 Vagrant 的威力。

行前準備:回復成乾淨狀態

如果你上回有乖乖地照著「生出一個虛擬機,只要兩道指令」來做,那麼這一回,我們要先將你的 host OS 恢復到尚未下載啟動 guest OS 虛擬機的乾淨狀態(簡單的說,就是 undo 那兩道指令啦)。且讓我們先進入同樣的工作目錄,大掃除一番。

如果你的 host OS 是 Linux 或 Mac,請輸入以下指令:

$ cd demo-1

$ vagrant halt ; vagrant destroy --force
$ rm -rf .vagrant Vagrantfile

$ vagrant box remove ubuntu/trusty64
$ rm -rf $HOME/.vagrant.d/boxes/ubuntu-VAGRANTSLASH-trusty64

如果你的 host OS 是 Windows,請改成:

$ cd demo-1

$ vagrant halt
$ vagrant destroy --force
$ del /F /Q  Vagrantfile
$ rmdir /S /Q  .vagrant

$ vagrant box remove ubuntu/trusty64
$ rmdir /S /Q %USERPROFILE%\.vagrant.d\boxes\ubuntu-VAGRANTSLASH-trusty64

看到這些 undo 手續,加上一點點倒推的想像力,不難一瞥之前 Vagrant 做了哪些事。

行前準備:雙視窗觀察畫面

接下來,建議你開兩個視窗,一邊是終端機命令列,讓你輸入 Vagrant 指令;一邊是 VirtualBox 視窗,讓你即時觀察輸入的上層 Vagrant 指令會對底層的 VirtualBox 產生什麼樣的變化,有助於領會進階操作的原理。

譬如說,做完前面的大掃除步驟後,我的雙視窗觀察畫面會變成這樣:

vagrant-3-desktop-layout

看著這畫面,由左至右,可依序觀察到幾件事:

  • 從【VirtualBox 視窗】可看到,VirtualBox 虛擬機清單已經完全清空。
  • 從【終端機視窗】的 ls -al 指令查知,工作目錄已經完全清空。
  • 從【終端機視窗】的 vagrant box list 指令查知,目前沒有任何 Vagrant box 存在。

嗯,的確已經回到乾淨的狀態。

我也故意將這兩個視窗的 z-order 安排成:Vagrant 所在的【終端機視窗】,疊在 VirtualBox 所在的視窗上面,以凸顯「上層 Vagrant」與「底層 VirtualBox」之間的上位、下位階層關係。

行前準備一切就緒,且讓我們放慢動作,一步一步來⋯⋯

定義你要用的虛擬機

照 Vagrant 的遊戲規則,在啟動任何一個 Vagrant box 之前,必須先定義好,在這個工作目錄中,我們要啟動的是哪一種 box,以及這個 box 該有哪些相關屬性。最常見的定義內容計有:

  • 虛擬機的名字,可能是 global 的(像上回示範過的 ubuntu/trusty64 名字)或 local 的(像自己取的 precise64my-ubuntu1404 名字)。
  • 如果該虛擬機檔案母體,並未登記在官方的 Vagrant Cloud repository 裡,而是另外散置在像 Vagrantbox.es 所列的這些網路硬碟中,那麼,我們也必須明指該母體的 URL 為何。
  • 要分配給虛擬機的主記憶體大小。
  • Host 與 guest OS 之間的 port 與目錄對應關係。

因此,我們必需先在選定的工作目錄裡(或是上層目錄,或是上上層目錄⋯⋯),把這些屬性寫進一個名叫 Vagrantfile 的「Vagrant 定義檔」裡面。

Vagrant 是用 Ruby 寫的,而 Ruby 陣營又對於直接以 Ruby 語言當成 DSL (domain-specific language) 覺得天經地義理所當然,更無比自豪(請見本文附錄),因此,Vagrantfile 本身也就是一份遵循 Ruby DSL 規則的 Ruby 源碼文件,可以擺放常數、變數、迴圈等程式語句。

每次都要先寫一份 Vagrant 定義檔,才能開始玩 Vagrant,也挺麻煩的(而且,我又不懂 Ruby 火星語⋯⋯)。你可以文抄公複製既有的定義檔過來用,或者,更簡單的方法,只要下一道 vagrant init 指令,Vagrant 就會自動幫你生出一份預設的版本。現在,請輸入:

$ vagrant init ubuntu/trusty64
A `Vagrantfile` has been placed in this directory. You are now
ready to `vagrant up` your first virtual environment! Please read
the comments in the Vagrantfile as well as documentation on
`vagrantup.com` for more information on using Vagrant.
$

畫面上告訴我們 “A `Vagrantfile` has been placed in this directory.”。沒錯吧!

畫面上也叫我們 “Please read the comments in the Vagrantfile”。好吧,乖乖的照著提示,看一看 Vagrant 自動幫我們生出的 Vagrantfile 長什麼樣子:

# -*- mode: ruby -*-
# vi: set ft=ruby :

# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  # All Vagrant configuration is done here. The most common configuration
  # options are documented and commented below. For a complete reference,
  # please see the online documentation at vagrantup.com.

  # Every Vagrant virtual environment requires a box to build off of.
  config.vm.box = "ubuntu/trusty64"

[略]

註解很多,即使不懂 Ruby,也不難做些初步的修改。有了這份 Vagrantfile 當出發點,就能再修改成各專案自己想要的設定。

Vagrantfile 是控制 Vagrant 的重要手段,也決定了 Vagrant 能做什麼、不能做什麼。完整的 Vagrantfile 設定內容,請見官方文件。我們以後會擇要介紹。

下載虛擬機檔案本體

Vagrantfile 定義好了,一切就緒,可以將這台虛擬機 box 開機啟動了吧?

且慢!把手移開鍵盤,先不要急著輸入上回示範過的 vagrant up 指令。先來分解動作。

還記得嗎?上回文章提過:

如果你是第一次在這個 host OS 上嘗試建立 ubuntu/trusty64 這個 box,那麼,在 vagrant up 這個步驟執行時,Vagrant 會先向 Vagrant Cloud 查詢並下載這個 box 檔案。檔案小則 100 MB,大則數百 MB,請稍待片刻。

且讓我們拿著放大鏡,分析這所謂的「查詢下載 box 檔案」動作。

請先用瀏覽器打開上回的 https://asciinema.org/a/11428 錄影,重看第 0 分 28 秒~4 分 25 秒。你會看到這樣的畫面:

vagrant-3-lookup

其中:

  • 「Loading metadata for box ‘ubuntu/trusty64′」這一行,就是所謂的「向 Vagrant Cloud 查詢 box 檔案」動作。
  • 「Downloading: https… 」這一行,就是所謂的「向 Vagrant Cloud 下載 box 檔案」動作。

那麼,下載回來的 box 檔案本體,會存在哪裡呢?我們稍後會再回頭探討這件事。

啟動(開機)你定義好的虛擬機

好,現在你可以輸入 vagrant up 指令了:

$ vagrant up

緊接著前述的「向 Vagrant Cloud 查詢並下載這個 box 檔案」中間過程之後,你會先看到如下的畫面:

vagrant-3-import

這表示,上層的 Vagrant 正在把 ubuntu/trusty64 這個 box 的檔案本體匯入 (import) 至底層的 VirtualBox。因此,在 VirtualBox 虛擬機清單中,可看到新增了一台虛擬機,而且一開始是處於「電源關閉」狀態。

緊接著,你會看到 Vagrant 旋即把這台虛擬機切換至「已開機,執行中」狀態:

vagrant-3-poweron

此時,也可以在終端機視窗用 vagrant status 指令來查看,在此工作目錄下,Vagrant 目前處於什麼狀態:

$ vagrant status
Current machine states:

default                   running (virtualbox)

The VM is running. To stop this VM, you can run `vagrant halt` to
shut it down forcefully, or you can run `vagrant suspend` to simply
suspend the virtual machine. In either case, to restart it again,
simply run `vagrant up`.
$

順便也看看,Vagrant 在我們的工作目錄做了什麼事?

$ # 看看現在工作目錄有什麼變化...
$ ls -al
total 16
drwxr-xr-x   4 william  wheel   136  8 31 21:45 .
drwxrwxrwt  13 root     wheel   442  8 31 20:55 ..
drwxr-xr-x   3 william  wheel   102  8 31 21:45 .vagrant
-rw-r--r--   1 william  wheel  4822  8 30 21:43 Vagrantfile
$

可以看到,工作目錄除了原本就有的定義檔 Vagrantfile 之外,還多了一個 .vagrant 目錄,Vagrant 會用它存放這個 box 執行個體的狀態及資料。

Vagrant box 檔案本體

剛剛是針對工作目錄看的 local 資訊,現在也讓我們看看 global 資訊。

先來回顧一下,系統裡面已經下載過哪些 Vagrant box 了:

$ vagrant box list
ubuntu/trusty64 (virtualbox, 14.04)
$

順便找找 box 檔案本體被 Vagrant 藏在哪裡吧。如果你沒有改變 VAGRANT_HOME 環境變數的話,預設目錄會是:

  • 若 host OS 是 Linux & Mac,會擺在 $HOME/.vagrant.d 目錄。
  • 若 host OS 是 Windows,會擺在 %USERPROFILE%\.vagrant.d 目錄。

且讓我們從這裡出發,一層一層鑽進去探險:

$ ls -al $HOME/.vagrant.d
total 16
drwxr-xr-x   9 william  staff   306  8 31 21:55 .
drwxr-xr-x+ 70 william  staff  2380  8 31 21:57 ..
drwx------   3 william  staff   102  8 31 21:56 boxes
drwxr-xr-x  13 william  staff   442  8 31 21:51 data
drwxr-xr-x   3 william  staff   102  3 31 14:56 gems
-rw-------   1 william  staff  1675  3  5 17:00 insecure_private_key
drwxr-xr-x   3 william  staff   102  3  5 17:00 rgloader
-rw-r--r--   1 william  staff     3  3 31 14:56 setup_version
drwxr-xr-x   4 william  staff   136  8 31 21:50 tmp
$
$ # 嗯,其中 'boxes' 這個目錄很可疑,進去看看...
$ ls -al $HOME/.vagrant.d/boxes
total 0
drwx------  3 william  staff  102  8 31 21:56 .
drwxr-xr-x  9 william  staff  306  8 31 21:55 ..
drwxr-xr-x  4 william  staff  136  7  3 22:47 ubuntu-VAGRANTSLASH-trusty64
$
$ # 嗯,出現了 'ubuntu' 及 'trusty64' 關鍵字,進去看看...
$ ls -al $HOME/.vagrant.d/boxes/ubuntu-VAGRANTSLASH-trusty64
total 8
drwxr-xr-x  4 william  staff  136  7  3 22:47 .
drwx------  3 william  staff  102  8 31 21:56 ..
drwxr-xr-x  3 william  staff  102  8 31 21:50 14.04
-rw-r--r--  1 william  staff   40  8 31 21:50 metadata_url
$
$ # 嗯,有一個疑似版本號的目錄 '14.04',進去看看...
$ ls -al $HOME/.vagrant.d/boxes/ubuntu-VAGRANTSLASH-trusty64/14.04
total 0
drwxr-xr-x  3 william  staff  102  8 31 21:50 .
drwxr-xr-x  4 william  staff  136  7  3 22:47 ..
drwxr-xr-x  6 william  staff  204  8 31 21:50 virtualbox
$
$ # 嗯,二話不說,鑽進去 'virtualbox' 目錄看看...
$ ls -al $HOME/.vagrant.d/boxes/ubuntu-VAGRANTSLASH-trusty64/14.04/virtualbox
total 737512
drwxr-xr-x  6 william  staff        204  8 31 21:50 .
drwxr-xr-x  3 william  staff        102  8 31 21:50 ..
-rw-r--r--  1 william  staff        505  8 31 21:50 Vagrantfile
-rw-------  1 william  staff  377585664  8 31 21:50 box-disk1.vmdk
-rw-------  1 william  staff      10506  8 31 21:50 box.ovf
-rw-r--r--  1 william  staff         25  8 31 21:50 metadata.json
$
$ # 就是這個!!! 'box-disk1.vmdk'

從最後所到目錄可看出,Vagrant 將下載回來的 box 檔案本體,儲存成互通性較高的 VMDK 格式,而不是 VirtualBox 原生的 VDI 格式

有興趣的,可以再打開這目錄裡面的其他檔案瀏覽一番。

關機、移除

現在,試著將這台虛擬機關機:

$ vagrant halt
==> default: Attempting graceful shutdown of VM...
$

的確,從 VirtualBox 角度來看,這台虛擬機狀態,從「執行中」變成「電源關閉」:

vagrant-3-poweroff

注意喔,這台虛擬機只是「關機」而已,並沒有被「移除」。因此,不管是從底層的 VirtualBox 還是上層的 Vagrant 兩種角度來看,這個 Ubuntu 虛擬機執行個體都還存在(只不過是暫時關機):

$ # 先看一看在此工作目錄下,Vagrant 目前的狀態...
$ vagrant status
Current machine states:

default                   poweroff (virtualbox)

The VM is powered off. To restart the VM, simply run `vagrant up`
$
$ # 很明顯地告訴我們,這台 VM 還可以再被 restart...
$ # 那麼,這個 Vagrant box 檔案本體還存在嗎?
$ vagrant box list
ubuntu/trusty64 (virtualbox, 14.04)
$
$ # 還在!

如果想進一步把它移除呢?可以用 vagrant destroy 指令:

$ vagrant destroy
    default: Are you sure you want to destroy the 'default' VM? [y/N] Y
==> default: Destroying VM and associated drives...
$

從畫面上可看到,這台虛擬機,徹底從 VirtualBox 的虛擬機清單上除名:

vagrant-3-destroy

不過,有趣的地方在於,這只是從「VirtualBox 虛擬機清單」上除名,但並沒有從「Vagrant 所管理維護的『已下載 box 清單』」上除名:

$ # 照例,先看一看在此工作目錄下,Vagrant 目前的狀態...
$ vagrant status
Current machine states:

default                   not created (virtualbox)

The environment has not yet been created. Run `vagrant up` to
create the environment. If a machine is not created, only the
default provider will be shown. So if a provider is not listed,
then the machine is not created for that environment.
$
$ # 現在的「Vagrant 所管理維護的『已下載 box 清單』」呢?
$ vagrant box list
ubuntu/trusty64 (virtualbox, 14.04)
$
$ # 還在!
$ # 那麼,box 檔案本體呢?
$ ls -al $HOME/.vagrant.d/boxes/ubuntu-VAGRANTSLASH-trusty64/14.04/virtualbox
total 737512
drwxr-xr-x  6 william  staff        204  8 31 21:50 .
drwxr-xr-x  3 william  staff        102  8 31 21:50 ..
-rw-r--r--  1 william  staff        505  8 31 21:50 Vagrantfile
-rw-------  1 william  staff  377585664  8 31 21:50 box-disk1.vmdk
-rw-------  1 william  staff      10506  8 31 21:50 box.ovf
-rw-r--r--  1 william  staff         25  8 31 21:50 metadata.json
$
$ # 也還在!

所以,Vagrant 不會輕易把下載回來的「Vagrant box 檔案本體」(即畫面中的 vmdk 檔)清除掉,只是把藉著它而增生出來的「VirtualBox 虛擬機執行個體 (instance)」清除掉而已。也因此,你反覆執行 up、halt、destroy 指令不管多少次,系統不會每次都跑去 Vagrant Cloud 下載那動輒數百 MB 的 box 檔案本體;除非你像本文一開始的大掃除動作那樣,強制驅離 $HOME/.vagrant.d 裡面的庫存資料。

小結

這一回,我們學會利用 vagrant init 指令,叫 Vagrant 幫我們生出一個 Vagrantfile 定義檔,定義想要的 Vagrant box 種類及屬性。之後,藉由 VirtualBox + 終端機雙視窗配置,逐一檢視 vagrant upvagrant haltvagrant destroy 等 Vagrant 指令,是如何同時作用在上層的 Vagrant 及底層的 VirtualBox 身上。過程中也穿插介紹實用的 vagrant box listvagrant status 查詢指令。

以上都是很基本的觀念,必須非常熟練。

我把最核心的操作動線錄影起來: http://www.screencast.com/t/U0iOeaDjJXMb ,建議你,不妨照著影片多試幾次,並留意影片中提醒的觀察重點。等到熟練了,再回到文章,將文章提到的所有細節都親自檢驗過一遍,才能擁有足夠的問題排除能力。

下一回,來碰碰大家愛用的 Redis,以及最近很夯的 Docker 吧。我會以「在 Ubuntu 中安裝 Docker engine」為例,示範如何設定虛擬機組態。

附錄

Ruby 達人 ihower 在他的《Ruby on Rails 實戰聖經FAQ 中如是說:

Ruby 是一套非常重視 usability 的物件導向程式語言,非常看重程式碼的可讀性及維護性。…Ruby 也是目前做 domain-specific language (DSL),特別是 internal DSL 最為成功的程式語言。透過 DSL,程式不但可以擁有非常好的可讀性,也可以大幅增加生產力。

後續 >> Vagrant Tutorial(4)虛擬機,若即若離的國中之國

分享:
按讚!加入 CodeData Facebook 粉絲群

相關文章

留言

留言請先。還沒帳號註冊也可以使用FacebookGoogle+登錄留言

關於作者

擔任過許多職場角色:程式設計師、技術團隊領班、技術作家及譯者、教授、顧問、技術佈道者,但目前最喜歡的身份,還是「軟體架構師」。

熱門論壇文章

熱門技術文章