If you’re studying for your IT certifications, do technical research, or develop software you often need to set up a virtual lab environment. I lately created an article about how to automate the creation and provisioning process of virtual machines with Vagrant. And I also created an article on how to automate all your Linux servers with Ansible. In this article, we’re combining those two amazing technologies. And I show you how you can easily automate a full lab environment containing multiple virtual machines.
How to use Vagrant with Ansible on Windows 10
If you’re running Vagrant on Linux, you can skip this part. But if you’re running Vagrant on Windows with VirtualBox or Hyper-V, you have a problem. Because Ansible is not running on Windows, you will need to run Vagrant with Ansible scripts on a Linux machine. Luckily, you can do this pretty easily with the Windows Subsystem for Linux (WSL2). The trick is to install Vagrant on your WSL machine and on your Windows 10, too. Note, that it needs to be installed exactly in the same version and it’s still considered a beta version at this time.
To install Vagrant on WSL just simply download the latest version at https://releases.hashicorp.com/vagrant/.
wget https://releases.hashicorp.com/vagrant/2.2.10/vagrant_2.2.10_x86_64.deb sudo apt install ./vagrant_2.2.10_x86_64.deb
Next, you need to add a few environment variables according to https://www.vagrantup.com/docs/other/wsl.html. If you’re running bash, which is the default shell, you simply add them to your .bashrc file. If you’re using zsh you need to place them in your .zshrc file.
If you’re running Hyper-V on Windows 10 instead of Virtualbox, you should also set the default provider with the following environment variable.
Check if Vagrant is running on your WSL2 and can communicate to the Hypervisor on your Windows 10 by executing the vagrant command. If and error shows up, you probably haven’t loaded the environment variables correctly.
sudo apt-add-repository ppa:ansible/ansible sudo apt update sudo apt install ansible
Prepare the Vagrantfile to automate the virtual machine creation
Now let’s start with the creation of our Vagrantfile. If you’re not familiar with Vagrant yet, you should check out my tutorial about Vagrant, to learn the fundamentals. When you’re running Vagrant with VirtualBox, the configuration will look slightly different, because I’m using Hyper-V as my default provider. Any Virtualbox fans can just comment out the HyperV subconfiguration part.
# -*- mode: ruby -*- # vi: set ft=ruby : Vagrant.configure("2") do |config| config.vm.define "master" do |subconfig| subconfig.vm.box = "generic/ubuntu2004" subconfig.vm.hostname = "master" subconfig.vm.provider "hyperv" subconfig.vm.network "public_network", bridge: "BRIDGE" subconfig.vm.provider "hyperv" do |h| h.enable_virtualization_extensions = false h.linked_clone = false h.vmname = "ubuntu_cluster_master" end subconfig.vm.provision "ansible" do |a| a.verbose = "v" a.playbook = "master_playbook.yaml" end end end
If you later want to add more than one virtual machine, it’s useful to create a sub config for every single machine.
config.vm.define "master" do |subconfig|
We can automatically attach our virtual machine(s) to a virtual switch in Hyper-V with the following statement. The “BRIDGE” Interface is the name of my virtual switch that connects the virtual machine to my physical network adapter.
subconfig.vm.network "public_network", bridge: "BRIDGE"
This h configuration is part of the provider-specific configuration of the Hyper-V on Windows 10. For more information check out this blogpost.
subconfig.vm.provider "hyperv" do |h| h.enable_virtualization_extensions = false h.linked_clone = false h.vmname = "ubuntu_cluster_master" end
Now we will create another subconfiguration to provision the machine with an ansible-playbook. This will contain all ansible instructions to provision our virtual machine. Vagrant automatically executes the ansible-playbook once the virtual machine is created the first time.
subconfig.vm.provision "ansible" do |a| a.verbose = "v" a.playbook = "master_playbook.yaml" end
Create Ansible playbooks to provision the virtual machines
Now, we need to create your ansible-playbook that is used to provision our virtual machine. I’ve created an example of a playbook that will automatically install Docker. Of course, you can simply change the playbook to whatever your need is. By the way, if you’re looking for more useful examples of ansible-playbooks, just have a look at my GitHub repository ansible-boilerplates. You can simply use and modify them in a variety of different use-cases and setups.
Vagrant completely handles the provisioning and authentication part. You don’t need to enter any passwords or public SSH keys.
--- - hosts: all become: yes tasks: - name: install prerequisites apt: name: - apt-transport-https - ca-certificates - curl - gnupg-agent - software-properties-common - name: add apt-key apt_key: url: https://download.docker.com/linux/ubuntu/gpg - name: add docker repo apt_repository: repo: deb https://download.docker.com/linux/ubuntu focal stable - name: install docker apt: name: - docker-ce - docker-ce-cli - containerd.io update_cache: yes - name: add userpermissions shell: "usermod -aG docker vagrant"
Start the virtual lab environment
Now we can start our virtual lab environment. Simply execute “vagrant up” and Vagrant will create the virtual machine, install the box image, and provision it with the ansible-playbook.
If the ansible-playbook was executed successfully, you should see that all tasks are applied.
Let’s check if we’re able to login to our virtual machine and execute the docker command. To log in a remote-shell simply type in the “vagrant ssh” command. Then execute the command “docker –version”, to check if you’re able to execute any docker commands. If everything was successful, you will get the version number of docker.