[轉] vagrant學習筆記 - provision


[From]  https://blog.csdn.net/54powerman/article/details/50684844

 

 

從字面上來看,provision是准備,實現的功能是在原生鏡像的基礎上,進行一些附加的操作,以改變虛擬機的環境,比如安裝應用,發布程序等。

1 helloword

在vagrant的 Vagrant.configure(2) do |config| 節點內,加入如下代碼:

  config.vm.provision "shell", inline: "echo hello provisio."
  • 1

還有一種格式:

  config.vm.provision "shell" do |s|
    s.inline = "echo hello provision."
  end
  • 1
  • 2
  • 3

測試一下:

如果vm已經啟動,直接運行

vagrant provision
  • 1

就可以看到控制台顯示的信息了。或者:

vagrant reload --provision
  • 1

重啟vm,並自動執行provision操作。

Tips: 運行后可能會提示:default: stdin: is not a tty 錯誤,不影響執行效果,想要去除,在配置文件增加一行即可。

config.ssh.shell = "bash -c 'BASH_ENV=/etc/profile exec bash'"
  • 1

什么是provision任務

provision任務是預先設置的一些操作指令,格式:

config.vm.provision 命令字 json格式參數
  • 1
config.vm.provion 命令字 do |s|
    s.參數名 = 參數值
end
  • 1
  • 2
  • 3

每一個 config.vm.provision 命令字 代碼段,我們稱之為一個provisioner。

根據任務操作的對象,provisioner可以分為:

  • Shell
  • File
  • Ansible
  • CFEngine
  • Chef
  • Docker
  • Puppet
  • Salt

根據vagrantfile的層次,分為:

  • configure級:它定義在 Vagrant.configure("2") 的下一層次,形如: config.vm.provision ...
  • vm級:它定義在 config.vm.define "web" do |web| 的下一層次,web.vm.provision ...

執行的順序是先執行configure級任務,再執行vm級任務,即便configure級任務在vm定義的下面才定義。例如:

Vagrant.configure("2") do |config|
  config.vm.provision "shell", inline: "echo foo"

  config.vm.define "web" do |web|
    web.vm.provision "shell", inline: "echo bar"
  end

  config.vm.provision "shell", inline: "echo baz"
end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

輸出結果:

==> default: "foo"
==> default: "baz"
==> default: "bar"
  • 1
  • 2
  • 3

2 如何執行provision任務

嘗試了helloword,我們來了解一下provision任務是怎么運行的。

  • 啟動時自動執行,缺省地,任務只執行一次,第二次啟動就不會自動運行了。如果需要每次都自動運行,需要為provision指定run:"always"屬性
  • 啟動時運行,在啟動命令加 --provision 參數,適用於 vagrant up 和 vagrant reload
  • vm啟動狀態時,執行 vagrant provision 命令。

在編寫provision任務時,可能同時存在幾種類型的任務,但執行時可能只執行一種,如,我只執行shell類型的任務。可以如下操作:

vagrant provision --provision-with shell
  • 1

3 shell

3.1 基本使用

3.1.1 數據類型

類型名 范例
string “arg1”
hash {key1:value1,key2:value2}
array [“arg1”,”arg2”]
boolean true,false

3.1.2 參數:

必選:inline 或者 path

可選:

參數名 類型 說明
args string or array 傳遞給shell或path的參數
env hash 傳遞給腳本的環境變量
binary boolean 是否替換windows的行結束符,這個參數名有點奇怪
privileged boolean 是否提權運行,如sudo執行,缺省為true
upload_path boolean 上傳到vm中的路徑,缺省是/tmp/vagrant-shell
keep_color boolean 設置是否腳本自身控制顏色,缺省為false,表示使用綠色和紅色來顯示輸出到stdout和stderr的消息
name string 給當前執行的腳本命名,與provisioner名稱無關
powershell_args string windows相關,略
powershell_elevated_interactive boolean windows相關,略

在有些情況下,vagrant會幫你處理引號,但建議,都匹配好雙引號,可讀性也好一些。

3.1.3 使用規則

3.1.3.1 單行腳本

helloword只是一個開始,對於inline模式,命令只能在寫在一行中。一個以上的命令,可以寫在同一行,用分號分隔,這屬於shell編程的范疇,在這里不多解釋。

單行腳本使用的基本格式:

config.vm.provision "shell", inline: "echo foo"
  • 1

shell命令的參數還可以寫入do ... end代碼塊中,如下:

config.vm.provision "shell" do |s|
  s.inline = "echo hello provision."
end
  • 1
  • 2
  • 3

其他,如后面提到的path參數也是一樣的。

一個shell代碼段,在1.7.0+版本,這個provisioner是可以命名的,如:

config.vm.provision "myshell,type:"shell" do |s| s.inline = "echo hello provision." end
  • 1
  • 2
  • 3

Tips: provisioner命名塊如果重名,會有覆蓋問題。

一個shell節點內,如果連續寫一條以上s.inline,則只有最后一條有效,前面的會被后面的覆蓋掉。

3.1.3.2 內聯腳本

如果要執行腳本較多,可以在Vagrantfile中指定內聯腳本,在Vagrant.configure節點外面,寫入命名內聯腳本:

$script = <<SCRIPT
echo I am provisioning...
echo hello provision.
SCRIPT
  • 1
  • 2
  • 3
  • 4

然后,inline調用如下:

  config.vm.provision "shell", inline: $script
  • 1
3.1.3.3 外部腳本

也可以把代碼寫入代碼文件,並保存在一個shell里,進行調用:

  config.vm.provision "shell", path: "script.sh"
  • 1

script.sh的內容:

echo hello provision.
  • 1

效果是一樣的。

