Vagrant is a powerful tool to create multiple virtual machines. Puppet is an equally powerful tool to manage multiple nodes. Let's create a second node to be provisioned entirely from the Puppetmaster started in the previous section.
Define a second node in the Vagrantfile. We'll make sure that this second node can access the Puppetmaster as Puppet by adding a fixed IP for the Puppetmaster and creating an
/etc/hosts/
entry that allows our new node to access the Puppetmaster at the default address of Puppet. A complete Vagrantfile with both nodes looks like this:# -*- mode: ruby -*- # vi: set ft=ruby : # Vagrantfile API/syntax version. Don't touch unless you know what you're doing! VAGRANTFILE_API_VERSION = "2" $puppetmaster_ip = "192.168.30.134" Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| config.vm.box = "puppetlabs/ubuntu-14.04-64-puppet" config.vm.define "puppetmaster" do |puppetmaster| puppetmaster.vm.hostname = "puppet" puppetmaster.vm.network "private_network", ip: $puppetmaster_ip puppetmaster.vm.provision "shell" , inline: "apt-get update" puppetmaster.vm.provision "puppet" do |puppet| puppet.manifests_path = "puppet/manifests" puppet.manifest_file = "site.pp" puppet.module_path = "puppet/modules" end end config.vm.define "web01" do |web| web.vm.hostname = "web01" web.vm.provision "shell", inline: "apt-get update" web.vm.provision "shell", inline: "echo '#{$puppetmaster_ip} puppet puppet.localdomain' >> /etc/hosts" end end
This defines our second node as
web01
.Start the node with the
vagrant up web01
command.SSH into the
web01
node with thevagrant ssh web01
command.In the
web01
node, start the Puppet agent with thesudo puppet agent –t
command. This will start the Puppet agent and quickly return an error as our Puppetmaster has not yet been configured to compile a catalog for web nodes.Define a web node by editing the
puppet/manifests/site.pp
file (the Puppetmaster manifest file) in our working directory. We'll make this simple for now: simply install the Apache web server package. In this case, being Ubuntu only for now. The additional node looks like this:node /^web/ { package{"apache2": ensure => installed,} }
Configure the Vagrant Puppet agent provisioner in the Vagrantfile. Add a provisioning block to the
web01
machine definition:web.vm.provision "puppet_server" do |puppet| puppet.puppet_server = "puppet" end
This will start the Puppet agent using the machine name
puppet
to retrieve a catalog. It would also be possible to use the IP address of the Puppetmaster itself, but having the definition of the IP address in the/etc/hosts
file allows the Puppet agent to run independently of Vagrant provisioners if desired.Run the Puppet server provisioner with the
vagrant provision web01
command. This will produce provisioner output that ends in a notification that the Puppet agent is running:==> web01: Running provisioner: puppet_server... ==> web01: Running Puppet agent...
Note
If you encounter issues related to waitforcert errors, be sure to verify that the Puppetmaster is configured to autosign certificates. While this might not be desirable in a real production environment, autosigning certificates can make development simpler. See https://docs.puppetlabs.com/puppet/latest/reference/ssl_autosign.html for more information on SSL and certificate verification options with Puppetmasters.
Log in to the web server (
vagrant ssh web01
) and verify that theapache2
package has been installed:vagrant@web01:~$ which apache2 /usr/sbin/apache2
The results of the Puppet run can also be verified through report creation on the node at
/var/lib/puppet/state/last_run_report.yaml
or any configured reporting on the Puppetmaster.
Now, we have a working node connecting to the Puppetmaster and retrieving catalogs. We can continue developing our manifests by adding more resources to our manifest, or by adding modules to the puppet/modules
directory, and calling the appropriate classes in our manifest.
Using Vagrant as a development environment for either individual modules or entire infrastructures can take any one of a number of methods. This example is simply one configuration that can be used to develop and test a puppet infrastructure.
There is another important use case to use Vagrant in conjunction with Puppet development: the use of Vagrant as part of an acceptance testing framework. Puppet Labs recently released an open source framework called Beaker (https://github.com/puppetlabs/beaker/wiki) to test puppet modules against a variety of operating systems. Beaker uses a number of hosts files to define virtual machines (or virtual environments) in order to test Puppet modules.
A quick way to get started with writing modules with Beaker tests is to install Gareth Rushgrove's puppet-module-skeleton project available at https://github.com/garethr/puppet-module-skeleton. The skeleton will extend the functionality of the puppet module
command, generating stub files for configuration as well as a number of test files using puppet-rspec
and beaker
as test frameworks. Once the framework is installed, generating a module will also generate a few stub hosts files for Beaker. For example, the hosts file generated to test against a CentOS Vagrant box:
HOSTS: centos-64-x64: roles: - master platform: el-6-x86_64 box : centos-64-x64-vbox4210-nocm box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-64-x64-vbox4210-nocm.box hypervisor : vagrant CONFIG: log_level: verbose type: foss
With these files in place (and proper role definition, and so on), the test framework will start Vagrant machines (or multiple Vagrant machines, depending on the number of test cases) by using the rake acceptance
build command.
Beaker is an example of using Vagrant not only as a development tool within a single virtual environment, but also as a tool to test a Puppet module across several virtual environments and operating systems.
Puppet: http://puppetlabs.com (the homepage of Puppet Labs and the Puppet configuration tool)
Puppet Labs Documentation: http://docs.puppetlabs.com
The puppet-module-skeleton project: https://github.com/garethr/puppet-module-skeleton