How to run an ansible playbook on a specific vagrant host

最后都变了- 提交于 2019-12-24 11:09:59

问题


I have a Vagrantfile which creates 3 servers. I have two ansible playbooks. playbook1 should be executed on every server first. The second playbook2 should only be executed on server1 and not on server2 and server3.

How can I manage this with my 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

The above executes playbook1 on all servers. How can I add config for playbook2.yml to be executed only on server1 and AFTER playbook1?


回答1:


Given your example Vagrantfile and your theoretical playbook2.yml executing only on server2 after playbook1.yml on server1, we would arrive at the following solution:

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

It is also worth noting that if you want to be precise about ordering, you can vagrant up server1 and then vagrant up server2 instead of an all-in-one vagrant up.

Basically, within Vagrant.configure there is a scope affecting all VMs within config.vm. You can restrict its scope to specific VMs by instantiating with config.vm.define like you do above. Object VMs instantiated with config.vm.define have the same members/attributes as the base config.

Note you can also do something like this if you want:

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

for a per-server specific playbook. This depends on what exactly is within your // though specific to each VM, and if you wanted a third playbook for the third VM.




回答2:


The below example will execute playbook1.yml on every server first then execute playbook2.yml only on server1 (this example assumes that the playbook1.yml can be parallelized):

# -*- 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

This example builds on top of the example provided in the Tips and Tricks, the ansible-playbook's are parallelized and the scope for both ansible-playbooks's is limited by the ansible.limit configuration option (e.g. a vagrant up will bring up the virtual machines first then execute the playbooks one after the other against all hosts or subset of hosts).

Note: the ubuntu/bionic64 (virtualbox, 20190131.0.0) box has /usr/bin/python3 installed, for the sake of having a copy & paste example and for using a dynamic inventory I deliberately kept the server.vm.provision :shell, inline: "sudo apt install -y python" in the example so ansible-playbook (2.7.6) doesn't bomb out with "/bin/sh: 1: /usr/bin/python: not found\r\n errors (ref. How do I handle python not having a Python interpreter at /usr/bin/python on a remote machine?). Example playbook1.yml and playbook2.yml (present in the same directory as the Vagrantfile):

---

- hosts: all
  tasks:
  - debug: 
      msg: 'executing on {{ inventory_hostname }}'

Results in:



来源:https://stackoverflow.com/questions/54468546/how-to-run-an-ansible-playbook-on-a-specific-vagrant-host

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!