Vagrant machines handling with Ansible

Vagrant machines handling with Ansible

Automation and prototyping are not trivial tasks, especially when it comes to advanced factors like idempotency and reproducibility. In this article, we will show you how to prototype a simple infrastructure and automate its deployment using the cooperating tools: Vagrant and Ansible.

In this article, we will show you how to prototype a simple infrastructure and automate its deployment using the cooperating tools: Vagrant and Ansible.

The shorter the time it takes to bring a refined product to the market, the greater the chance of its success. When the process is repeatable and tasks can be automated, optimizations can be made to eliminate excessive use of resources, including employees’ time. The benefits of automation can grow infinitely when we consider its scalability.

The examples of automation benefits are:

  • the reduction of costs and the ability to invest the money saved
  • the standardization of workflows and products – they are consistent and reliable
  • employees can focus on tasks that require thinking outside the box, which makes the effect of work more satisfying than performing boring, repetitive tasks.

Prototyping involves creating a simplified, experimental model of a solution to see if it meets user expectations.

This phase of product release has the following benefits:

  • a working baseline that gives all stakeholders a picture of benefits, risks and costs
  • an earlier recognition of elements worthy of improvement and implementation of changes
  • the ability to receive feedback to determine which implementations work according to specifications
  • shortening the time of product launch by minimizing the number of errors to be corrected before the product is released on the market.

Automation and prototyping are not trivial tasks, especially when it comes to advanced factors like idempotency and reproducibility. However, there are many dedicated programs that provide them. One of the pair of tools we will describe today is Ansible and Vagrant.

Ansible

Ansible is an open source automation engine for tasks such as:

  • deploying software and infrastructure in the cloud
  • configuration management
  • in-service orchestration
  • the focus on Continuous Delivery.

Ansible uses Playbooks to interpret the tasks to be executed. A playbook is a text file that describes the roles that are assigned to specific machines. This allows you to reuse deployment tasks and describe some responsibility within that specified role. These machines are defined as a key-value pair in the inventory file.

Vagrant

Vagrant allows you to interpret the specification written by the deployer, described in a Vagrantfile. Vagrant imports previously prepared system images, applies the settings to the newly created virtual machine, and makes final configuration changes to the already running system using Ansible, for example. This specification means that the user does not have to manually configure their working environment for a specific task. The result of using Vagrant is that the operating environment is generalized and can be defined directly in a text file. This means that it can be placed together with the sources of the project itself, which is executed in the desired ecosystem.

Creating a simple infrastructure consisting of multiple machines is easy. Vagrant takes care of running the multiple VMs and applying the network configuration. If you need to change any of the parameters quickly, all you need to do is make a simple change to the specification – as opposed to manually managing said machines one by one.

Cooperation of the tools

Let’s take a look at how the tools described above are used in a DevOps workshop as part of preparation and automation of a prototype. As a demonstration, we will show a truncated version of a certain production project containing a server hosting a website and a monitoring server. In this example, for simplicity’s sake, the implementation will only rely on the running machines being able to communicate that they are online as Ansible requests. Let’s look at the file and directory structure:

.
├── playbooks
│   ├── monitoring.yml
│   └── webserver.yml
├── inventory.ini
└── Vagrantfile

and at the content of the files:

  • Vagrantfile
Vagrant.configure(2) do |config|
  config.vm.box = "eurolinux-vagrant/eurolinux-8"

  config.vm.define "monitoring" do |monitoring|
    monitoring.vm.hostname = "monitoring"
    monitoring.vm.network "private_network", ip: "10.0.0.2"
    monitoring.vm.provision "ansible" do |ansible|
      ansible.playbook = "playbooks/monitoring.yml"
    end
  end

  config.vm.define "webserver" do |webserver|
    webserver.vm.hostname = "webserver"
    webserver.vm.network "private_network", ip: "10.0.0.3"
    webserver.vm.provision "ansible" do |ansible|
      ansible.playbook = "playbooks/webserver.yml"
    end
  end
end
  • inventory.ini
[monitoring]
10.0.0.2

[webserver]
10.0.0.3
  • playbooks/monitoring.yml
---
- hosts: monitoring
  tasks:
    - name: Sample message from first machine
      debug:
        msg: "Monitoring machine is up"
  • playbooks/webserver.yml
---
- hosts: webserver
  tasks:
    - name: Sample message from second machine
      debug:
        msg: "Webserver machine is up"

In this simple example, we can see that Vagrant will interpret the specification in a Vagrantfile by running two VMs. It will then use Ansible to read an inventory.ini and connect to the systems with the addresses defined there. The instance will execute one of the playbooks contained in the playbooks directory that was specified earlier in that Vagrantfile.

We can now run this technology stack. For readability, I added the --no-parallel parameter so that the machines will be run sequentially, not in parallel.

 

