Vagrant Tutorial(5)客製化虛擬機內容的幾種方法 by William Yeh | CodeData
top

Vagrant Tutorial(5)客製化虛擬機內容的幾種方法

分享:

Vagrant Tutorial(4)虛擬機,若即若離的國中之國 << 前情

上回我們示範了如何在 guest OS 裡面,手動設定好 Redis server,以及一份「Docker 化 (Dockerized)」的 Redis server。辛辛苦苦把軟體設定好了,下一步,就是研究該如何存檔、散佈、自動化管理,讓這些心血不會因意外就消失不見,還得整個從頭來過。

讓我們先手動將虛擬機組態設定、儲存、複製增生虛擬機等流程完整走過一遍,之後再設法自動化整個流程。

我們會依序演練以下任務:

  1. 手動設定 Guest OS 組態
  2. 打包,存檔
  3. 加進本機端 Vagrant repository
  4. 複製增生虛擬機執行個體
  5. 散佈 box 檔
  6. 加進 Vagrant Cloud repository
  7. 自動設定 Guest OS 組態 (Provisioning)

手動設定 Guest OS 組態

與上一篇文章一樣,我們仍然以「在 guest OS 中安裝 Redis server」當例子。

首先,換一個新的工作目錄 demo-redis-1

$ mkdir demo-redis-1
$ cd demo-redis-1

下一步,要準備一份 Vagrant 定義檔 Vagrantfile

以前我們都是藉由 vagrant init 指令產生一份 Vagrantfile 供我們差遣,不過,本系列文章都已經連載到第五集了,不能再當懶人了。這一回,讓我們當個硬漢吧!自己硬刻,手動將以下內容寫進 Vagrantfile 檔案裡面去:

VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.box = "ubuntu/trusty64"
end

接著,啟動、登入這台 guest OS:

$ vagrant up
$ vagrant ssh
vagrant$

最後,用以下指令安裝 Redis server 進去:

vagrant$  # 安裝 Redis...
vagrant$  sudo apt-get install redis-server -y
[略]
vagrant$
vagrant$  # 允許 Redis bind 至全部 network interface...
vagrant$  sudo sed -i -e 's/^bind/#bind/' /etc/redis/redis.conf
vagrant$  # 重啟 Redis,讓新設定生效。
vagrant$  sudo service redis-server restart

到目前為止,都是上一回我們演練過的步驟。好戲還在後面⋯⋯

打包,存檔

我們可用 vagrant package 指令,叫 Vagrant 將目前這個虛擬機執行個體打包起來,整個儲存到外部檔案。依照 Vagrant 慣例,儲存的檔案,副檔名會是 .box。如果不特別下 --output 參數,預設的輸出檔名會是 package.box

假設我們想存成 redis.box 檔:

vagrant$  # 先登出 guest OS
vagrant$  exit
$
$ # 回到 host OS 了。
$ # 打包,存成 redis.box 檔
$ vagrant package --output redis.box
==> default: Attempting graceful shutdown of VM...
==> default: Clearing any previously set forwarded ports...
==> default: Exporting VM...
==> default: Compressing package to: /private/tmp/demo-redis-1/redis.box
$
$ # 看看存檔的情況
$ ls -al
total 673168
drwxr-xr-x   5 william  wheel        170  9 23 23:00 .
drwxrwxrwt  17 root     wheel        578  9 23 22:47 ..
drwxr-xr-x   3 william  wheel        102  9 23 22:47 .vagrant
-rw-r--r--   1 william  wheel        191  9 23 22:47 Vagrantfile
-rw-r--r--   1 william  wheel  344656169  9 23 23:01 redis.box
$

有了這個 box 檔母體,就可據以複製增生新的虛擬機執行個體;在本機端,甚至讓別的電腦下載回去安裝。

據 Vagrant 官方文件 “Box File Format” 的說法,box 檔案會是一個壓縮檔(tartar.gzzip)。以此例而言,壓縮檔是 tar.gz 格式:

$ # 看看這個壓縮檔裡面到底塞了哪些東西...
$ tar ztvf redis.box
-rw-------  0 william staff 352730624  9 23 23:00 ./box-disk1.vmdk
-rw-------  0 william staff     10849  9 23 22:59 ./box.ovf
-rw-r--r--  0 william staff       505  9 23 23:00 ./Vagrantfile
$

