5 min read

Managing virtual machines with Vagrant

Managing virtual machines with Vagrant

Years ago, the developer world faced the containers age, which was quicker and stronger than virtual machines, easy to deploy, portable, and lightweight.

So, why are we talking about Virtual Machines?

It is important to highlight that some businesses still use virtual machines to support their products or applications. Paid hosting services, for example, employ KVM (Kernel-based Virtual Machine), VirtualBox, VMWare and Hyper-V. We may also use these virtual machine technologies to run our Linux distribution.

I used to use VMWare and VirtualBox on my Linux to test Windows applications and development. Nowadays, Linux has a lot of support, and wine can simulate programs and tools with plenty of documentation to do this.

However, Roblox Corporation decided to ban Wine, arguing that it is a haven for cheaters. Okay, it's a Windows emulator; is there no cheat on Windows 😕? How can I entertain my son 😢?

Back to Vagrant, this tool was created by HashiCorp, a company that has made significant contributions to the Open Source community. This tool describes a virtual machine ruby file called Vagrantfile, in which images such as Debian, Ubuntu, Arch, Fedora, Amazon Linux, and others may be defined.

Shell scripts or Ansible may be used to prepare virtual machines. That's cool; you may test your configuration in your local environment. Another essential element is the network, which allows us to set public and private ports, as well as mapping and forwarding. VirtualBox, KVM, VMWare and Hyper-V may be utilized for running machines.

Personal application

I started using Vagrant when Docker deprecated the Docker machine tool, which was great when you wanted to create a droplet at Digital Ocean or our testing Docker Swarm. When you run at a local Docker machine, VirtualBox is utilized by default to setup your Docker Host. There are forks from this project, but I only found images with outdated Docker versions, so I went with Vagrant.

Examples of use cases

  • MongoDB Cluster
  • RabbitMQ Cluster
  • Dokku Node
  • Docker Swarm Cluster
  • Kubernetes Cluster
Vagrant may be used to test clusters in a local environment.

Requirements

VirtualBox

The default, and it works with one cup of coffee ☕ right away. To simulate a virtual machine, I can confirm that the version 6.1 available from the official Ubuntu/Debian repository works. To install VirtualBox, use the following line; for Windows, get the installer here.

# debian, ubuntu
sudo apt install virtualbox

# arch, manjaro
sudo pacman -S virtualbox
Other dependencies as Ruby, will be installed by vagrant.

Network settings

To allow virtual to assign IP addresses, create a file called /etc/vbox/networks.conf. In the example below, we set a range of 192.168.0.0/16.

sudo mkdir -p /etc/vbox
echo "* 192.168.0.0/16" | sudo tee -a /etc/vbox/networks.conf

Installing

Vagrant offers a comprehensive installation that includes all operational systems. Install vagrant by clicking here.

For debians

wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update && sudo apt install vagrant

Creating a Virtual Machine

It is now time to configure your Virtual Machine; first, we must declare the Vagrantfile.

IP = "192.168.0.200"

Vagrant.configure("2") do |config|
  config.vm.box = "debian/buster64"
  config.vm.hostname = "hello-vagrant"
  config.vm.network :private_network, ip: IP
  
  config.vm.synced_folder "shared", "/shared"
end

Let us go over this simple Vagrant file.

  • config.vm.box specifies the name of the operating system box;
  • config.vm.hostname specifies the name of the virtual machine's host;
  • config.vm.network specifies private and public network settings.
  • config.vm.synced_folder defines which directories should be shared by the host and virtual machine.

The following command will start the machine, prepare some resources, and let you to log in over SSH.

mkdir -p shared && echo "bar" > shared/foo.txt
vagrant up
vagrant ssh

Provisioning

Shell

The following changes will insert a shell script that creates a dummy file at /home/vagrant/LOADED every time provision is executed.

  • Vagrantfile
IP = "192.168.0.200"
ANSIBLE_PATH = File.expand_path("./ansible")

Vagrant.configure("2") do |config|
  config.vm.box = "debian/buster64"
  config.vm.hostname = "hello-vagrant"
  config.vm.network :private_network, ip: IP
  
  config.vm.synced_folder "shared", "/shared"

  config.vm.provision "shell", inline: "touch /home/vagrant/LOADED"
end

Ansible

Ansible is best suited for complex and reusable scripts. The following changes add Ansible script as a provision that runs as root.

  • Vagrantfile
IP = "192.168.0.200"
ANSIBLE_PATH = File.expand_path("./ansible")

Vagrant.configure("2") do |config|
  config.vm.box = "debian/buster64"
  config.vm.hostname = "hello-vagrant"
  config.vm.network :private_network, ip: IP
  
  config.vm.synced_folder "shared", "/shared"

  config.vm.provision "setup", type: "ansible" do |ansible|
    ansible.playbook = "#{ANSIBLE_PATH}/setup.yml"
    ansible.become = true
  end

  config.vm.provision "shell", inline: "touch /home/vagrant/LOADED"
end

The became attribute defines playbook execution as the root.

  • ansible/setup.yml
---
- name: Setup vagrant
  hosts: all
  become: true

  tasks:
    - name: Install packages
      apt:
        name:
          - curl
          - wget
          - nano
          - htop
          - nginx
        state: latest
        update_cache: true

The preceding playbook will install a few APT packages. If you want to learn more about Ansible, follow the link below.

Run your first Ansible playbook
Is an IT solution focuses on automation, configuration management, application deployment and orchestration. Without an agent on the server.

Testing

As a huge fan of NGINX, I installed the web server through Ansible Script to test connection; recall, we defined IP 192.168.0.200 for the virtual machine. To test, open your browser.

Commands

Run provisions

# run all provisions
vagrant up --provision

# run specific provision
vagrant up --provision-with setup

Restart

vagrant reload

Stop

vagrant suspend

Destroying machine

vagrant destroy

Connect over ssh

vagrant ssh

# for multiple machines
vagrant ssh [machine-name]

Final thoughts

You may get the source code from my Github repository.

This time, we'll look at how to use Vagrant to build virtual machines for testing scenarios. You may learn more from the official documentation and experiment with KVMKVM or VMWare as homework.

Keep your 🧠 kernel up to date. See ya! God bless 🙏🏿 you.