在Vagrant完成所有配置后,是否可以在虚拟机上运行脚本?

时间:2014-08-01 20:56:36

标签: ruby vagrant vagrantfile centos6.5

我正在使用Vagrant v1.5.1来创建虚拟机(VM)群集。配置完所有虚拟机后,是否可以在其中一台机器上运行单个脚本?我想运行的脚本将从一个VM设置无密码SSH到所有其他VM。

例如,我在Vagrant(CentOS 6.5)中配置的节点如下所示。

  • 节点1
  • 节点2
  • 节点3
  • 节点4

我的Vagrantfile如下所示。

(1..4).each do |i|
 config.vm.define "node-#{i}" do |node|
  node.vm.box = "centos65"
  ...omitted..
 end
end

完成所有这些后,我需要在node1上运行一个脚本,以便为node2,node3和node4启用无密码SSH。

我知道您可以在配置每个虚拟机时运行脚本,但在这种情况下,我希望在配置所有虚拟机后运行脚本,因为我需要启动并运行所有虚拟机来运行最后一个脚本。

这是否可以在Vagrant中使用?

我意识到我也可以向后迭代。

r = 4..1
(r.first).downto(r.last).each do |i|
 config.vm.define "node-#{i}" do |node|
  node.vm.box = "centos65"
  ...omitted..
  if i == 1
   node.vm.provision "shell" do |s|
    s.path = "/path/to/script.sh"
   end
  end
 end
end

这将很有用,但实际上,我还需要设置从node2到node1,node3和node4的无密码SSH。在上面的方法中,这只能用于node1,但不适用于node2(因为node1不会被配置)。

如果有一个Vagrant插件允许在我的集群中的所有节点之间使用SSH密码,那就更好了。

5 个答案:

答案 0 :(得分:4)

问题是一年之久,无论如何我发现它是因为我遇到了同样的问题,所以这里是我用来解决问题的工作,有人可能觉得它很有用。

我们需要“vagrant triggers”来实现这一目标。流浪者触发器的事情是它们为你正在创建的每台机器开火,但我们想要确定所有机器都是UP的时刻。我们可以通过检查每个UP事件来做到这一点,如果该事件对应于正在创建的最后一台机器:

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

  (1..$machine_count).each do |i| 

  config.vm.define vm_name = "w%d" % i do |worker|

   worker.vm.hostname = vm_name
   workerIP = IP
   worker.vm.network :private_network, ip: workerIP

   worker.trigger.after :up do
     if(i == $machine_count) then
       info "last machine is up"
       run_remote  "bash /vagrant/YOUR_SCRIPT.sh"
     end   
   end

  end
 end
end

这适用于不支持在Vagrant(VBox,VMWare)上并行执行的提供程序。

答案 1 :(得分:1)

Vagrant中没有挂钩“在配置完所有虚拟机后运行”,因此您需要自己实现它。我能想到几个选项:

1:在所有VM运行后运行SSH安装脚本。

例如,如果脚本名为ssh_setup.sh并存在于共享文件夹中:

$ for i in {1..4}; do vagrant ssh node$i -c 'sudo /vagrant/ssh_setup.sh'; done

2:对所有主机使用相同的SSH密钥,并在配置期间进行设置

如果所有节点共享相同的无密码短语SSH密钥,您可以将所需文件复制到~.ssh,如authorized_keysid_rsa等。

答案 2 :(得分:1)

这对我非常有效:我使用了每个VM设置脚本,在上一个脚本中,我在第一个VM上通过ssh调用了后置脚本。

Vagrantfile中:

require 'fileutils'

Vagrant.require_version ">= 1.6.0"

$max_nodes = 2
$vm_name = "vm_prefix"

#...<skipped some lines that are not relevant to the case >...
Vagrant.configure("2") do |config|
  config.ssh.forward_agent = true
  config.ssh.insert_key    = false
  #ubuntu 16.04
  config.vm.box = "ubuntu/xenial64"

  (1..$max_nodes).each do |i|
    config.vm.define vm_name = "%s-%02d" % [$vm_name, i] do |config|
      config.vm.hostname = vm_name
      config.vm.network "private_network", ip: "10.10.0.%02d" % [i+20], :name => 'vboxnet2'
      config.vm.network :forwarded_port, guest: 22, host: "1%02d22" % [i+20], id: "ssh"
      config.vm.synced_folder "./shared", "/host-shared"
      config.vm.provider :virtualbox do |vb|
        vb.name = vm_name
        vb.gui = false
        vb.memory = 4096
        vb.cpus = 2
        vb.customize ["modifyvm", :id, "--cpuexecutioncap", "100"]
        vb.linked_clone = true
      end

      # Important part:
      config.vm.provision "shell", path: "common_provision.sh"
      config.vm.provision "shell", path: "per_vm_provision#{i}.sh"

    end
  end
