如何在Vagrant中为多机器环境指定供应商默认值?

7
我想知道在使用Vagrant创建多机环境时是否有一种指定provisioners默认值的方法?
我试图做如下操作:
Vagrant.configure("2") do |config|
  config.vm.box = "andyshinn/ubuntu-precise64"

  config.vm.provision :chef_client do |chef|
    chef.chef_server_url = "https://api.opscode.com/organizations/myorg"
    chef.validation_key_path = "~/.chef/myorg-validator.pem"
    chef.delete_node = true
    chef.delete_client = true
    chef.validation_client_name = "myorg-validator"
  end

  config.vm.define :app do |app|
    app.vm.network "private_network", ip: "172.16.64.61"
    app.vm.host_name = "vagrant-app-#{ENV['USER']}"

    app.vm.provision :chef_client do |chef|
      chef.add_recipe "myrecipe1"
      chef.add_recipe "myrecipe2"
      chef.add_recipe "sudo"
    end
  end

  config.vm.define :web do |web|
    web.vm.network "private_network", ip: "172.16.64.62"
    web.vm.host_name = "vagrant-web-#{ENV['USER']}"

    web.vm.provision :chef_client do |chef|
      chef.add_recipe "myrecipe3"
      chef.add_recipe "myrecipe4"
      chef.add_recipe "sudo"
    end
  end
end

但是每个虚拟机块似乎都没有获取到任何主配置块的设置。我遇到了这个错误:

There are errors in the configuration of this machine. Please fix
the following errors and try again:

chef client provisioner:
* Chef server URL must be populated.
* Validation key path must be valid path to your chef server validation key.

可以通过另一种方法实现吗?

我认为.Vagrantfile通常描述一个自包含的虚拟机。当你谈论multi-machine环境时,这似乎有些可疑,因为答案是多个.Vagrantfile。你是否认为你正在尝试做一些Vagrant并不打算做的事情? - nsfyn55
我理解你的想法。但是我认为多机设置是为了应对需要扩展到多个节点的应用程序而设计的。为了正确地进行扩展,应用程序被模块化为在不同节点上运行的不同组件。因此,为了在本地模拟该环境并保持开发和生产的一致性,我希望以相同的方式运行它。Vagrant非常适合这种情况,并且确实有效。但是当您不得不为每个框重复相同的配置时,它变得非常不DRY(湿润?)。 - Andy Shinn
啊,那其实是我在谷歌上失败了。我不知道他们已经添加了那个多机器配置。 - nsfyn55
让我看一下这个,我觉得你的配置有些问题。 - nsfyn55
3个回答

1
你的问题是作用域问题。变量chefconfig.vm.provision块中具有块级作用域。一旦此块退出,您所做的更改就会消失。您应该遵循vagrant网站上文档中的示例。

config.vm.provision“shell”,inline:“echo Hello”

Vagrant.configure("2") do |config|
  config.vm.box = "andyshinn/ubuntu-precise64"


  config.vm.provision "chef_client", chef_server_url: "https://api.opscode.com/organizations/myorg"
  config.vm.provision "chef_client", validation_key_path:  "~/.chef/myorg-validator.pem                
  config.vm.provision "chef_client", delete_node: true
  config.vm.provision "chef_client", delete_client: true
  config.vm.provision "chef_client", validation_client_name: "myorg-validator"


  config.vm.define :app do |app|
    app.vm.network "private_network", ip: "172.16.64.61"
    app.vm.host_name = "vagrant-app-#{ENV['USER']}"

    app.vm.provision :chef_client do |chef|
      chef.add_recipe "myrecipe1"
      chef.add_recipe "myrecipe2"
      chef.add_recipe "sudo"
    end
  end

应该可以解决问题。

感谢你的建议!我会在下周尝试这个方法,如果有效果的话,我会接受它。 - Andy Shinn
我最终尝试了一下,但它并没有起作用。每个机器块都会出现错误,指出无法找到所需的参数,例如Chef服务器URL和验证密钥。它似乎没有继承这些参数。 - Andy Shinn

0

指出配置中的部分会很好。最终我明白了你的意思,自定义方法确实有助于更接近这一目标。虽然不是最优雅的解决方案,但它能够正常工作。 - Andy Shinn
是的,办法不好但是能用。我正在尝试解决这个复杂的问题,涉及很多不同的配置,分散在不同的文件中:
  • Vagrant文件在Box内部
  • Vagrant文件在主目录下
  • 自定义Vagrant文件
我希望能将与chef相关的内容(URL、Keys等)放在一个地方。我成功地在VAGRANT_HOME/Vagrantfile中使用了实例变量,并且能够在自定义的Vagrantfile中引用它们。
- Lukino

0

我认为内部块“覆盖”了外部块。但是,你可以像我在我的答案中所做的那样(回答自己的问题),模拟从内到外的配置顺序而不是Vagrant提供的从外到内的顺序。在你的情况下,你没有像我一样的shell和puppet provisioner,但你可以应用类似于模板方法模式来扩展chef provisioner的更多配方。也许是这样:

module Vagrant
  module Config
    module V2
      class Root
        def provision(extra_recipes)
          config.vm.provision :chef_client do |chef|
            chef.chef_server_url = "https://api.opscode.com/organizations/myorg"
            chef.validation_key_path = "~/.chef/myorg-validator.pem"
            chef.delete_node = true
            chef.delete_client = true
            chef.validation_client_name = "myorg-validator"
            extra_recipes.each { |recipe| chef.add_recipe(recipe) }
          end
        end
      end
    end
  end
end

Vagrant.configure("2") do |config|
  config.vm.box = "andyshinn/ubuntu-precise64"

  config.vm.define :app do |app|
    app.vm.network "private_network", ip: "172.16.64.61"
    app.vm.host_name = "vagrant-app-#{ENV['USER']}"

    app.provision("myrecipe1", "myrecipe2", "sudo")
  end

  config.vm.define :web do |web|
    web.vm.network "private_network", ip: "172.16.64.62"
    web.vm.host_name = "vagrant-web-#{ENV['USER']}"

    app.provision("myrecipe3", "myrecipe4", "sudo")
  end
end

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接