14

人们如何使用 vagrant(最好来自同一个 vagrantfile)为开发/生产环境处理简单的自动化(使用 puppet)?

我正在尝试解决的用例

  • 如果没有创建,我很想用 vagrant 启动生产机器。
  • 如果在我的开发环境的 puppet 文件中调整了 nginx 或 apache confs,我很乐意使用 vagrant 在生产环境中重新加载它们。

问题

当您向 AWS 或 Digital Ocean 等提供商致电 vagrant 时,它会成为活跃的提供商,您无法切换。你得到这个错误:

发现一台活动机器具有不同的提供程序。Vagrant 目前允许每台机器一次只使用一个提供者。未来的版本将消除此限制。在此之前,请销毁现有机器以使用新的提供商。

它似乎是要摧毁的答案,但我只需要切换。我不想破坏。

我很想能够说

vagrant up prod

或者

vagrant reload prod

然后一个简单的 vagrant up 将回退到默认机器。

这种语法类似于多台机器的工作方式,但是当我只调用 vagrant up(这是默认行为)时,我不想启动开发和生产环境。

我应该将打包程序视为工作流程的一部分吗?我在 puppetconf 2013 上观看了 Mitchell 关于 Multi-Provider 的演讲http://puppetlabs.com/presentations/multi-provider-vagrant-aws-vmware-and-more

我仍然没有看到我的问题的解决方案。


2013 年 9 月 27 日更新

如果其他人反对这个想法,这篇文章解决了我的很多问题。 http://pretengineer.com/post/packer-vagrant-infra

4

4 回答 4

2

至于解决方法,您应该定义config.vm.define(如此处所建议),以支持多个提供程序。

请查找@kzap发布的以下配置作为示例:

Vagrant.configure("2") do |config|

  # Store the current version of Vagrant for use in conditionals when dealing
  # with possible backward compatible issues.
  vagrant_version = Vagrant::VERSION.sub(/^v/, '')

  # Configuration options for the VirtualBox provider.
  def configure_vbox_provider(config, name, ip, memory = 2048, cpus = 1)
    config.vm.provider :virtualbox do |v, override| 
      # override box url
      override.vm.box = "ubuntu/trusty64"
      # configure host-only network
      override.vm.hostname = "#{name}.dev"
      override.vm.network :private_network, id: "vvv_primary", ip: ip

      v.customize ["modifyvm", :id, 
        "--memory", memory,
        "--cpus", cpus,
        "--name", name,
        "--natdnshostresolver1", "on",
        "--natdnsproxy1", "on"
      ]
    end
  end

  default_provider = "virtualbox"
  supported_providers = %w(virtualbox rackspace aws managed)
  active_provider = ENV['VAGRANT_ACTIVE_PROVIDER'] # it'd be better to get this from the CLI --provider option
  supported_providers.each do |provider|
  next unless (active_provider.nil? && provider == default_provider) || active_provider == provider

    #
    # VM per provider
    #
    config.vm.define :"sample-#{provider}" do | sample_web_config |

      case provider
      when "virtualbox"
        configure_vbox_provider(sample_web_config, "examine-web", "192.168.50.1")

      when "aws"
        configure_aws_provider(sample_web_config)

      when "managed"
        configure_managed_provider(sample_web_config, "1.2.3.4")

      when "rackspace"
        configure_rackspace_provider(sample_web_config)  

      end
  end

end

或@maxlinc 在 gist 上发布的以下示例:

# -*- mode: ruby -*-
# vi: set ft=ruby :

# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.box = "dummy"

  config.vm.provider :rackspace do |rs|
    rs.username = ENV['RAX_USERNAME']
    rs.api_key  = ENV['RAX_API_KEY']
    rs.rackspace_region   = :ord
  end

  supported_providers = %w(virtualbox rackspace)
  active_provider = ENV['VAGRANT_ACTIVE_PROVIDER'] # it'd be better to get this from the CLI --provider option
  supported_providers.each do |provider|
    next unless active_provider.nil? || active_provider == provider

    config.vm.define "exact_name_#{provider}" do |box|
      box.vm.provider :rackspace do |rs|
        rs.flavor = '1 GB Performance'
        rs.image  = 'Ubuntu 14.04 LTS (Trusty Tahr) (PVHVM)'
      end
    end

    config.vm.define "regex_#{provider}" do |box|
      box.vm.provider :rackspace do |rs|
        rs.flavor = /1\s+GB\s+Performance/
        rs.image  = /Ubuntu.*Trusty Tahr.*(PVHVM)/
      end
    end

    config.vm.define "id_#{provider}" do |box|
      box.vm.provider :rackspace do |rs|
        rs.flavor = 'performance1-1'
        rs.image  = 'bb02b1a3-bc77-4d17-ab5b-421d89850fca'
      end
    end

    config.vm.define "unlisted_#{provider}" do |box|
      box.vm.provider :rackspace do |rs|
        rs.flavor = 'performance1-1'
        rs.image = '547a46bd-d913-4bf7-ac35-2f24f25f1b7a'
      end
    end
  end