$ vagrant up --no-parallel
Bringing machine 'monitoring' up with 'libvirt' provider...
Bringing machine 'webserver' up with 'libvirt' provider...
==> monitoring: Checking if box 'eurolinux-vagrant/eurolinux-8' version '8.5.2' is up to date...
==> monitoring: Creating image (snapshot of base box volume).
==> monitoring: Creating domain with the following settings...
==> monitoring:  -- Name:              sample-ansible-with-vagrant_monitoring
==> monitoring:  -- Domain type:       kvm
==> monitoring:  -- Cpus:              1
==> monitoring:  -- Feature:           acpi
==> monitoring:  -- Feature:           apic
==> monitoring:  -- Feature:           pae
==> monitoring:  -- Clock offset:      utc
==> monitoring:  -- Memory:            512M
==> monitoring:  -- Management MAC:
==> monitoring:  -- Loader:
==> monitoring:  -- Nvram:
==> monitoring:  -- Base box:          eurolinux-vagrant/eurolinux-8
==> monitoring:  -- Storage pool:      default
==> monitoring:  -- Image:             /var/lib/libvirt/images/sample-ansible-with-vagrant_monitoring.img (80G)
==> monitoring:  -- Disk driver opts:  cache='default'
==> monitoring:  -- Kernel:
==> monitoring:  -- Initrd:
==> monitoring:  -- Graphics Type:     vnc
==> monitoring:  -- Graphics Port:     -1
==> monitoring:  -- Graphics IP:       127.0.0.1
==> monitoring:  -- Graphics Password: Not defined
==> monitoring:  -- Video Type:        cirrus
==> monitoring:  -- Video VRAM:        9216
==> monitoring:  -- Sound Type:
==> monitoring:  -- Keymap:            en-us
==> monitoring:  -- TPM Backend:       passthrough
==> monitoring:  -- TPM Path:
==> monitoring:  -- INPUT:             type=mouse, bus=ps2
==> monitoring: Creating shared folders metadata...
==> monitoring: Starting domain.
==> monitoring: Waiting for domain to get an IP address...
==> monitoring: Waiting for SSH to become available...
    monitoring:
    monitoring: Vagrant insecure key detected. Vagrant will automatically replace
    monitoring: this with a newly generated keypair for better security.
    monitoring:
    monitoring: Inserting generated public key within guest...
    monitoring: Removing insecure key from the guest if it's present...
    monitoring: Key inserted! Disconnecting and reconnecting using new SSH key...
==> monitoring: Setting hostname...
==> monitoring: Configuring and enabling network interfaces...
    monitoring: SSH address: 192.168.121.139:22
    monitoring: SSH username: vagrant
    monitoring: SSH auth method: private key
==> monitoring: Rsyncing folder: /home/user/Documents/sample-ansible-with-vagrant/ => /vagrant
==> monitoring: Running provisioner: ansible...
    monitoring: Running ansible-playbook...

PLAY [monitoring] **************************************************************

TASK [Gathering Facts] *********************************************************
ok: [monitoring]

TASK [Sample message from first machine] ***************************************
ok: [monitoring] => {
    "msg": "Monitoring machine is up"
}

PLAY RECAP *********************************************************************
monitoring                 : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

==> webserver: Checking if box 'eurolinux-vagrant/eurolinux-8' version '8.5.2' is up to date...
==> webserver: Creating image (snapshot of base box volume).
==> webserver: Creating domain with the following settings...
==> webserver:  -- Name:              sample-ansible-with-vagrant_webserver
==> webserver:  -- Domain type:       kvm
==> webserver:  -- Cpus:              1
==> webserver:  -- Feature:           acpi
==> webserver:  -- Feature:           apic
==> webserver:  -- Feature:           pae
==> webserver:  -- Clock offset:      utc
==> webserver:  -- Memory:            512M
==> webserver:  -- Management MAC:
==> webserver:  -- Loader:
==> webserver:  -- Nvram:
==> webserver:  -- Base box:          eurolinux-vagrant/eurolinux-8
==> webserver:  -- Storage pool:      default
==> webserver:  -- Image:             /var/lib/libvirt/images/sample-ansible-with-vagrant_webserver.img (80G)
==> webserver:  -- Disk driver opts:  cache='default'
==> webserver:  -- Kernel:
==> webserver:  -- Initrd:
==> webserver:  -- Graphics Type:     vnc
==> webserver:  -- Graphics Port:     -1
==> webserver:  -- Graphics IP:       127.0.0.1
==> webserver:  -- Graphics Password: Not defined
==> webserver:  -- Video Type:        cirrus
==> webserver:  -- Video VRAM:        9216
==> webserver:  -- Sound Type:
==> webserver:  -- Keymap:            en-us
==> webserver:  -- TPM Backend:       passthrough
==> webserver:  -- TPM Path:
==> webserver:  -- INPUT:             type=mouse, bus=ps2
==> webserver: Creating shared folders metadata...
==> webserver: Starting domain.
==> webserver: Waiting for domain to get an IP address...
==> webserver: Waiting for SSH to become available...
    webserver:
    webserver: Vagrant insecure key detected. Vagrant will automatically replace
    webserver: this with a newly generated keypair for better security.
    webserver:
    webserver: Inserting generated public key within guest...
    webserver: Removing insecure key from the guest if it's present...
    webserver: Key inserted! Disconnecting and reconnecting using new SSH key...
==> webserver: Setting hostname...
==> webserver: Configuring and enabling network interfaces...
    webserver: SSH address: 192.168.121.116:22
    webserver: SSH username: vagrant
    webserver: SSH auth method: private key
==> webserver: Rsyncing folder: /home/user/Documents/sample-ansible-with-vagrant/ => /vagrant
==> webserver: Running provisioner: ansible...
    webserver: Running ansible-playbook...

PLAY [webserver] ***************************************************************

TASK [Gathering Facts] *********************************************************
ok: [webserver]

TASK [Sample message from second machine] **************************************
ok: [webserver] => {
    "msg": "Webserver machine is up"
}

PLAY RECAP *********************************************************************
webserver                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Summary

As we can see, the task was completed successfully. This was a simple and intuitive introduction to creating larger, complex infrastructures within the prototype. For critical production systems, there is the ability to reuse tasks saved in playbooks, what significantly reduces developer effort and allows us to see the results at the layer of the DevOps’ workstation.

Authors

The blog articles are written by people from the EuroLinux team. We owe 80% of the content to our developers, the rest is prepared by the sales or marketing department. We make every effort to ensure that the content is the best in terms of content and language, but we are not infallible. If you see anything that needs to be corrected or clarified, we'd love to hear from you.