Using Vagrant to Explore Ansible

Last week I wrote about Vagrant, a fantastic tool to spin up virtual development environments. Today I’m exploring Ansible. Ansible is an open source tool which streamlines certain system administration activities. Unlike Vagrant, which provisions new machines, Ansible takes an already provisioned machine and configures it. This can include installing and configuring software, managing services, and even running simple commands. Ansible doesn’t require any agent software to be installed on the system being managed. Everything is executed over SSH.

Ansible only runs on Linux (though I’ve heard of people running it in cygwin with some difficulty). In order to play with Ansible, I used Vagrant to spin up a control box and a subject box that are connected in a way that I can easily run Ansible commands. Here’s my Vagrantfile

# -*- mode: ruby -*-
# vi: set ft=ruby :
 
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"
 
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|

  # define ansible subject (web in this case) box
  config.vm.define "subject" do |subject|
    subject.vm.box = "ubuntu/trusty64"
    subject.vm.network "public_network"
    subject.vm.network "private_network", ip: "192.168.51.4"
    subject.vm.provider "virtualbox" do |v|
      v.name = "Ansible subject"
      v.cpus = 2
      v.memory = 768
    end
    # copy private key so hosts can ssh using key authentication (the script below sets permissions to 600)
    subject.vm.provision :file do |file|
      file.source      = 'C:\Users\watrous\.vagrant.d\insecure_private_key'
      file.destination = '/home/vagrant/.ssh/id_rsa'
    end
    subject.vm.provision :shell, path: "subject.sh"
    subject.vm.network "forwarded_port", guest: 80, host: 8080
  end
 
  # define ansible control box (provision this last so it can add other hosts to known_hosts for ssh authentication)
  config.vm.define "control" do |control|
    control.vm.box = "ubuntu/trusty64"
    control.vm.network "public_network"
    control.vm.network "private_network", ip: "192.168.50.4"
    control.vm.provider "virtualbox" do |v|
      v.name = "Ansible control"
      v.cpus = 1
      v.memory = 512
    end
    # copy private key so hosts can ssh using key authentication (the script below sets permissions to 600)
    control.vm.provision :file do |file|
      file.source      = 'C:\Users\watrous\.vagrant.d\insecure_private_key'
      file.destination = '/home/vagrant/.ssh/id_rsa'
    end
    control.vm.provision :shell, path: "control.sh"
  end
 
  # consider using agent forwarding instead of manually copying the private key as I did above
  # config.ssh.forward_agent = true
 
end

Notice that I created a public network to get a DHCP external address. I also created a private network with assigned addresses in the open address space. This is so I can indicate to Ansible in the hosts file where to locate all of the inventory.

I had trouble getting SSH agent forwarding to work on Windows through PuTTY, so for now I’m manually placing the private key and updating known_hosts with the ‘ssh-keyscan’ command. You can see part of this in the Vagrantfile above. The remaining work is done in two scripts, one for the control and one of the subject.

control.sh

#!/usr/bin/env bash
 
# set proxy variables
#export http_proxy=http://myproxy.com:8080
#export https_proxy=https://myproxy.com:8080
 
# install pip, then use pip to install ansible
apt-get -y install python-dev python-pip
pip install ansible
 
# fix permissions on private key file
chmod 600 /home/vagrant/.ssh/id_rsa
 
# add subject host to known_hosts (IP is defined in Vagrantfile)
ssh-keyscan -H 192.168.51.4 >> /home/vagrant/.ssh/known_hosts
chown vagrant:vagrant /home/vagrant/.ssh/known_hosts
 
# create ansible hosts (inventory) file
mkdir -p /etc/ansible/
cat /vagrant/hosts >> /etc/ansible/hosts

subject.sh

#!/usr/bin/env bash
 
# fix permissions on private key file
chmod 600 /home/vagrant/.ssh/id_rsa

I also provide copy this hosts file into place on the control system so it knows against which inventory it should operate.

hosts

[targets]
localhost   ansible_connection=local
192.168.51.4    ansible_connection=ssh

After running ‘vagrant up‘, I can verify that the control box is able to access the subject box using the ping module in ansible.

vagrant-ansible

Conclusion

This post doesn’t demonstrate the use of Ansible, aside from the ping command. What it does do is provide an environment where I can build and run Ansible playbooks, which is exactly what I plan to do next.

Twitter Digg Delicious Stumbleupon Technorati Facebook Email

About Daniel Watrous

I'm a Software & Electrical Engineer and online entrepreneur.

11 Responses to “Using Vagrant to Explore Ansible”


  1. Fatal error: Uncaught Error: Call to undefined function ereg() in /home/dwatrous/webapps/software_danielwatrous_com/wp-content/themes/headlines/includes/theme-comments.php:66 Stack trace: #0 /home/dwatrous/webapps/software_danielwatrous_com/wp-content/themes/headlines/includes/theme-comments.php(22): the_commenter_link() #1 /home/dwatrous/webapps/software_danielwatrous_com/wp-includes/class-walker-comment.php(180): custom_comment(Object(WP_Comment), Array, 1) #2 /home/dwatrous/webapps/software_danielwatrous_com/wp-includes/class-wp-walker.php(146): Walker_Comment->start_el('', Object(WP_Comment), 1, Array) #3 /home/dwatrous/webapps/software_danielwatrous_com/wp-includes/class-walker-comment.php(140): Walker->display_element(Object(WP_Comment), Array, '5', 0, Array, '') #4 /home/dwatrous/webapps/software_danielwatrous_com/wp-includes/class-wp-walker.php(371): Walker_Comment->display_element(Object(WP_Comment), Array, '5', 0, Array, '') #5 /home/dwatrous/webapps/software_danielwatrous_com/wp-includes/comment-template.php(20 in /home/dwatrous/webapps/software_danielwatrous_com/wp-content/themes/headlines/includes/theme-comments.php on line 66