如何在特定的流浪汉主机上运行Ansible剧本

时间:2019-01-31 20:11:15

标签: ansible vagrant vagrantfile

我有一个Vagrantfile,可以创建3个服务器。我有两本有趣的剧本。 playbook1应该在每台服务器上首次执行。第二本playbook2应该仅在server1上执行,而不应该在server2和server3上执行。

如何使用我的Vagrantfile进行管理?

Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/bionic64" 

  config.vm.define "server1" do |server1|
    //
  end

  config.vm.define "server2" do |server2|
    //
  end

  config.vm.define "server3" do |server3|
    //
  end

  config.vm.provision "ansible" do |ansible|
    ansible.playbook = "playbook1.yml"
  end
end

上面执行playbook1所有服务器上。如何添加配置为将只在Server1和AFTER playbook1执行playbook2.yml?

2 个答案:

答案 0 :(得分:1)

鉴于您的示例Vagrantfile和理论playbook2.yml仅在server2的{​​{1}}之后在playbook1.yml执行,我们将得出以下解决方案:

server1

还值得注意的是,如果您想精确订购,可以先Vagrant.configure("2") do |config| config.vm.box = "ubuntu/bionic64" config.vm.define "server1" do |server1| // # restrict scope of ansible provisioner to server1 by invoking on its class method off the constructor server1.vm.provision :ansible do |ansible| ansible.playbook = 'playbook1.yml' end end config.vm.define "server2" do |server2| // # perform similarly for server2, which executes after server1 provisioning due to the imperative ruby dsl server2.vm.provision :ansible do |ansible| ansible.playbook = 'playbook2.yml' end end config.vm.define "server3" do |server3| // end end ,然后再vagrant up server1,而不是一体的vagrant up server2

基本上,vagrant up内有一个范围会影响Vagrant.configure内的所有VM。您可以像上面一样通过config.vm实例化将其范围限制为特定的VM。用config.vm.define实例化的对象VM具有与基础config.vm.define相同的成员/属性。

请注意,您还可以根据需要执行以下操作:

config

针对每个服务器的特定剧本。这取决于Vagrant.configure('2') do |config| ... (1..3).each do |i| config.vm.define "server#{i}" do |server| // server.vm.provision :ansible do |ansible| ansible.playbook = "playbook#{i}.yml" end end end end 内到底是什么(尽管特定于每个VM),以及您是否需要第三本VM的第三本手册。

答案 1 :(得分:1)

下面的示例将首先在每个服务器上执行playbook1.yml,然后仅在server1上执行playbook2.yml(此示例假定playbook1.yml可以并行化):

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

VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  N = 3
  (1..N).each do |server_id|
    config.vm.define "server#{server_id}" do |server|
      server.vm.box = "ubuntu/bionic64"
      server.vm.hostname = "server#{server_id}"
      server.vm.network "private_network", ip: "172.28.128.25#{server_id}"
      server.vm.provision :shell, inline: "sudo apt install -y python"
      # only execute once the ansible provisioner,
      # when all the machines are up and ready.
      if server_id == N
        server.vm.provision :ansible do |ansible|
          # disable default limit to connect to all the machines
          # execute playbook1 on all hosts
          ansible.limit = "all"
          ansible.playbook = "playbook1.yml"
          ansible.compatibility_mode = "2.0"
        end
        server.vm.provision :ansible do |ansible|
          # limit the connection to server1 and execute playbook2
          ansible.limit = "server1"
          ansible.playbook = "playbook2.yml"
          ansible.compatibility_mode = "2.0"
        end
      end
    end
  end
end

此示例以Tips and Tricks中提供的示例为基础,ansible-playbook被并行化,两个ansible-playbooks的范围都受{{1} }配置选项(例如ansible.limit将首先启动虚拟机,然后针对所有主机或主机子集依次执行剧本)。

注意vagrant up框已安装ubuntu/bionic64 (virtualbox, 20190131.0.0),为了提供复制和粘贴示例并使用动态清单,我特意保留了{{1 }},因此/usr/bin/python3不会出现server.vm.provision :shell, inline: "sudo apt install -y python"错误(参考How do I handle python not having a Python interpreter at /usr/bin/python on a remote machine?)。示例ansible-playbook (2.7.6)"/bin/sh: 1: /usr/bin/python: not found\r\n(与playbook1.yml位于同一目录中):

playbook2.yml

结果: enter image description here