從字面上來看,provision是準備,實作的功能是在原生鏡像的基礎上,進行一些附加的操作,以改變虛拟機的環境,比如安裝應用,釋出程式等。
在vagrant的 Vagrant.configure(2) do |config| 節點内,加入如下代碼:
還有一種格式:
測試一下:
如果vm已經啟動,直接運作
就可以看到控制台顯示的資訊了。或者:
重新開機vm,并自動執行provision操作。
Tips: 運作後可能會提示:default: stdin: is not a tty 錯誤,不影響執行效果,想要去除,在配置檔案增加一行即可。
provision任務是預先設定的一些操作指令,格式:
每一個 <code>config.vm.provision 指令字</code> 代碼段,我們稱之為一個provisioner。
根據任務操作的對象,provisioner可以分為:
Shell
File
Ansible
CFEngine
Chef
Docker
Puppet
Salt
根據vagrantfile的層次,分為:
configure級:它定義在 <code>Vagrant.configure("2")</code> 的下一層次,形如: <code>config.vm.provision ...</code>
vm級:它定義在 <code>config.vm.define "web" do |web|</code> 的下一層次,<code>web.vm.provision ...</code>
執行的順序是先執行configure級任務,再執行vm級任務,即便configure級任務在vm定義的下面才定義。例如:
輸出結果:
嘗試了helloword,我們來了解一下provision任務是怎麼運作的。
啟動時自動執行,預設地,任務隻執行一次,第二次啟動就不會自動運作了。如果需要每次都自動運作,需要為provision指定<code>run:"always"</code>屬性
啟動時運作,在啟動指令加 <code>--provision</code> 參數,适用于 <code>vagrant up</code> 和 <code>vagrant reload</code>
vm啟動狀态時,執行 <code>vagrant provision</code> 指令。
在編寫provision任務時,可能同時存在幾種類型的任務,但執行時可能隻執行一種,如,我隻執行shell類型的任務。可以如下操作:
類型名
範例
string
“arg1”
hash
{key1:value1,key2:value2}
array
[“arg1”,”arg2”]
boolean
true,false
必選:inline 或者 path
可選:
參數名
類型
說明
args
string or array
傳遞給shell或path的參數
env
傳遞給腳本的環境變量
binary
是否替換windows的行結束符,這個參數名有點奇怪
privileged
是否提權運作,如sudo執行,預設為true
upload_path
上傳到vm中的路徑,預設是/tmp/vagrant-shell
keep_color
設定是否腳本自身控制顔色,預設為false,表示使用綠色和紅色來顯示輸出到stdout和stderr的消息
name
給目前執行的腳本命名,與provisioner名稱無關
powershell_args
windows相關,略
powershell_elevated_interactive
在有些情況下,vagrant會幫你處理引号,但建議,都比對好雙引号,可讀性也好一些。
helloword隻是一個開始,對于inline模式,指令隻能在寫在一行中。一個以上的指令,可以寫在同一行,用分号分隔,這屬于shell程式設計的範疇,在這裡不多解釋。
單行腳本使用的基本格式:
shell指令的參數還可以寫入<code>do ... end</code>代碼塊中,如下:
其他,如後面提到的path參數也是一樣的。
一個shell代碼段,在1.7.0+版本,這個provisioner是可以命名的,如:
Tips: provisioner命名塊如果重名,會有覆寫問題。
一個shell節點内,如果連續寫一條以上s.inline,則隻有最後一條有效,前面的會被後面的覆寫掉。
如果要執行腳本較多,可以在Vagrantfile中指定内聯腳本,在Vagrant.configure節點外面,寫入命名内聯腳本:
然後,inline調用如下:
也可以把代碼寫入代碼檔案,并儲存在一個shell裡,進行調用:
script.sh的内容:
效果是一樣的。
Tips:path可以使用http/https來通路遠端腳本,這個在部署時通路一個腳本倉庫來做一些通用的操作,比較友善。如:
Tips: 腳本檔案在host機器上,而腳本實際上是在vm裡運作的,做個測試驗證一下,在Vagrant.configure節點外面,寫入命名内聯腳本:
檢查結果, /etc/vagrant_provisioned_at 這個檔案不在host主機裡,而是在vm虛機裡。
如果要執行的腳本需要參數,那麼使用args屬性進行傳遞:
Tips: 這兩args有兩層引号,如果去掉一層,字元串中的逗号會讓shell以為是兩個參數,那麼後面的world會被丢掉。
你也可以使用方括号作為外層分隔符,而内層分隔符使用單引号或雙引号都可以,隻要前後比對即可,如:
Tips: 多個參數,你可以把args了解為一個json 數組,隻要在inline裡用 <code>$x</code> 進行引用即可。
為指令行指定環境變量,env的格式為hash,是一個hash對象的清單,多個環境變量,多次配置env。
如:
執行結果:
多個環境變量的例子:
Tips: 環境變量可以引用已經存在的環境變量,如 <code>PATH:"/opt/java/bin:$PATH"</code>,結果是在原有的PATH環境變量前面增加了一個路徑。
Tips: env新增的環境變量,是順序執行指派操作的,執行個體中JAVA_HOME,系統中原來是沒有的,如果JAVA_HOME和PATH這兩個參數順序換一下,把JAVA_HOME放在後面,PATH在拼接JAVA_HOME的時候取到的是系統原來的值,這裡是null。
結果是:
<code>==> default: java_home is /opt/java ;PATH = /bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games</code>
這裡出錯了,本來應該是<code>/opt/java/bin</code>,結果變成了<code>/bin</code>。
同樣,如果在系統的/etc/profile中加入:<code>export JAVA_HOME=/usr/local/jdk</code>
那麼上面例子的執行結果将是:
Tips: provision裡設定的環境變量,隻對provision自身操作有效,<code>vagrant ssh</code> 登入vm,裡邊的變量值是不會變的。
file 操作有兩個參數:
source : 源檔案或檔案夾
destination : 目标檔案或檔案
将host主機的 “./Vagrantfile” 上傳到 vm虛拟機的目标檔案 “./Vagrantfile” 。
Tips: 檔案是通過scp上傳到vm的,使用的是預設使用者,可使用<code>vagrant ssh-config</code> 檢視預設使用者的名稱,一般為vagrant。是以,目的路徑需要讓預設使用者擁有寫權限。
vagrant可以內建其他伺服器運維工具,來增強伺服器管理能力。在使用這些技術之前,需要系統地學習這些技術。而每一套系統都有很多内容學習。本文隻簡單介紹,不做詳細展開。
ansible,cfengine,Chef,puppet
每一套系統都可以寫本書了,是以這裡不詳細說明。
簡單來說 Ansible 是一個極簡化的應用和系統部署工具,類似 Puppet、Chef、SaltStack。由于預設使用 ssh 管理伺服器(叢集),配置檔案采用 yaml 而不是某一種特定語言制定。
cfengine是一個Linux的自動化配置系統。
Chef 是一套Linux的配置管理系統。
Docker 是一個開源的應用容器引擎,讓開發者可以打包他們的應用以及依賴包到一個可移植的容器中,然後釋出到任何流行的 Linux 機器上。docker不會虛拟guest os系統,幾乎沒有性能開銷,最重要的是,他們不依賴于任何語言、架構包括系統。
Docker自身提供了很多優秀的工具和用戶端,目前vagant支援的操作并不友善,建議直接使用docker的用戶端工具學習和使用docker。
Salt 是一個強大的遠端執行管理器,用于快速和高效的伺服器管理。