Tips:path可以使用http/https來訪問遠程腳本,這個在部署時訪問一個腳本倉庫來做一些通用的操作,比較方便。如:

  config.vm.provision "shell", path: "https://example.com/provisioner.sh"
  • 1

Tips: 腳本文件在host機器上,而腳本實際上是在vm里運行的,做個測試驗證一下,在Vagrant.configure節點外面,寫入命名內聯腳本:

$script = <<SCRIPT
echo I am provisioning...
date > /etc/vagrant_provisioned_at
SCRIPT
  • 1
  • 2
  • 3
  • 4

檢查結果, /etc/vagrant_provisioned_at 這個文件不在host主機里,而是在vm虛機里。

3.2 腳本參數

如果要執行的腳本需要參數,那么使用args屬性進行傳遞:

  config.vm.provision "shell" do |s|
    s.inline = "echo $1"
    s.args   = "'hello, world!'"
  end
  • 1
  • 2
  • 3
  • 4

Tips: 這兩args有兩層引號,如果去掉一層,字符串中的逗號會讓shell以為是兩個參數,那么后面的world會被丟掉。 
你也可以使用方括號作為外層分隔符,而內層分隔符使用單引號或雙引號都可以,只要前后匹配即可,如:

s.args   = ["hello, world!"]
  • 1

Tips: 多個參數,你可以把args理解為一個json 數組,只要在inline里用 $x 進行引用即可。

2.3 環境變量

為命令行指定環境變量,env的格式為hash,是一個hash對象的列表,多個環境變量,多次配置env。 
如:

  config.vm.provision "shell" do |s|
    s.inline = "echo $1 $JAVA_HOME"
    s.env = {JAVA_HOME:"/opt/java"}
    s.args   = ["java_home is "]
  end
  • 1
  • 2
  • 3
  • 4
  • 5

執行結果:

==> default: java_home is /opt/java
  • 1

多個環境變量的例子:

  config.vm.provision "shell" do |s|
    s.inline = "echo $1 $JAVA_HOME $2 $PATH"
    s.env = {JAVA_HOME:"/opt/java",PATH:"$JAVA_HOME/bin:$PATH"}
    s.args   = ["java_home is ",";PATH ="]
  end
  • 1
  • 2
  • 3
  • 4
  • 5

執行結果:

==> default: java_home is /opt/java ;PATH = /opt/java/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
  • 1

Tips: 環境變量可以引用已經存在的環境變量,如 PATH:"/opt/java/bin:$PATH",結果是在原有的PATH環境變量前面增加了一個路徑。

Tips: env新增的環境變量,是順序執行賦值操作的,實例中JAVA_HOME,系統中原來是沒有的,如果JAVA_HOME和PATH這兩個參數順序換一下,把JAVA_HOME放在后面,PATH在拼接JAVA_HOME的時候取到的是系統原來的值,這里是null。

  config.vm.provision "shell" do |s|
    s.inline = "echo $1 $JAVA_HOME $2 $PATH"
    s.env = {PATH:"$JAVA_HOME/bin:$PATH",JAVA_HOME:"/opt/java"}
    s.args   = ["java_home is ",";PATH ="]
  end
  • 1
  • 2
  • 3
  • 4
  • 5

結果是: 
==> 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

這里出錯了,本來應該是/opt/java/bin,結果變成了/bin

同樣,如果在系統的/etc/profile中加入:export JAVA_HOME=/usr/local/jdk

那么上面例子的執行結果將是:

==> default: java_home is /usr/local/jdk ;PATH = /usr/local/jdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
  • 1

Tips: provision里設置的環境變量,只對provision自身操作有效,vagrant ssh 登錄vm,里邊的變量值是不會變的。

4 文件操作

file 操作有兩個參數:

  • source : 源文件或文件夾
  • destination : 目標文件或文件
  config.vm.provision "file", source: "./Vagrantfile", destination: "Vagrantfile"
  • 1

將host主機的 “./Vagrantfile” 上傳到 vm虛擬機的目標文件 “./Vagrantfile” 。

Tips: 文件是通過scp上傳到vm的,使用的是缺省用戶,可使用vagrant ssh-config 查看缺省用戶的名稱,一般為vagrant。所以,目的路徑需要讓默認用戶擁有寫權限。

5 擴展操作

vagrant可以集成其他服務器運維工具,來增強服務器管理能力。在使用這些技術之前,需要系統地學習這些技術。而每一套系統都有很多內容學習。本文只簡單介紹,不做詳細展開。

5.1 集群管理,自動化配置等系統

ansible,cfengine,Chef,puppet 
每一套系統都可以寫本書了,所以這里不詳細說明。

簡單來說 Ansible 是一個極簡化的應用和系統部署工具,類似 Puppet、Chef、SaltStack。由於默認使用 ssh 管理服務器(集群),配置文件采用 yaml 而不是某一種特定語言制定。 
cfengine是一個Linux的自動化配置系統。 
Chef 是一套Linux的配置管理系統。

5.2 Docker 面向容器的虛擬解決方案

Docker 是一個開源的應用容器引擎,讓開發者可以打包他們的應用以及依賴包到一個可移植的容器中,然后發布到任何流行的 Linux 機器上。docker不會虛擬guest os系統,幾乎沒有性能開銷,最重要的是,他們不依賴於任何語言、框架包括系統。

Docker自身提供了很多優秀的工具和客戶端,目前vagant支持的操作並不方便,建議直接使用docker的客戶端工具學習和使用docker。

5.3 Salt

Salt 是一個強大的遠程執行管理器,用於快速和高效的服務器管理。

更多,請參考:https://www.vagrantup.com/docs/provisioning/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM