vagrant 知識庫

版權聲明:轉載時請以超連接形式標明文章原始出處和做者信息及本聲明 
http://wushaobo.info/?p=83

Vagrant讓虛擬化技術走近尋常家。腳踏實地地說,網絡上相似「兩分鐘入門」的文章有很多,但求助各類問題的帖子更多,由於vagrant官網的文檔太簡潔了,這裏頭有些道理有些坑,都沒涉及到。即使是O’Reilly兩天前出版的 《Vagrant: Up and Running》 也含糊着某些問題。於是在Google了各類的前人零碎經驗的基礎上、以本身實踐證實以後,有了我這篇文章,但願對涉及到的這些問題能彙總知識作一個澄清,並給讀者一個可操做的指導。html

文章結構

vagrant 的便利 
vagrant 怎麼玩 
vagrant 到底怎麼玩 
— vagrant 基礎模板哪兒找 
— 辨析 vagrant box | *.box文件 | VM | *.iso文件 
— Vagrantfile 怎麼配 
——- [HOWTO] 指定要使用的vagrant box和設置VM名稱 
——- [HOWTO] 設置VM對宿主機和外部機器的網絡鏈接 
——- [HOWTO] 配置並啓動VM後運行後續安裝腳本 
疑難雜症 
— VM上端口的可訪問性 
— 修改默認ssh端口 
— 將VM打包成*.box文件前清理網絡設置上的障礙 
— 設置共享目錄位置與讀寫權限 
— 多個VM的配置和啓動

vagrant 的便利

  • 打造Virtual Machine的過程當中可放手作嘗試,反覆從某個基礎模板開始安裝或設置。可快速推倒重來,可步步爲營。
  • 可快速在一臺宿主機上搭建多VM的EndToEnd環境。
  • 管理開發環境,可腳本化複製、操縱等行爲,提升自動化程度。

vagrant 怎麼玩

簡單點說,三步走:linux

  • 安裝 vagrant 、VM軟件( Virtualbox 是主流,後文也默認以此爲例)
  • 給vagrant添加基礎模板(box)
  • 配置Vagrantfile後用vagrant啓動VM

滿共就三個命令,有些人玩到這就以爲已經偉大的不得了了,至此ssh上VM各類虐。web

你還差得遠 !shell

vagrant 到底怎麼玩

vagrant 基礎模板哪兒找

www.vagrantbox.es 介紹了vagrant的基礎模板,並提供了知足各類需求的*.box文件供下載。apache

推薦選擇 minimal + guest additions + puppet|chef 的box,理由:ubuntu

  • 小,就意味着資源佔用少
  • Virtualbox共享目錄須要guest additions
  • 預裝puppet或chef並不是必選。它們對將來提高VM配置自動化有好處,自己不大

辨析 vagrant box | *.box文件 | VM | *.iso文件

解釋詞彙:windows

  • 打包了操做系統的 *.iso文件 是沒法被vagrant直接使用的
  • VM 是可啓動/已啓動的虛擬機
  • *.box文件 是vagrant可接受的基礎模板文件
  • vagrant box 指vagrant已安裝好的基礎模板

辨析關係:centos

  • *.iso文件 可經Virtualbox界面的手動安裝獲得可啓動的 VM
  • VM 可被vagrant package命令打包成爲 *.box文件
  • *.box文件 可被vagrant box add命令安裝爲 vagrant box
  • vagrant box 可被vagrant在Vagrantfile中指定爲 VM 運行的基礎模板

Vagrantfile 怎麼配

Vagrantfile是vagrant配置VM的起點, 官方文檔 裏零零散散的說明讓我明白了「東西很簡單,但找對不容易」這句話。網絡

對Vagrantfile,有幾個常問 HOWTO :ssh

  1. 指定要使用的vagrant box和設置VM名稱
  2. 設置VM對宿主機和外部機器的網絡鏈接
  3. 配置並啓動VM後運行後續安裝腳本

[HOWTO] 指定要使用的vagrant box和設置VM名稱

一看便知。

Vagrant.configure("2") do |config|      # ‘2’的意思是我所用的vagrant-1.2.2屬於內部v2版 
  config.vm.define :web do |web_config| # 設置此VM名稱爲web
    web_config.vm.box = "apache-centos" # 指定使用已安裝的名爲「apache-centos」的vagrant box
  end
end

參考

[HOWTO] 設置VM對宿主機和外部機器的網絡鏈接

  1. 當VM只與宿主機通訊時,可設置爲私有網絡,等效於設置virtualbox使用host-only模式網絡適配器。
    config.vm.network :private_network, ip: "192.168.50.4"
  2. 當寄宿與同一宿主機上的多臺VM之間也需相互通訊時,設置各VM爲私有網絡,但將固定IP設爲同一網段。
  3. 當VM須要與宿主機網絡內的其餘機器通訊時,設置爲公開網絡,等效於設置virtualbox使用bridged模式網絡適配器,默認DHCP獲取地址。
    config.vm.network :public_network   # vagrant-1.2.2以後的版本可能改用 :bridged

參考

