我有一个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?
答案 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