end
于 2016-06-10T12:49:42.927 回答
1

不是一个理想的解决方案,但是使用 git 分支呢?我的想法是,它在概念上可能类似于使用 heroku,你可能有一个 master、staging 和 production 版本(因为它们通常是不同的遥控器)。

在这种情况下,您从 prod 分支开始,对 Vagrantfile 进行小编辑,以稍微不同地命名 VM。然后,您应该能够将 dev 中的所有更改与 prod 分支合并。所以你的工作流程看起来像:

$ git checkout prod
$ vagrant up
$ git checkout master
...  make changes to puppet ...
$ git checkout prod
$ git merge master
$ vagrant reload
$ git checkout master

你可以编写脚本和别名这些,所以你最终得到

$ start_production
$ reload_production
于 2013-09-15T11:30:29.003 回答
0

这是根据命令行指定的动态更改“默认”机器名称的简单方法--provider,因此它们不会在不同的提供者之间发生冲突:

require 'getoptlong'
opts = GetoptLong.new(
  [ '--provider', GetoptLong::OPTIONAL_ARGUMENT ],
  [ '--vm-name',  GetoptLong::OPTIONAL_ARGUMENT ]
)

provider=ENV['PROVIDER'] || 'virtualbox'
vm_name=ENV['VM_NAME'] || 'default'
opts.each do |opt, arg|
  case opt
    when '--provider'
      provider=arg
    when '--vm-name'
      vm_name=arg
  end
end

Vagrant.configure(2) do |config|

  # HERE you are dynamically changing the machine name to prevent conflict.
  config.vm.define "mt-#{provider}-#{vm_name}"

  # Below sections are just examples, not relevant.
  config.vm.provider "virtualbox" do |vm|
    vm.name = "test.local"
    vm.network "private_network", ip: "192.168.22.22"
    vm.customize ['modifyvm', :id, '--natdnshostresolver1', 'on']
    config.vm.box = "ubuntu/wily64"
  end

  config.vm.provider :aws do |aws, override|
    aws.aws_profile = "testing"
    aws.instance_type = "m3.medium"
    aws.ami = "ami-7747d01e"
    config.vm.box = "testing"
  end
end

示例用法:

VM_NAME=dev PROVIDER=virtualbox vagrant up --provider=virtualbox
VM_NAME=uat PROVIDER=aws vagrant up --provider=aws
VM_NAME=test PROVIDER=aws vagrant up --provider=aws
VM_NAME=prod PROVIDER=aws vagrant up --provider=aws
VM_NAME=uat PROVIDER=aws vagrant destroy -f
VM_NAME=test PROVIDER=aws vagrant status

另请参阅:单个 vagrant 文件中的多个供应商?

于 2016-06-10T16:05:22.697 回答
0

我想出处理这种情况的是管理 2 distincts.vagrant文件夹。

注意:大多数其他答案都涉及设置多提供者,假设您将在不同的提供者上运行 dev 和 prod,在大多数情况下这可能是正确的,但您肯定会遇到 dev 和 prod 的提供者相同的情况。假设您正在使用 aws 并且您想使用 dev 和 prod 作为 ec2 实例,它将是同一个提供者。

假设您要管理devprod实例,可能使用不同的提供程序(但也很可能在同一个提供程序上),因此您将执行以下操作:

  • dev用 normal设置实例vagrant up --provider <dev_provider>。这将创建一个您可以管理的开发虚拟机

  • 备份.vagrant在项目目录中创建的文件夹并将其重命名为.vagrant.dev

  • 使用您选择的提供商设置prod实例vagrant up --provider <prod_provider>。现在这会创建您的产品虚拟机

  • 备份.vagrant在项目目录中创建的新文件夹并将其重命名为.vagrant.prod

现在,根据您是要在 dev 还是 prod 上工作,您将.vagrant.dev.vagrant.prod目录重命名为,.vagrant并且 vagrant 将运行正确的 VM。

我没有想出一个脚本,因为我大部分时间都与开发人员一起工作,很少有时候我需要切换到其他提供商。但我认为从 CLI 读取参数并使重命名更加动态不会太难。

于 2016-06-14T06:57:11.080 回答