Ansible I: Concepts and Installation

2019-08-03 , updated 2019-10-23

With this post we start a series about Ansible, the IT automation tool. This first article introduces the basic concepts of Ansible and its installation. Also we will install VirtualBox and Vagrant which will help us to practice Ansible in a more realistic scenario without exiting our computer.

UPDATE: I found that in the Docker for Windows approach you can't use the containers IP to connect to them in the documentation. I added new sections using Vagrant and VirtualBox which will represent better a real scenario, removed Docker mentions, and did other minor changes.

By the end of this article you will have:

Note: This series is focused in Ansible on Windows but the commands can be easily ported to Linux, as we will be using the Windows Subsystem for Linux which is basically Linux inside Windows. Ask if you have any doubt or problem!

Ansible in a few words

Ansible is an automation tool that can run actions (aka commands or tasks) in machines directly from your computer, without any special setup. To write the actions we use YAML which lowers the barrier for newcomers, since it is easy to read. Ansible has a large community and RedHat behind it so it grows more and more every day, improving the Windows support each day (which is nice for me since I work in a Windows environment).

Control Node and Managed Nodes

With Ansible you can run actions from your computer in other machines. Technically you should call Control Node to your computer and Managed Nodes to the other machines. Your computer control machines and those machines are managed by you, pretty straightforward. However here we will use the word hosts to call the Managed Hosts, since that word is too long (the community use the word hosts too, probably for the same reason).

Getting work done: Modules, Tasks, Roles & Playbooks

Modules encapsulate Ansible "actions". We can think about them as the unit of work. For example with the copy module (source and documentation) we can copy files from the control node to the hosts.

Modules need parameters to do their job. For example copy needs to know where the file that we want to copy (on your machine) and where will be copied (in the remote hosts). We can provide those using src and dest. For example:

# Welcome to YAML, use two spaces to ident
copy:  # Module name
  src: instructions.pdf  # Parameter, idented
  dest: some/remote/folder/instructions.pdf  # Parameter, idented

This alone will not work, as we should use modules inside tasks. Those basically give them a name for better comprehension, but also can be used to control the flow of execution. For example:

name: distribute PDF with instructions to all machines  # Give them an meaningful name!
copy:  # Module name
  src: instructions.pdf  # Parameter, idented
  dest: some/remote/folder/instructions.pdf  # Parameter, idented

Tasks should run inside another bigger thing called playbook. It contains tasks in a certain order and defines in which hosts those tasks will be used. An example of a playbook:

# YAML files start with three dashes, weird but true
---
# Playbooks are lists, so use a dash before the name of the playbook
- name: Playbook Name
  hosts: all  # We want to run against all hosts
  # Tasks is also a list, so use a dashe before each task
  tasks:
    - name: distribute PDF with instructions to all machines  # Task name
      copy:  # Module name
        src: instructions.pdf  # Parameter, idented
        dest: instructions.pdf  # Parameter, idented

    - name: notify everyone  # Task name
      slack:  # Module name
        channel: event-X  # Parameter, idented
        msg: Instructions are in your computers!  # Parameter, idented

This playbook will run the copy module, which will copy the instructions.pdf from our computer to the managed nodes and then will call the slack module to notify a channel about it.

Knowing who you talk to: Inventories

So how our computer knows which are the managed nodes? Ansible has the inventory. The inventory is a file in ini format that contains a list of managed nodes. Remember that hosts: all from the playbook? You can group them! For example:

[all]
managed-01.company.com
managed-02.company.com
10.120.240.240

[windows]
managed-01.company.com

[debian]
managed-02.company.com
10.120.240.240

So you could run your playbooks using hosts: windows or hosts: debian instead of hosts:all if you want to.

Preparing the environment

Install the Windows Subsystem for Linux (WSL)

Microsoft WSL Installation Guide

We can not install Ansible directly into Windows, but it works inside the Windows Subsystem for Linux (WSL from now on), which is kind of an embeded Linux inside Windows.

The WSL is a feature, so we can activate it using the interface. However we will use PowerShell to activate it. Open a PowerShell prompt (search 'PowerShell' in the search bar and right-click it) with administrator rights and run:

Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux

After rebooting your computer you can install a Linux distribution from the Windows Store. I personally use Ubuntu, since I am familiar with it. Now search for Ubuntu in the Windows Store!

Screenshot of Ubuntu in the Windows Store
Ubuntu in the Windows Store.

After install the distribution, type "Ubuntu" in the search bar and open the application. The first time you will have to configure the user and the password, but it is straightforward to do it. This is not the only way to access your Ubuntu inside Windows. I usually open a PowerShell prompt and type wsl and this moves me to the Ubuntu bash prompt.

Screnshot of console configuring Ubuntu for the first time
First time configuration of Ubuntu

Many of the commands from now will be run inside the WSL, so be careful! If you see a bash flag on the top of the code box, it means that is run inside the WSL, as we will use bash there. If the flag is powershell we will be running in Windows directly.

Preparing a Python virtual environment and installing Ansible

Note: Remember to run inside the distribution

Ansible runs with Python, so you will need to have Python installed. If you selected the Ubuntu distribution you will have python3 installed. If that is not the case, check how to install Python in your distribution. Then run:

$ python3 -m venv venv

This will create a virtual environment that we will use to install Ansible. Using it we will maintain our Ansible installation isolated from the global packages installed, which is nice when there are conflicting dependencies. In Ubuntu this will fail with the following error:

$ python3 -m venv ansible-venv
The virtual environment was not created successfully because ensurepip is not
available. On Debian/Ubuntu systems, you need to install the python3-venv
package using the following command.

    apt-get install python3-venv

You may need to use sudo with that command.  After installing the python3-venv
package, recreate your virtual environment.

Failing command: ['/home/hector/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']

So run: sudo apt-get y install python3-venv and accept the installation of the proposed packages. After that you should be able run the command without problem:

$ python3 -m venv ansible-venv

The virtual environment resides in a folder which has a certain structure. To activate the virtual environment you have to source a file inside those folders. Here you have the command:

$ source ansible-venv/bin/activate

After the activation you should see a (ansible-venv) flag in your bash prompt. That indicates that the virtual environment is activated. Remember to do so when running Ansible, since it will be only avaiable inside this virtual environment.

(ansible-venv) $ pip install ansible
(ansible-venv) $ ansible --help

This should return the Ansible command line help. If it worked, Ansible will probably run without problem.

Installing Vagrant and VirtualBox

Yet another thing to prepare before we start playing with Ansible. Vagrant is a tool that help us to create configurations in order to standardize environments across people. Then with a backend, in our case VirtualBox, we will create virtual machines (for short VMs) to test Ansible against.

Both are simply installers and you will need to restart your computer, maybe a couple of times. To test they are correctly installed, run:

vagrant init ubuntu/bionic64
vagrant up

This will require administrator permissions (on Windows), so be sure to run in a terminal with adminsitrative rights. On Linux I'm not sure if it will need sudo to run. That two commands will create a Vagrantfile (the configuration file) and will start the virtual machine. You can now open the VirtualBox app and check that a machine is created and running. Then you can connect to the virtual machine with vagrant ssh which will start a ssh session. After using it, you can destroy it using:

vagrant destroy

Closing

So now you are ready to start playing with Ansible and some virtual machines. You can check the getting started guides of both tools to grasp more basic concepts and get a better idea on how to use them.

In the following article we will spin up some virtual machines and configure Ansible to run playbooks against them.

Continue reading

it automation configuration as code