天天看點

vagrant學習筆記 - provision

從字面上來看,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>==&gt; 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 是一個強大的遠端執行管理器,用于快速和高效的伺服器管理。