開發需要在各種系統上進行開發任務,運維則需要在各種系統上學習工具使用。因此,虛擬機恐怕也是 IT 人員最常使用的工具之一了。最常用的虛擬化工具有 VMware Workstation 和 VirtualBox 等等,雖然底層的實現各有不同,但具體的使用方法則非常相近:打開工具,為虛擬機創建一塊存儲空間,配置一下性能參數,在界面中安裝系統,接下來就可以使用了。很多時候,為了滿足虛擬機重復使用的需要,各種虛擬機工具中還會帶有“模版”功能和“快照”功能,前者可以方便地讓用戶創建出標準的虛擬機,后者可以讓用戶快速的回復到以前的狀態。
虛擬化為 IT 人員提供了極大的便利。但是,人們很快便不滿足此了。具體說來,使用虛擬機的時候,用戶往往會遇到下面的問題:
- 虛擬化工具學習成本:有的時候,配置虛擬機的步驟比較繁瑣,普通用戶上手可能比較困難。
- 環境無法共享:一個人創建的環境和另一個人創建的環境很難完全一致,在 Alice 的虛擬機中跑的好好的代碼,到了 Bob 的機器上可能怎么也運行不起來。
- 虛擬化平臺不統一:不同用戶、不同場景使用的平臺可能不一樣,在不改變工作流程的前提下,很難跨躍多個平臺來進行虛擬化管理和資源使用。
后來,上面的問題終于有了解決的方法:Vagrant。
Vagrant 是一套用 Ruby 編寫的工具,它為用戶提供了一種標準化、可定義、可分享的虛擬化平臺使用模式。使用 Vagrant,用戶可以使用文本文件來“定義”一個虛擬機,快速創建出自己想要的環境,還可以將其分享給其他人;此外,Vagrant 還支持多款虛擬化平臺,VMware、Virtualbox、AWS 甚至是 Docker 都可以,用戶再也不需要為對接多個虛擬化平臺而犯愁了。
本文便旨在向讀者介紹性感的 Vagrant,帶領讀者進行 Vagrant 快速上手。這個過程中還會用其搭建一臺 ELK 服務器,來展示 Vagrant 的便捷和強大。
部分操作步驟和腳本來自官方文檔,下文不會單獨指出。
筆者使用的環境為 macOS Sierra 10.12.3 ,Vagrant 1.9.1 以及 VirtualBox 5.1.14。
1. 前期準備和安裝
Vagrant 將其支持的各種虛擬化平臺稱為 “Provider”。我們在本次的快速上手中選擇了 VirtualBox 作為后端虛擬化平臺。因此,您首先需要安裝最新版本的 VirtualBox 來搭配 Vagrant。請訪問這里下載最新版的 VirtualBox。
安裝 Vagrant 的方法也很簡單,在此處下載安裝即可。需要注意的是,如果您使用的是 macOS 或 Linux,您可能希望使用 Brew 或者 YUM 等軟件管理器來安裝,然而官方并不推薦這樣做:在第三方軟件管理器的軟件倉庫中,Vagrant 可能版本較低,或者缺少依賴包。因此還是建議用戶直接在官方網站上下載安裝。
在安裝之后,用戶的家目錄下會多出一個給 Vagrant 使用的隱藏文件夾 .vagrant.d
。這里將保存 Vagrant 所需的所有基礎配置。如果將其刪除,再次運行 Vagrant 時,Vagrant 會認為這是一次全新安裝,然后再次將該文件夾創建出來。
2. 創建項目文件夾和 Vagrantfile
接下來我們就可以為創建虛擬機做準備了。首先,我們要為虛擬機創建一個主目錄,用來存放與該服務器相關的文件等;然后在這個文件夾中創建 Vagrant 的主配置文件:Vagrantfile。
Vagrantfile 是用來描述虛擬機狀態的主文件,其中包括虛擬機鏡像、機器配置、網絡配置、以及初始化腳本等。通過使用 vagrant init
命令,我們便可以創建出一份標準的 Vagrantfile。
$ mkdir vagrant_getting_started
$ cd vagrant_getting_started
$ vagrant init
這樣一來,我們便創建出 Vagrantfile
這個文件了。
3. 獲取虛擬機模版:Box
有了虛擬機的配置文件還不夠,我們要告訴 Vagrant 使用哪一個虛擬機模版。以前我們會自己從頭創建虛擬機,然后自己制作成模版;而在 Vagrant 的世界,模版名稱叫做 “Box”。此外,Vagrant 還有一個專門的模版倉庫,提供一些權威機構或用戶創建的模版供用戶下載。
讓我們用 Vagrant 下載一份 CentOS 7.3 的 Box。這里我們選用了 Bento 項目提供的鏡像。這個項目由 Chef 公司發起,旨在為 Vagrant 制作各種操作系統的標準 Box。
$ vagrant box add bento/centos-7.3
首次下載時間較長。在國內,速度可能會比較慢。如果有搭梯子的方法,建議各位在 Shell 中使用 HTTP 代理下載。
下載完成之后,這份 CentOS 7.3 的 Box 會被保存在 ~/.vagrant.d/boxes/bento-VAGRANTSLASH-centos-7.3
中。再繼續往下尋找,會找到.vmdk
格式的虛擬機文件。這就是我們需要的虛擬機模版了。
Vagrant Box 的命名規則為“用戶名/項目名”,比如 bento/centos-7.3
,和 Github 的風格很像。
打開我們創建的“Vagrantfile”文件,告訴 Vagrant 我們要使用剛剛下載的 bento/centos-7.3
。
Vagrant.configure("2") do |config|
config.vm.box = "bento/centos-7.3"
end
如果我們在這里填了一個沒有預先下載好的 Box 名稱,Vagrant 會先去官方的 Box 庫將其下載下來,保存在上面提到的目錄中。
Box 還支持版本標記,如果我們希望使用某一個 Box 的特定版本,我們也可以在 Vagrantfile 中指定。例如:
Vagrant.configure("2") do |config|
config.vm.box = "bento/centos-7.3"
config.vm.box_version = "2.3.1"
end
4. 啟動虛擬機以及使用 SSH 連接
接下來我們便可以啟動虛擬機了。
$ vagrant up
這個過程中完全不需要打開 VirtualBox,Vagrant 會自己去調用 VirtualBox,完成所有創建的工作。
創建完成之后,我們可以通過 Vagrant 提供的 SSH 直接連接到服務器中,Vagrant 已幫我們配置好端口映射和密鑰,非常方便。
$ vagrant ssh
按照平時的方式退出 SSH 便可退回到原來的 Shell。
如果希望將這臺服務器關機,可以執行:
$ vagrant halt
在現在的這個目錄下再次執行 vagrant up
即可將其重新開啟。
如果希望刪除這臺虛擬機,也非常方便:
$ vagrant destroy
此時,這臺虛擬機便會被刪除。但是,我們使用過的 Box 并不會被刪除掉。它還會保存在 ~/.vagrant.d
中,以便我們再次使用。如果需要刪除某一個 Box,使用 vagrant box remove
加上 Box 的名稱即可。
5. 共享文件夾
Vagrant 提供了在宿主機和虛擬機之間的一個共享文件夾功能。如果你使用的是 VirtualBox,這個功能要求虛擬機中安裝有 VirtualBox Guest Addition。我們剛剛使用的 “bento/centos-7.2” Box 中已經預裝了該工具,所以可以直接使用。
宿主機方面,共享文件夾便是我們剛才使用的 Vagrantfile 所在的項目文件夾;虛擬機方面,共享文件夾的路徑位于 /vagrant
。
注意:但如果你是在 “bento/centos-7.3” Box 中使用共享目錄功能,請不要嘗試升級內核。在我自己的測試過程中,更新內核會導致 VirtualBox Guest Addition 失效,導致共享文件夾無法使用。
Vagrant 還提供了其他的同步方法,包括 rsync,NFS 等等。但這些或多或少需要在宿主機上面做一些相應的配置,所以這里還是推薦使用 VirtualBox Guest Addition。
6. 網絡
Vagrant 可以幫助我們配置端口映射。比如我們剛剛使用的 vagrant ssh
命令,實際上連接的也是我們宿主機的 2222 端口,只是由 Vagrant 操縱 VirtualBox 將虛擬機的 22 端口映射了過來而已。
此外,我們還可以在 Vagrantfile 中自行配置希望映射的端口,寫法也非常簡單:
Vagrant.configure("2") do |config|
config.vm.box = "bento/centos-7.3"
config.vm.network :forwarded_port, guest: 80, host: 4567
end
這樣一來,如果在這個虛擬機里開啟了跑在 80 端口的 HTTP 服務,便可以在宿主機的 http://127.0.0.1:4567
訪問到了。
網卡也可以通過 Vagrantfile 來配置。上面的內容都是針對于使用 VirtualBox NAT 的網絡選項來說的,這種配置適用于一些比較簡單的場景。如果有配置 Public IP 或 Private IP 的需求,也可以寫在 Vagrantfile 中:
Vagrant.configure("2") do |config|
config.vm.box = "bento/centos-7.3"
config.vm.network :forwarded_port, guest: 80, host: 4567
config.vm.network "private_network", ip: "192.168.10.101"
config.vm.network "public_network"
end
在 Vagrant 和 VirtualBox 的搭配中,Vagrant 所謂的 private_network
會自動和 VirtualBox 的 “Host-only network” 相對應,是一個僅包含了宿主機和虛擬機的網絡,且需要預先在 VirtualBox 的網絡配置中創建出來;而 public_network
和 “Bridged network” 相對應,在網絡中和宿主機處于平等地位。
7. 系統初始化
如果 Vagrant 僅能做到如此,對于解放生產力來說還是不夠的。因此 Vagrant 內置了一套系統初始化功能,能夠讓用戶在創建虛擬機時便將初始化工作一并完成。這套功能在 Vagrant 中被稱為 “Provision”。
Provision 支持多種初始化腳本。用戶可以把需要執行的 Shell 命令寫在 Vagrantfile 中,也可以單獨寫一個 Bash 腳本。Vagrant 還支持 Ansible、CFEngine、Chef、Puppet 等眾多配置管理工具。Vagrant 介紹了使用 Bash 腳本的例子,我們這里用 Ansible 來做一個范例,來展示一下如何利用 Provision 功能。
如果希望使用 Ansible,前提是宿主機上已安裝好了 Ansible,macOS 下使用 Brew 或者 pip 均可,這里暫且不表。接下來,我們在這個虛擬機項目的文件夾中創建一個 Ansible Playbook,將其命名為 elk-playbook.yml
。
---
- hosts: all
become: true
tasks:
- name: disable-ipv6
sysctl:
name: "net.ipv6.conf.all.disable_ipv6"
value: 1
sysctl_set: yes
reload: yes
- name: download-java-8u112
shell: 'curl -v -j -k -L -H "Cookie: oraclelicense=accept-securebackup-cookie" http://download.oracle.com/otn-pub/java/jdk/8u112-b15/jdk-8u112-linux-x64.rpm > /vagrant/jdk-8u112-linux-x64.rpm'
args:
creates: "/vagrant/jdk-8u112-linux-x64.rpm"
- name: install-java-with-yum
yum:
name: /vagrant/jdk-8u112-linux-x64.rpm
state: present
- name: add-elk-repo
yum_repository:
name: elk-5.x
description: Elasicsearch repo files
file: elk-5.x
baseurl: https://artifacts.elastic.co/packages/5.x/yum
gpgcheck: no
- name: install-elk-packages
yum:
name: "{{ item }}"
state: present
with_items:
- elasticsearch
- logstash
- kibana
- filebeat
- metricbeat
接下來,我們編輯 Vagrantfile,告訴 Vagrant 在創建虛擬機之后執行我們的 Playbook。
Vagrant.configure("2") do |config|
config.vm.box = "bento/centos-7.3"
config.vm.provision "ansible" do |ansb|
ansb.playbook = "elk-playbook.yml"
ansb.sudo = true
end
end
然后我們便可以執行 vagrant up
了。在正常顯示虛擬機創建過程提示后,將會顯示的 Ansible 執行過程。
因為要下載的內容比較多,安裝時間可能會比較長。在成功執行完成 Ansible Playbook 之后,一個完整安裝了 ELK 環境的虛擬機便創建完成了!
8. 全網共享
有了這些功能,Vagrant 在日常開發和學習環境中已經帶給用戶極大的便利了。然而這還不算完,Vagrant 還有一個不得不說的犀利功能:全網共享。
比如,你在你自己的虛擬機中運行著自己開發的網站,希望展示另一個城市的朋友。有了 Vagrant,你可以輕松地創建出一個臨時的地址,朋友只要訪問這個地址,便可以直接訪問到你虛擬機上的網站來;不僅是網站,通過這個地址 SSH 到你的虛擬機也可以;甚至,任何一個端口,經過配置之后,都可以映射到這個公網的地址,共享給他人進行訪問,稱得上完全意義上的“全網全局共享”。
使用這個功能的前提是用戶已經注冊了 HashiCorp 的 “Atlas” 賬號。HashiCorp 是發布和維護 Vagrant 工具的公司,Atlas 是這家公司的一套企業級 IT 產品,但創建賬號、使用共享功能是完全免費的。
首先,我們要在 Shell 中登錄 Atlas 賬號。
$ vagrant login
Username or Email: colinleefish@gmail.com
Password (will be hidden):
You are now logged in!
然后就可以使用共享功能了。
$ vagrant share
...
==> default: Your Vagrant Share is running!
==> default: URL: http://frosty-weasel-0857.vagrantshare.com
...
如果你的虛擬機中的 80 端口正在提供 HTTP 服務,上面的鏈接便可以直接訪問到你的網站。
如果你希望朋友通過 SSH 連接到你的服務器,在共享命令中加入 --ssh
參數即可。
$ vagrant share --ssh
==> default: Detecting network information for machine...
default: Local machine address: 192.168.163.152
default: Local HTTP port: 4567
default: Local HTTPS port: disabled
default: SSH Port: 22
==> default: Generating new SSH key...
default: Please enter a password to encrypt the key:
default: Repeat the password to confirm:
default: Inserting generated SSH key into machine...
==> default: Checking authentication and authorization...
==> default: Creating Vagrant Share session...
default: Share will be at: itty-bitty-polar-8667
==> default: Your Vagrant Share is running!
default: Name: itty-bitty-polar-8667
...
將最下面的隨機名字(itty-bitty-polar-8667
)發給你的朋友,你的朋友在他的 Shell 中執行 vagrant connect --ssh itty-bitty-polar-8667
即可連接到你的虛擬機上來了。
$ vagrant connect --ssh itty-bitty-polar-8667
Loading share 'itty-bitty-polar-8667'...
The SSH key to connect to this share is encrypted. You will
require the password entered when creating the share to
decrypt it. Verify you have access to this password before
continuing.
Press enter to continue, or Ctrl-C to exit now.
Password for the private key:
Executing SSH...
Welcome to Ubuntu 12.04.3 LTS (GNU/Linux 3.8.0-29-generic x86_64)
* Documentation: https://help.ubuntu.com/
Last login: Fri Mar 7 17:44:50 2014 from 192.168.163.1
vagrant@vagrant:~$
當然,你和你的朋友能使用這個功能的前提是你們都安裝了 Vagrant。
……既然 Vagrant 這么強大,有什么理由不推薦給他呢?
有關 Vagrant 的特點和使用方法,我們就先介紹到這里,希望對讀者有所幫助。感謝閱讀,也歡迎留言或者和我交流。