[HOWTO] 配置並啓動VM後運行後續安裝腳本

  1. 追求簡單,那麼下面兩條配置其一就夠用了
    config.vm.provision :shell, :inline => "ifconfig"  # inline script
    
     config.vm.provision :shell, :path => "initialize.sh"  # external script
  2. 不得不復雜時, Chef / Puppet / Ansible 都是可供你用的。細緻配置見 參考 。
  3. 自動化部署是好的,但若是是VM每次安裝固定軟件,那麼就沒必要了。大能夠將不變的軟件安裝配置完成後,將VM打包成爲*.box文件靜態化,之後以此box文件做爲基礎模板作進一步配置。步步爲營的提高基礎的實踐,會加速VM搭建過程並減小配置腳本。

疑難雜症

VM上端口的可訪問性

尤爲對不連外網的VM,咱們辛苦建了它卻不能訪問它的端口,那要它何用?防火牆是阻止端口訪問的罪魁,索性關了它吧。

Centos/Redhat/Fedora 用iptables管理firewall,因此兩個辦法搞掉它

  1. 停掉iptables的服務, 參考
    $ sudo service iptables save
     $ sudo service iptables stop
     $ sudo iptables off
  2. 索性幹掉iptables的全部規則, 參考
    $ sudo iptables -F
     $ sudo iptables -X
     $ sudo service iptables save

Ubuntu 用ufw管理firewall,關掉它就是了, 參考

$ sudo ufw disable

修改默認ssh端口

場景

ssh端口默認22,那位說「爲何我要改它呢」,我例舉一個場景:

假如你要開發一個包含SFTP server的應用。爲了給使用者提供便利,你最好保留22端口給用戶,使他能使用默認方式經過SFTP傳文件。同時,你要將這個應用部署到VM上作測試,那麼VM的ssh login就不能同時也用22端口了,你須要爲它指定新端口,如 10022。

難點

難點在於下面的約束條件:

  • 原有VM的基礎模板默認使用22端口,因此vagrant 不能 一開始就棄用22端口,不然VM沒法訪問。
  • VM上ssh端口的改變爲新端口後,再重啓VM前 須要 更改Vagrantfile以選用新端口。
  • vagrant ssh命令 並不 直接訪問VM的ssh端口,而是經過訪問宿主機的22XX端口來間接ssh login到VM上。
  • vagrant內置了從宿主機22XX端口向VM的22端口的映射,若是VM的新端口並無被指定映射到宿主機的某個端口上,vagrant ssh命令 仍會 訪問原來的宿主機22XX端口即VM的22端口。(vagrant選擇22XX端口時的嘗試路線是:2222 -> 2201 -> 2202 -> 2203 -> … ,以此保證多臺VM啓動時不會有端口衝突。)

坑是挺多的吧?Vagrantfile的 ssh settings參考 和 forwarded ports參考 可沒把這事兒說這麼清楚。

行動大綱

解決問題需要分幾步走:

  1. 預先在Vagrantfile中爲VM的新端口作端口映射
  2. VM上修改ssh使用的端口到新端口
  3. 在Vagrantfile中指定ssh login時使用VM的新端口
  4. [非必作] 創建新基礎模板以固化上述更改

按步驟走起

Step1: 在Vagrantfile中爲VM的新端口作端口映射

config.vm.network :forwarded_port, guest: 10022, host: 2255
# config.ssh.port = 2255            # port of host  # commented in step1
# config.ssh.guest_port = 10022     # port of VM    # commented in step1

Step2: VM上修改ssh使用的端口到新端口

  • VM上將22端口換爲10022端口:vi編輯sshd_config文件( Centos/Ubuntu: /etc/ssh/sshd_config ;Mac OS X: /etc/sshd_config )
    :%s/#Port 22/Port 10022/g
      :wq
  • 重啓sshd服務
    $ sudo service sshd restart

Step3: 在Vagrantfile中指定ssh login時使用VM的新端口

config.vm.network :forwarded_port, guest: 10022, host: 2255
config.ssh.port = 2255          # port of host  # uncommented in step3
config.ssh.guest_port = 10022   # port of VM    # uncommented in step3

Step4 [optional]: 創建新基礎模板以固化上述更改

使用vagrant package命令將改過端口的VM保存爲box文件。由這個新基礎模板所產生的VM中,10022即爲ssh訪問端口,使用上述的Vagrantfile可直接經過vagrant ssh訪問。

vagrant package <vm-name> --output <new-base.box>

生成新*.box文件前須清理網絡設置上的障礙。詳見下文。

將VM打包成*.box文件前清理網絡設置上的障礙

將手動配置過的VM從新打包生成*.box文件做爲新基礎模板,在這件事上對linux-based的VM有個關於網絡設置的障礙。

問題表現

例如設置了private network(等同於virtualbox設置host-only模式的網絡適配器)的VM,若不作準備而直接使用vagrant package生成新box文件,那麼安裝此box文件到vagrant box後在啓動VM時,會發現當前Vagrantfile指定的private network配置失敗。

[default] Configuring and enabling network interfaces…