這 box 壓縮檔的內容,是不是似曾相識呢?

沒錯!解壓縮後的內容,其實就是本系列文章第三集提過的這些東西:

Vagrant box 檔案本體被 Vagrant 藏在哪裡?

如果你沒有改變 VAGRANT_HOME 環境變數的話,預設目錄會是:

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

可見,本機端的 Vagrant repository,其實擺的就是 box 檔案解壓縮之後的東西,再加上一些輔助資訊。

加進本機端 Vagrant repository

我們可用 vagrant box add 指令,叫 Vagrant 將這個虛擬機 box 檔案,以指定的名字,添加、登記到本機端的 Vagrant repository。

假設我們想把它取名為 my-redis-1

$ # 先看看目前本機端的 Vagrant repository 已有哪些 box:
$ vagrant box list
ubuntu/trusty64                   (virtualbox, 14.04)
$
$
$ # 把 redis.box 這個虛擬機檔案,添加到本機端的 Vagrant repository,
$ # 並取名為 my-redis-1
$ vagrant box add  --name my-redis-1  redis.box
==> box: Adding box 'my-redis-1' (v0) for provider:
    box: Downloading: file:///private/tmp/demo-redis-1/redis.box
    box: Progress: 0% (Rate: 0/s, Estimated time remaining: --:--
    box: Progress: 70% (Rate: 267M/s, Estimated time remaining: 0
==> box: Successfully added box 'my-redis-1' (v0) for 'virtualbox'!
$
$
$ # 現在,再看看是否真的已經有一個 `my-redis-1` box 生出來了:
$ vagrant box list
my-redis-1                        (virtualbox, 0)
ubuntu/trusty64                   (virtualbox, 14.04)
$
$
$ # 或是,更深入一點看看本機端的 Vagrant repository 內容:
$ ls -al ~/.vagrant.d/boxes/my-redis-1/0/virtualbox/
total 688968
drwxr-xr-x  6 william  staff        204  9 23 23:09 .
drwxr-xr-x  3 william  staff        102  9 23 23:09 ..
-rw-r--r--  1 william  staff        505  9 23 23:09 Vagrantfile
-rw-------  1 william  staff  352730624  9 23 23:09 box-disk1.vmdk
-rw-------  1 william  staff      10849  9 23 23:09 box.ovf
-rw-r--r--  1 william  staff         25  9 23 23:09 metadata.json
$
$
$ # 與前面的 redis.box 壓縮檔內容對照看看...
$ tar ztvf redis.box
-rw-------  0 william staff 352730624  9 23 23:00 ./box-disk1.vmdk
-rw-------  0 william staff     10849  9 23 22:59 ./box.ovf
-rw-r--r--  0 william staff       505  9 23 23:00 ./Vagrantfile
$

兩相比對,顯而易見的,本機端的 Vagrant repository,其實擺的就是 box 檔案解壓縮之後的東西,再加上一些輔助資訊(即此例的 metadata.json)。

複製增生虛擬機執行個體

只要 box 檔案有添加登記到本機端的 Vagrant repository,日後就可用這個登記過的名字去 vagrant initvagrant up 相同組態的虛擬機執行個體。

首先,換一個乾淨的工作目錄:

$ cd ..
$ mkdir demo-redis-2
$ cd demo-redis-2

再根據 my-redis-1 這個登記在案的虛擬機母體,複製增生一份虛擬機執行個體:

$ vagrant init my-redis-1
$ vagrant up

你可以 vagrant ssh 進去看一看,是否一切正常。

小測驗:打包、安裝一份 Ubuntu + Docker box

中場休息一下,來一段小測驗。

在上一集文章中,我們已經手動在 Ubuntu 這個 guest OS 裡面,安裝設定出一份 Ubuntu + Docker 系統。現在,請你根據本篇文章學的新把戲,從頭開始一步一步做出:

  1. 以 Ubuntu 做為 guest OS,啟動,登入。
  2. 手動設定此 guest OS 組態(可參考上次的錄影,複習一下 Ubuntu + Docker 安裝過程: http://www.screencast.com/t/7XqIo9Cepb4 )。
  3. 打包,存檔。
  4. 加進本機端 Vagrant repository。
  5. 複製增生虛擬機執行個體。

參考解答: https://asciinema.org/a/11924

散佈 box 檔

有了 box 檔,不只可以安裝在本機端的 Vagrant repository。只要把它擺在一個可供他人下載的網路空間,甚至可讓別的電腦下載回去,安裝在其他電腦自己的本機端 Vagrant repository。

這個所謂「可供他人下載的網路空間」,簡單一點的,通常會是像 Dropbox、Google Drive 之類的網路硬碟、雲端硬碟;高檔一點的,可能會是 Amazon S3 或 CDN;有隱私要求的,則可放在私有檔案伺服器。

來演練一次吧!

首先,上傳 box 檔案到某一個可供他人下載的網路空間,並記下它的 URL。以我的例子,網址是 http://bit.ly/vagrantbox-redis

接著,換一個乾淨的工作目錄:

$ cd ..
$ mkdir demo-redis-3
$ cd demo-redis-3

接著,編輯 Vagrantfile 內容,加上一行 config.vm.box_url 設定。正如變數名稱所暗示的,這裡要填上該 box 檔案的 URL:

VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|

  # 這次,改取名為 "my-redis-2"
  config.vm.box = "my-redis-2"

  # 填入該 box 檔案所在網址
  config.vm.box_url = "http://bit.ly/vagrantbox-redis"

end

一切就緒,讓我們啟動虛擬機吧!

$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Box 'my-redis-2' could not be found. Attempting to find and install...
    default: Box Provider: virtualbox
    default: Box Version: >= 0
==> default: Adding box 'my-redis-2' (v0) for provider: virtualbox
    default: Downloading: http://bit.ly/vagrantbox-redis
    default: Progress: 0% (Rate: 0/s, Estimated time remaining: -
[略]
    default: Progress: 99% (Rate: 723k/s, Estimated time remainin
==> default: Successfully added box 'my-redis-2' (v0) for 'virtualbox'!
==> default: Importing base box 'my-redis-2'...
==> default: Matching MAC address for NAT networking...
==> default: Setting the name of the VM: demo-redis-3_default_1411486799399_97764
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
    default: Adapter 1: nat
==> default: Forwarding ports...
    default: 22 => 2222 (adapter 1)
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
    default: SSH address: 127.0.0.1:2222
    default: SSH username: vagrant
    default: SSH auth method: private key
    default: Warning: Connection timeout. Retrying...
==> default: Machine booted and ready!
==> default: Checking for guest additions in VM...
==> default: Mounting shared folders...
    default: /vagrant => /private/tmp/demo-redis-3
$

輸出畫面中有這麼一行:

==> default: Adding box 'my-redis-2' (v0) for provider: virtualbox
    default: Downloading: http://bit.ly/vagrantbox-redis

表示 Vagrant 真的有試著去指定網址下載 box 檔案。

再往下看,看到這一行:

==> default: Successfully added box 'my-redis-2' (v0) for 'virtualbox'!

我們就來看一看,本機端的 Vagrant repository 是否真的已經新增了 my-redis-2 這個 box:

$ vagrant box list
my-redis-1                        (virtualbox, 0)
my-redis-2                        (virtualbox, 0)
ubuntu/trusty64                   (virtualbox, 14.04)
$

同樣的,你可以 vagrant ssh 進去看一看,是否一切正常。

從這個例子可以看出,只要別人知道 box 檔案的網址,就可以自己依樣畫葫蘆寫一份 Vagrantfile 檔,以將它下載安裝到他們自己的本機端 Vagrant repository;至於他們想替這個 box 取什麼名字,則由他們自己決定。

現在你應該知道,該怎麼善用像 Vagrantbox.es 網站所列的 box 檔案母體了。

加進 Vagrant Cloud repository

到目前為止,我們所示範的,都是把 box 登記到本機端的 repository(或其他電腦自己的本機端 repository),取的 box 名字也都是相對於本機端。

所謂的「相對於本機端」的名字,意思是:前面我們示範出來的 my-redis-1my-redis-2 這類的 box 名字,他們的有效能見範圍(就像程式語言的 scope 概念),只限於該機器本身。換句話說,我電腦裡面的 my-redis-1,不見得和你電腦裡面的 my-redis-1 一樣。

那麼,像 ubuntu/trusty64hashicorp/precise64chef/centos-6.5 這種全域式的 box 名字,是怎麼設定出來的?

答案是,要向 Vagrant 發明人 Mitchell Hashimoto 所創辦的 HashiCorp 公司所經營的 Vagrant Cloud 服務辦理登記手續,Vagrand Cloud 網站才會配置 ubuntu/trusty64hashicorp/precise64chef/centos-6.5 這樣專屬的全域名稱,供世界各地的 Vagrant 用戶引用。

所以,Vagrant Cloud 就相當於 Vagrant 世界的中央 repository。

把 box 送進這個中央 repository 的步驟是:

  1. 如前一節所示範的,先將 box 檔案上傳到一個可供他人下載的網路空間。
  2. 登入 Vagrant Cloud 網站,替 box 取一個名字:vagrant-5-vagrantcloud-naming
  3. 填入該 box 檔案所在網址:vagrant-5-vagrantcloud-uploading
  4. 發佈!vagrant-5-vagrantcloud-release

發佈完畢,其他人就可在 Vagrant Cloud 搜尋到它。如果你希望這是個只限特定人士才搜得到、用得到的 box,就得升級成付費會員。

來驗收成果吧。假設我們在 Vagrant Cloud 將它取名為 williamyeh/redis 的話,以後全世界各地用戶,都可以這樣引用它:

$ vagrant init williamyeh/redis
$ vagrant up

照例,你可以 vagrant ssh 進去看一看是否一切正常。整段操作細節也都錄影起來了: http://www.youtube.com/watch?v=dUwoUPqQQPM

這種方法的好處是,用戶不必知道 box 檔案實際擺放的網址,不必手寫 Vagrantfileconfig.vm.box_url 設定值,還享有 Vagrant Cloud 網站提供的瀏覽搜尋服務協助你曝光成果。缺點則是,如果你不是付費會員,你的成果會被迫公開在全世界人類眼前。

自動設定 Guest OS 組態:Provisioning

剛剛我們已經先手動將虛擬機組態設定、儲存、複製增生虛擬機等流程完整走過一遍,現在該設法自動化整個流程了。

回顧一下,本文到目前為止,依序手動演練過哪些任務:

  1. 手動設定 Guest OS 組態
  2. 打包,存檔
  3. 加進本機端 Vagrant repository
  4. 複製增生虛擬機執行個體
  5. 散佈 box 檔
  6. 加進 Vagrant Cloud repository

該怎麼自動化這些任務呢?

其中,(2)~(5) 都只是在 host OS 裡面串接流程而已,很容易用腳本語言搞定。「(6) 加進 Vagrant Cloud repository」稍微麻煩一點,需要透過 Vagrant Cloud API,但這份 API 是帶有 REST 風格的,用腳本語言就能串起來,厲害一點的人,甚至用 bash + curl 組合技就能搞定。

剩下「(1) 手動設定 Guest OS 組態」這一點,還沒介紹該如何自動化。

這段自動化環節,有一個正規的術語,叫做「provisioning」。據 Wikipedia 的解釋:

Server provisioning is a set of actions to prepare a server with appropriate systems, data and software, and make it ready for network operation.

Typical tasks when provisioning a server are: select a server from a pool of available servers, load the appropriate software (operating system, device drivers, middleware, and applications), appropriately customize and configure the system and the software to create or change a boot image for this server, and then change its parameters […] to find associated network and storage resources […] to audit the system.

[…] This makes the system ready for operation.

節錄自 http://en.wikipedia.org/wiki/Provisioning#Server_provisioning

如果懶得讀那麼長的說明,只要抓住頭尾兩句重點:

  • Server provisioning is a set of actions to prepare a server” 告訴我們,provisioning 往往是一連串的連續動作。
  • This makes the system ready for operation” 告訴我們,provisioning 的目的是讓系統組態設定到可上線運作的 “I’m READY!” 狀態。

Vagrant 提供三種自動化 provisioning 機制。由淺入深,依序是:

  1. inline script(內嵌腳本)
  2. external script file(外部腳本檔)
  3. configuration management software(組態管理軟體)

只要依照各自的語法去修改 Vagrantfile,爾後,在以下幾種情況,Vagrant 都會自動執行我們準備好的一系列自動化 provisioning 指令:

  • vagrant up 第一次執行時。
  • 每次執行 vagrant up --provision 時。
  • 每次執行 vagrant provision 時。
  • 每次執行 vagrant reload --provision 時。

讓我們逐一嘗試這三種做法。

Inline script 內嵌腳本

內嵌腳本的做法是,將我們要 Vagrant 自動執行的一系列自動化 provisioning 指令,以 shell script 語法,塞入 Vagrantfileconfig.vm.provision 設定值。譬如說,如果寫成這樣:

Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/trusty64"
  config.vm.provision "shell", inline: "echo Hello, World"
end

那麼,當你在此工作目錄下,第一次執行 vagrant up 時,會看到輸出畫面的最後面,在 guest OS 啟動完畢後,在 port forwarding 及 shared folder 也都配置完畢後,還多執行了一行 echo Hello, World 指令:

$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'ubuntu/trusty64'...
[略]
==> default: Machine booted and ready!
==> default: Checking for guest additions in VM...
==> default: Mounting shared folders...
    default: /vagrant => /private/tmp/z
==> default: Running provisioner: shell...
    default: Running: inline script
==> default: stdin: is not a tty
==> default: Hello, World

當然啦,實務上,我們要塞的自動化指令,不會只有 echo Hello, World 這麼一行而已。萬一我們想塞多行指令進去呢?

Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/trusty64"
  config.vm.provision "shell",
    inline: "echo Hello, World\necho World Peace\necho I love Vagrant"
end

寫法有點蠢。

漂亮一點的寫法是,利用「Vagrantfile 本身也就是一份遵循 Ruby DSL 規則的 Ruby 源碼文件」此一事實(本系列文章第三集介紹過),再借用 Ruby 的 heredoc 語法,將 Vagrantfile 改寫成:

$script = <<SCRIPT
# 安裝 Redis...
sudo apt-get install redis-server -y
# 允許 Redis bind 至全部 network interface...
sudo sed -i -e 's/^bind/#bind/' /etc/redis/redis.conf
# 重啟 Redis,讓新設定生效。
sudo service redis-server restart
SCRIPT

Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/trusty64"
  config.vm.provision "shell", inline: $script
end

如此一來,程序式的 provisioning 指令擺在前面,宣告式的虛擬機屬性內容擺在後面,一邊一國明顯區隔成兩塊,比較好維護。

External script 外部腳本檔

上述 script 內容,還可更進一步抽離到外部檔案。

譬如說,如果我們在工作目錄裡,寫一個 install.sh 檔:

#!/bin/bash

# 安裝 Redis...
sudo apt-get install redis-server -y
# 允許 Redis bind 至全部 network interface...
sudo sed -i -e 's/^bind/#bind/' /etc/redis/redis.conf
# 重啟 Redis,讓新設定生效。
sudo service redis-server restart

然後,修改 Vagrantfileconfig.vm.provision 設定值,讓它指涉到外部腳本檔 install.sh

Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/trusty64"
  config.vm.provision "shell", path: "install.sh"
end

如此一來,Vagrant 便會在 provisioning 階段,載入並執行這個 install.sh 檔。

這種寫法,適合有潔癖的人。

Configuration management 組態管理軟體

如果上線主機早已導入組態管理機制,也早已運用像 ChefPuppetAnsibleSalt 這類比 shell script 更合身的軟體,是否也能套用在 Vagrant 的 provisioning 環節?如此一來,就能 “infrastructure as code” 一以貫之了。

譬如說,以下這份 Ansible 檔案,可用來將 Redis 安裝在 Ubuntu 上:

---
# file: playbook.yml
# Ansible playbook for installing Redis on Ubuntu

- hosts: all
  sudo: True

  tasks:
    - name: Install the Redis package
      apt: name={{ item }} state=present update_cache=yes
      with_items: redis-server

    - name: let Redis bind all network interfaces, if necessary.
      lineinfile: dest=/etc/redis/redis.conf regexp="^bind 127.0.0.1" line="#bind 127.0.0.1" insertafter="^bind"

    - name: restart redis-server
      service: name=redis-server state=restarted enabled=yes

該怎樣將它套用在 Vagrant 身上呢?

有兩種做法,硬漢法及懶人法。

硬漢法:叫 Ansible 直接對已經 vagrant up 之後的 guest OS 進行 SSH 連線,透過此 SSH 通道設定 guest OS 組態。當然啦,本系列文章第四集就提醒過了,想當嘴硬的硬漢,就得手動輸入該 guest OS 對外開放的 IP 位址 (預設為 127.0.0.1)、TCP 通訊埠 (預設為 2222),甚至登入的帳號 (vagrant) 及密碼 (vagrant):

$ # 先啟動 guest OS
$ vagrant up
$
$ # 將這次 Vagrant 告訴我們的 SSH host:port 填入 Ansible inventory file
$ cat <<EOF > inventory
[vagrant]
127.0.0.1 ansible_ssh_port=2222
EOF
$
$ # 叫 Ansible 透過 SSH 連線,將 "playbook.yml" 組態套用進去
$ ansible-playbook -c paramiko -u vagrant -k -vvv -i inventory playbook.yml

整個經過,請見錄影: http://asciinema.org/a/12556

懶人法:首先,編輯 Vagrantfile 內容,加入 config.vm.provision 一系列設定值:

Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/trusty64"

  config.vm.provision "ansible" do |ansible|
    ansible.playbook = "playbook.yml"
    ansible.sudo = true
  end
end

接著,直接 vagrant up(或 vagrant up --provisionvagrant provision)即可,不必準備 inventory 檔案,也不必手動執行 ansible-playbook 程式、夾帶一堆命令列參數,Vagrant 會替你打理好這堆瑣事。整個過程,請見錄影:https://asciinema.org/a/12554

懶人法的確簡單多了。不過,你還是必須知道硬漢法的原理。

這裡只是簡單示範如何將組態管理軟體融入 Vagrant provisioning 機制中,實務上組態管理遠比此例複雜,請參考 Vagrant 官方文件的 Provisioning 章節。

Docker, again!

前面的小測驗,我們已經手動打包一份「Ubuntu + Docker engine」box。現在,如果想將某個 Docker image 自動裝進去,該怎麼做?

你可能會利用剛剛學到的 inline script 來安裝:

Vagrant.configure("2") do |config|
  config.vm.box = "williamyeh/ubuntu-trusty64-docker"
  config.vm.provision "shell",
    inline: "docker pull redis:latest"
end

或者,利用 Vagrant 1.6 新增的 “docker” provisioner 語法

Vagrant.configure("2") do |config|

  # any base box with Docker engine installed is OK;
  # e.g, "yungsang/coreos", "yungsang/coreos-beta"
  config.vm.box = "williamyeh/ubuntu-trusty64-docker"

  # pull images from the Docker registry
  # see http://docs.vagrantup.com/v2/provisioning/docker.html
  config.vm.provision "docker", images: ["redis:latest"]
end

Vagrant 1.6 對於 Docker 的支援還不僅如此,有興趣的,可參考以下文章:

回顧:虛擬機 Wish List

本系列文章第二集曾經分析過,軟體研發者需要以下這些「可程式化介面」,才能將虛擬機納入軟體開發工具鏈中:

  1. 自動安裝一台或多台指定版本的 guest OS 虛擬機。
  2. 自動設定好這些虛擬機叢集的組態,與上線主機共用同一套組態管理機制。
  3. 儲存虛擬機現有狀態,可日後回復或快速複製。
  4. 虛擬機層次的 repository 中央儲存庫。

到目前為止,我們已經用 Vagrant 逐一實現各般需求,只剩下「多台虛擬機叢集」這一招。請待下回分解。

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

相關文章

留言

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

關於作者

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

熱門論壇文章

熱門技術文章