Vagrant Provisioning with Ansible

Messing around with Vagrant again, this time using Ansible to automate configuration post deployment.

Ansible is billed as an automation platform which makes it easier to deploy systems and applications. It does this through a scripting framework which supports a wide range of functionality covering deployment and configuration.

Vagrant Config

To define which Ansible playbooks should be run, the vm.provision config can be used in a Vagrantfile:

  config.vm.define "vm1" do |vm1|  
vm1.vm.box = "centos/7"
vm1.vm.hostname = "vm1"
vm1.vm.network "private_network", ip: "192.168.10.10"

vm1.vm.provision "docker", type:"ansible" do |ansible|
ansible.playbook = "docker-playbook.yml"
end

vm1.vm.provision "kubernetes", type: "ansible" do |ansible|
ansible.playbook = "kube-playbook.yml"
end
end

A Simple Playbook

Ansible uses the concept of playbooks to define a set of repeatable deployment steps.

This example deploys Docker on a CentOS system (should be saved as docker-playbook.yml in same directory as the Vagrantfile):

- hosts: all
become: yes
tasks:
- name: install docker dependancies
yum:
name: "{{ packages }}"
vars:
packages:
- yum-utils
- device-mapper-persistent-data
- lvm2

- name: Add Docker repo
get_url:
url: https://download.docker.com/linux/centos/docker-ce.repo
dest: /etc/yum.repos.d/docker-ce.repo
become: yes

- name: install docker
yum:
name: "{{ packages }}"
vars:
packages:
- docker-ce
- docker-ce-cli
- containerd.io

- name: Start Docker service
service:
name: docker
state: started
enabled: yes

- name: Add user vagrant to docker group
user:
name: vagrant
groups: docker
append: yes

Running

Running ‘vagrant up’ will cause all configured provision entries to run:

$ vagrant up
Bringing machine 'vm1' up with 'virtualbox' provider…
<snip>
==> vm1: Configuring and enabling network interfaces…
==> vm1: Rsyncing folder: /home/rich/vagrant_storm/ => /vagrant
==> vm1: Running provisioner: file…
==> vm1: Running provisioner: shell…
vm1: Running: inline script
==> vm1: Running provisioner: docker (ansible)…
vm1: Running ansible-playbook…
PLAY [all] *
TASK [setup] ***
ok: [vm1]
TASK [install docker dependancies] ***
changed: [vm1]
TASK [Add Docker repo] *
changed: [vm1]
<etc...>

Provisioning Again

Provisioning can also be run independently once the VM(s) are up

vagrant provision

By naming each provision entry, it’s also possible to run a specific item:

$ vagrant provision --provision-with kubernetes
==> vm1: Running provisioner: kubernetes (ansible)…
vm1: Running ansible-playbook…
PLAY [all] *
TASK [setup] ***
ok: [vm1]
TASK [add Kubernetes' YUM repository]
ok: [vm1]
TASK [install kubernetes]
ok: [vm1]
TASK [start kubelet] ***
changed: [vm1]
PLAY RECAP *
vm1 : ok=4 changed=1 unreachable=0 failed=0

Summary

Making use of Ansible along with Vagrant provides a super-fast, repeatable way to bring up a system with a defined configuration.

This will form the basis of an automation system for end-to-end testing, which future posts will build on.