The following SSH command responded with a non-zero exit status. 
Vagrant assumes that this means the command failed!

/sbin/ifup eth1 2> /dev/null

被啓動的VM以讓能夠經過vagrant ssh命令去訪問,但網絡配置上卻沒有host-only模式的適配器。

分析解決

還記得配置private network時設置的固定ip地址麼?是的,問題就在持久網絡設備udev規則(persistent network device udev rules)是被原VM設置好的,再用box生成新VM時,這些rules須要被更新。而這和Vagrantfile裏對新VM設置private network的指令發生衝突。

既然之後在Vagrantfile裏顯示地設置private network ip是免不了的,那麼只要在生成box文件前幹掉udev規則就是了。

sudo rm -f /etc/udev/rule.d/70-persistent-net.rules

題外話

有趣的是這篇 參考 細述了這個問題的因果與對策,反卻是O’Reilly出版的 《Vagrant: Up and Running》 一書中(第6章)對此含糊帶過。

該書計劃於2013年6月12日出版。試讀版中尚仍有對過期命令的介紹(如「repackage」),但願正書出來了不會當即過期。

學習的話, 官網文檔 仍是應該對照的。

設置共享目錄位置與讀寫權限

Virtualbox共享目錄須要VM上裝有Guest Additions。本身安裝到VM再打包成box文件作基礎模板,或者一開始就找好合適的box文件(前文提到過),隨便你怎麼整好。

vagrant 默認將宿主機上Vagrantfile所載目錄共享至VM上的 /vagrant 目錄。

咱們常須要的是指定共享某個目錄,爲此vagrant 支持兩種方式:

簡單:vboxsf

vboxsf是 V irtual boxS hared F older(或 VboxS hared F older)的縮寫。不少人知道能夠指定vboxsf做類型來mount,殊不知這個這個詞全稱,甚至誤解爲「虛擬機文件系統」而錯寫成vboxfs。

vagrant默認使用這種方式共享目錄。優勢方便,缺點是性能很差。配置時,只要在Vagrantfile裏指明:

config.vm.synced_folder "path/on/host", "/absolute/path/on/vm"
  • 前一個參數須是宿主機上已存在的目錄,若爲相對目錄,那是相對Vagrantfile所在目錄。
  • 後一個參數須是VM上的絕對路徑,若不存在,vagrant會在啓動VM時建好,多層的目錄也不要緊。

正經:NFS

NFS是正途,不過它也挑剔。

vagrant 內置了宿主機和VM兩端對NFS的支持與配置的協調。若是你用windows,那vagrant看成你的配置不存在,直接忽略(我也以爲你在瞎胡鬧)。Vagrantfile裏很容易,標上標記就好了:

config.vm.synced_folder "path/on/host", "/absolute/path/on/vm", :nfs => true
  • 兩個目錄能夠同樣,如都用 「/shared」 ,藉此創建多個機器節點的共享存儲了。

NFS的共享目錄這種方式的挑剔之處在於目錄內的讀寫權限。

讀寫權限

以創建宿主機與VM的共享存儲這個應用場景爲例,目標是:

  • 兩端對共享目錄( /shared )的讀寫無限制
  • 沒有root權限的麻煩

若是你在宿主機建 /shared ,而後直接配置關聯,那對上述兩個目標你都會失敗。按我說的步驟來吧:

  1. 宿主機上將創建的共享目錄改成可讀寫
    $ sudo chmod o+w /shared
  2. 設置爲non-root用戶全部
    $ sudo chown <user>:<group> /shared
  3. 配置了Vagrantfile後啓動VM
    config.vm.synced_folder "/shared", "/shared", :nfs => true

這樣獲得的共享目錄對場景設定的目標已大功告成了:

  • 在宿主機和VM兩端都它都不是root用戶全部
    • 宿主機上 /shared 屬於例如twer用戶。
    • VM上 /shared 所屬的用戶會是個數字,如1000。
  • 在宿主機和VM兩端它都對讀寫無限制

多個VM的配置和啓動

單Vagrantfile vs 多Vagrantfile

雖然vagrant支持在一個Vagrantfile中配置多個VM,但我我的喜歡爲各VM寫各自的Vagrantfile。

  • 一來,各個VM的配置和啓動都相對獨立,如vagrant ssh時可不指定VM名,用默認。
  • 二來,Vagrantfile也不至於經常要改。

不過真正的牛人沒我這麼小家子氣。用統一的一個Vagrantfile來管理多個VM,從大局着眼確是有好處的:

  • 一個Vagrantfile收錄了整個大環境中全部VM的基本配置,維持了虛擬網絡的上下文完成。你一眼就知道環境裏共有哪些VM,也不須要切換目錄來檢查各VM的狀態,跟不會搞混了目錄「丟掉」哪一個倒黴的VM。
  • 更多地使用Chef/Puppet來配置各VM,好比把VM的ip配置從Vagrantfile後推到puppet進行,保持Vagrantfile的簡潔。目的是在對本地環境的VM配置與E2E環境(甚至生產環境)的節點配置上,保持較高的一致性,有利於統一部署方式。
相關文章
相關標籤/搜索