end

在磁盘上: (确保post_provision.sh至少具有所有者执行权限:rwxr..r ..)

vm$ ls /vagrant/
...<skipped some lines that are not relevant to the case >...
config.sh
common_provision.sh
per_vm_provision1.sh
per_vm_provision2.sh
per_vm_provision3.sh
...
per_vm_provisionN.sh
post_provision.sh
Vagrantfile
...<skipped some lines that are not relevant to the case >...

config.sh中:

  num_vm="2" # should equal the $max_nodes in Vagrantfile
  name_vm="vm_prefix" # should equal the $vm_name in Vagrantfile
  username="user1"
  userpass="abc123"
    ...<skipped some lines that are not relevant to the case >...

common_provision.sh中:

  source /vagrant/config.sh
  ...<skipped some lines that are not relevant to the case >...

  sed -r -i 's/\%sudo.*$/%sudo       ALL=(ALL:ALL) NOPASSWD:ALL/' /etc/sudoers
  sed -r -i 's/PasswordAuthentication no/PasswordAuthentication yes/' /etc/ssh/sshd_config
  service ssh reload

  # add user ${username}
  useradd --create-home --home-dir /home/${username}  --shell /bin/bash  ${username}
  usermod -aG admin ${username} 
  usermod -aG sudo ${username}
  /bin/bash -c "echo -e \"${userpass}\n${userpass}\" | passwd ${username}"

  # provision additional ssh keys
  # copy ssh keys from disk
   cp /vagrant/ssh/* /home/vagrant/.ssh
   cat /vagrant/ssh/id_rsa.pub >> /home/vagrant/.ssh/authorized_keys
   mkdir /home/${username}/.ssh
   cp /vagrant/ssh/* /home/${username}/.ssh
   cat /vagrant/ssh/id_rsa.pub >> /home/${username}/.ssh/authorized_keys

# not required, just for convenience
 cat >> /etc/hosts <<EOF
10.10.0.21    ${name_vm}-01
10.10.0.22    ${name_vm}-02
10.10.0.23    ${name_vm}-03
...
10.10.0.2N    ${name_vm}-0N
EOF
  ...<skipped some lines that are not relevant to the case >...

per_vm_provision2。sh中:

#!/bin/bash

  # import variables from config
  source /vagrant/config.sh

  ...<skipped some lines that are not relevant to the case >...

 # check if this is the last provisioned vm 
 if [ "x${num_vm}" = "x2" ] ; then
   ssh vagrant@10.10.0.21 -o StrictHostKeyChecking=no -- '/vagrant/post_provision.sh'
 fi

per_vm_provisionN.sh中:

#!/bin/bash

  # import variables from config
  source /vagrant/config.sh

  ...<skipped some lines that are not relevant to the case >...

 # check if this is the last provisioned vm. N represents the highest number 
 if [ "x${num_vm}" = "xN" ] ; then
   ssh vagrant@10.10.0.21 -o StrictHostKeyChecking=no -- '/vagrant/post_provision.sh'
 fi

我希望,我没有跳过任何重要的事情,但是我认为这个想法很明确。

注意:默认情况下,Vagrant设置了用于interVM访问的ssh密钥。您可以根据需要使用common_provision.sh

添加自己的ssh密钥

答案 3 :(得分:0)

You can install vagrant-triggers plugin

This will allow you to run anything before & after up/resume/destroy commands

Github page for plugin

答案 4 :(得分:0)

添加更新的答案。

vagrant-triggers插件于2018年5月mergedVagrant 2.1.0

我们可以简单地使用 trigger 类中的only_on option选项。

假设我们具有以下配置:

var data = './' var context = requireAll(require.context( data, false, /[^.]{5}$/));

我们现在可以在最后一台机器启动后轻松执行触发器:

servers=[
  {:hostname => "net1",:ip => "192.168.11.11"},
  {:hostname => "net2",:ip => "192.168.22.11"},
  {:hostname => "net3",:ip => "192.168.33.11"}
]

我们可以检查输出,并仅在“ net3”启动后才能触发触发器:

# Take the hostname of the last machine in the array
last_vm = servers[(servers.length) -1][:hostname]

Vagrant.configure(2) do |config|
    servers.each do |machine|
        config.vm.define machine[:hostname] do |node|

            # ----- Common configuration ----- #
            node.vm.box = "debian/jessie64"
            node.vm.hostname = machine[:hostname]
            node.vm.network "private_network", ip: machine[:ip]

            # ----- Adding trigger - only after last VM is UP ------ #
            node.trigger.after :up do |trigger|
                trigger.only_on = last_vm  # <---- Just use it here!
                trigger.info = "Running only after last machine is up!"
            end
        end
    end
end
相关问题