天天看點

Vagrant 手冊之 Provisioning - 基本用法配置運作 Provisioner運作一次還是一直運作多個 Provisioner覆寫 Provisioner 的設定

原文位址

雖然 Vagrant 提供了用于配置虛拟機的多個選項,但是有标準用法,好多知識點對這個 provisioner 是通用的。

配置

首先,Vagrantfile 中配置的每個 provisioner 都使用

config.vm.provision

方法調用。例如,使用 shell 配置程式:

Vagrant.configure("2") do |config|
  # ... other configuration

  config.vm.provision "shell", inline: "echo hello"
end
           

每個 provisioner 都有類型,例如“shell”,是第一個參數。後面緊跟着用于配置特定 provisioner 的鍵值對。除了基本的鍵值對,還可以使用 Ruby 塊這種類似變量定義的文法。下面示例跟上面的相同:

Vagrant.configure("2") do |config|
  # ... other configuration

  config.vm.provision "shell" do |s|
    s.inline = "echo hello"
  end
end
           

基于塊的文法的好處是,使用多個選項可以大大提高可讀性。此外,一些 provisioner (如 Chef provisioner)具有可在該塊内調用的特殊方法,以簡化無法使用鍵值對進行的配置,此文法還可以将參數傳遞給 shell 腳本。

使用

=

樣式設定的屬性可以在單行中設定,例如上面的

inline ="echo hello"

。如果樣式更像是一個函數調用,比如

add_recipe "foo"

,那麼這不能在一行中指定。

Provisioner 也可以被命名(自 1.7.0 起)。這些名稱可以用于輸出以及覆寫 provisioner 設定(下面會進一步介紹)。下面顯示了一個命名過的 provisioner:

Vagrant.configure("2") do |config|
  # ... other configuration

  config.vm.provision "bootstrap", type: "shell" do |s|
    s.inline = "echo hello"
  end
end
           

命名 provisioner 很簡單。

config.vm.provision

的第一個參數就是名字,後面的

type

參數用于指定 provisioner 類型,例如

type: "shell"

運作 Provisioner

provisioner 在三種情況下運作:第一次

vagrant up

vagrant provision

vagrant reload --provision

如果不想運作 provisioner,可以将

--no-provision

标志傳遞給 up 和 reload。類似,也可以傳遞

--provision

來強制執行 provisioning。

如果有多個 provisioner,要運作指定的 provisioner 時,可以使用

--provision-with

标志。例如,同時又 shell 和 Puppet 配置程式時,如果隻想運作 shell,可以執行

vagrant provision --provision-with shell

--provision-with

的參數可以是 provisioner 的類型(例如 shell)或指令(例如上面示例中的 bootstrap)。

運作一次還是一直運作

預設情況下,除非設定了

--provision

标志,否則 provisioner 配置程式隻在上次

vagrant destroy

後的第一次

vagrant up

期間運作一次。

或者,可以配置 provisioner 以在每次啟動或重新加載時運作。隻有在顯式指定

--no-provision

标志時才會運作它們。為此,請将 run 選項設定為“always”,如下所示:

Vagrant.configure("2") do |config|
  config.vm.provision "shell", inline: "echo hello",
    run: "always"
end
           

如果想在“提示消息”中提示使用者有可選的 provisioner,或者 provisioner 在啟動之前依賴其他配置,也可以将 run 選項設定為“never”。之後可以通過

vagrant provision --provision-with bootstrap

調用。

如果使用塊格式,則必須在塊外指定 run 這個選項,如下所示:

Vagrant.configure("2") do |config|
  config.vm.provision "shell", run: "always" do |s|
    s.inline = "echo hello"
  end
end
           

多個 Provisioner

可以使用多個

config.vm.provision

方法來定義多個 provisioner。這些 provisioner 将按照他們定義的順序運作。常見的使用常見是:使得 shell 腳本可以引導某些系統,以便其他設定程式可以稍後進行。

如果在多個“scope”級别定義 provisioner(例如在配置塊中全局化,然後在多機器定義中,然後可能在 provider 特定的覆寫中),那麼外部 scope 将始終在任何内部 scope 之前運作。例如,在下面的 Vagrantfile 中:

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
           

provisioner 的順序是列印“foo”,“baz”,然後是“bar”。

使用多個 provisioner 時,使用

--provision-with

設定和名稱可以更好地控制運作的内容和時間。

覆寫 Provisioner 的設定

警告:進階主題! Provisioner 覆寫是一個進階主題,如果已經在使用多機器和/或提供程式覆寫,那麼它非常有用。 如果你剛剛開始使用 Vagrant,可以放心地跳過。

在使用 multi-machine 或特定于 provider 的功能時,可能需要在 Vagrantfile 的全局配置範圍中定義通用 provisioner,但在内部覆寫它們的某些方面。Vagrant 允許你這樣做,但有一些細節需要考慮。

要覆寫設定,必須為 provisioner 配置設定一個名稱。

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

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

在上面,隻會顯示“bar”,因為内聯設定會重載外部provisioner。這個重載隻在該範圍内有效:“web”虛拟機。如果定義了另一個虛拟機,它仍會回顯“foo”,除非它本身也重載了 provisioner。

順序要小心。當覆寫子範圍中的 provisioner 時,provisioner 将在該點運作。在下面的例子中,輸出将是“foo”,然後是“bar”:

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

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

如果想保留原來的順序,可以指定

preserve_order:true

标志:

Vagrant.configure("2") do |config|
  config.vm.provision "do-this",
    type: "shell",
    preserve_order: true,
    inline: "echo FIRST!"
  config.vm.provision "then-this",
    type: "shell",
    preserve_order: true,
    inline: "echo SECOND!"
end