Using this blog and video we demonstrate using Vagrant to provision Terraform using Ansible. We will provision Terraform to deploy Docker containers on our Vagrant host, but, of course, Ansible could provision anything and not just Terraform. Vagrant is a Virtual Machine Manager and it has a variety of provisioners that allow you to customise the system on first boot. We do have an Ansible provisioner which can deploy a Playbook from Ansible installed on the Host. Ansible can be installed on Linux and macOS but currently not on Windows. Additionally, you may not want additional software installed on your host. There is also and Ansible_local provisioner which will install Ansible on to you guest system before running the Playbook. Whilst this is good, I do not like the idea of hardcoding the PLaybook to run inside of my Vagrantfile. This leads use to another possibility; have the shell provisioner install Ansible for you and add a variety of Playbooks into the directory that the Vagrantfile exists. This is shared with the Virtual Machine. We can also have a Playbook clone a git repository where you keep all the PLaybook you need.
On your host system you will need to create a project directory for the Vagrant file. The file could look something similar to this:
The Vagrantfile
# vi: ft=ruby:ts=2:ai:sw=2 $script = <<-SCRIPT echo "Provisioning OS" sudo apt-get update sudo apt-get install -y ansible SCRIPT Vagrant.configure("2") do |config| config.vm.box = "ubuntu/focal64" config.vm.provision "shell", inline: $script end
As the system boots Ansible will be installed by the shell provisioner that we have added.
Ansible does not need any configuration if it working just with the localhost. So it is easy to execute and Playbooks that we want. The working directory where we added the Vagrantfile is mapped through to the /vagrant directory on the guest. If we add Playbooks and resources we need into this directory on your host. In the following Playbook we download the Hashicorp signing keys for their repos, add their repo allowing us to install Terraform into the VM. We also install Docker and add the current user to the Docker group. To make resource access easy we can use the Ansible git module to clone a repository which has the Terraform config files we need, the main.tf. It is this file that is used to configure the Docker containers.
The Playbook:
. --- - name: Setup Terraform on New Ubuntu 20.04 System hosts: localhost gather_facts: true tasks: - name: Update the APT Package Cache become: true apt: update_cache: true cache_valid_time: 3600 - name: Before we add the Hashicorp Repo - we add the signing key become: true apt_key: url: "https://apt.releases.hashicorp.com/gpg" state: present - name: We now add the Hashicorp Repo to Ubuntu become: true apt_repository: repo: "deb [arch=amd64] https://apt.releases.hashicorp.com focal main" state: present - name: Install software from standard repos and hashicorp become: true package: name: - docker.io - gnupg - software-properties-common - curl - terraform - name: We add the local USER to the Docker group become: true user: name: "{{ lookup('env', 'USER') }}" groups: docker append: true - name: We clone the course git repository git: repo: "https://github.com/theurbanpenguin/comptia-automation.git" dest: "{{ lookup('env', 'HOME') }}/comptia-automation" version: main - name: We create the directory for terraform project file: path: "{{ lookup('env', 'HOME') }}/terraform/" state: directory - name: We create the web directory to store content file: path: "{{ lookup('env', 'HOME') }}/terraform/web" state: directory - name: We copy the main.tf terraform file from the course repo copy: src: "{{ lookup('env', 'HOME') }}/comptia-automation/terraform/main.tf" dest: "{{ lookup('env', 'HOME') }}/terraform/main.tf" - name: Create the index page for the website copy: dest: "{{ lookup('env', 'HOME') }}/terraform/web/index.html" content: This is my web page
The Terraform file, main.tf, is written the HCL format, it is also in my git repo:
The Terraform Main.tf
terraform { required_providers { docker = { source = "kreuzwerker/docker" version = "2.16.0" } } } provider "docker" { # Configuration options } resource "docker_image" "nginx" { name = "nginx:latest" keep_locally = false } resource "docker_container" "nginx" { image = docker_image.nginx.latest name = "webserver" ports { internal = 80 external = 8000 } volumes { container_path = "/usr/share/nginx/html" host_path = "/home/vagrant/terraform/web/" } }
Having run the Playbook we can logout and back in to join the correct groups and then enter our /terraform directory before running:
terraform init terraform apply
The plan will be shown and once we accept the Docker container will be started and our Nginx web site will be running. To destroy the containers we can use:
terraform destroy
You can see by adding the Playbooks that you want to your system we can have the flexibility to configure anything that we want including using Vagrant to Provision Terraform using Ansible Playbooks.