Ansible – next generation configuration management

by Mohamed El MoussaouiMarch 26, 2013

The popularity of the cloud has taken configuration management to the next level. Tools that help system administrators and developers configure and manage large amounts of servers, like Chef and Puppet, have popped up everywhere. Ansible is the next generation configuration management. Ansible can be used to excute tasks on remote computers via SSH so no agent is required on the remote computer. It was originally created by Michael DeHaan.
I won’t compare Ansible with Puppet or Chef, you can check the Ansible FAQ. But the key differentiators are that Anisble does not require an agent to be installed, its commands can be ordered, can be extended via modules written in any language as long as they return JSON, basically taking the best of both worlds (Puppet and Chef).

Instalation

You’ll want to install Ansible on a central computer from which you can reach all the other computers.

On Fedora, it is already packaged:

sudo yum install ansible

On Ubuntu, you need to add a repo:

sudo add-apt-repository ppa:rquillo/ansible
sudo apt-get install ansible

On Mac, you can use MacPorts.

On others, compile it from source https://github.com/ansible/ansible.

Getting started

One of the core constructs in Ansible is the notion of an inventory. Ansible uses this inventory to know which computers should be included when executing a module for a given group. An inventory is a very simple file (by default it uses /etc/ansible/hosts) containing groups of computers.

Example:

[appservers]
app1.trifork.nl
app2.trifork.nl

As part of the inventory you can also initialize variables common to a group. These variables can then be reused when executing tasks for each computer.

[appservers]
app1.trifork.nl
app2.trifork.nl

[appservers:vars]
tomcat_version=7
java_version=7

You can set your own inventory by setting a global environment variable:

export ANSIBLE_HOSTS=my-ansible-inventory

You can then start using Ansible right away:

ansible appservers -m ping -u my-user -k

What this does is run module ‘ping’ for all computer in the group appservers, it returns:

app1.trifork.nl | success >> {
"changed": false,
"ping": "pong"
}

app2.trifork.nl | success >> {
"changed": false,
"ping": "pong"
}

You see that the module executed successfully on both hosts. We’ll come back to the ‘changed’ output later.
-u tells Ansible that you want to use another user (it uses root by default) to login on the remote computers. -k tells Ansible that you want to provide a password for this user.
In most cases you’ll probably want to setup a passwordless connection to the remote computers, ssh-copy-id will help you do that. Or better, you can rely on ssh-agent.

Gathering facts

Most of the time when using Ansible, you want to know something about the computer you are executing a task on.
The ‘setup’ module does just that, it gathers facts about a computer.

ansible appservers -m setup -u tomcat -k

You get a big output (I’ve removed some of it):

app1.trifork.nl | success >> {
    "ansible_facts": {
        ...
        "ansible_architecture": "x86_64",
        ...
        "ansible_distribution": "Ubuntu",
        ...
        "ansible_domain": "trifork.nl",
        ...
        "ansible_fqdn": "app1.trifork.nl",
        "ansible_hostname": "app1",
        "ansible_interfaces": [
            "lo",
            "eth0"
        ],
        ...
        "ansible_machine": "x86_64",
        "ansible_memfree_mb": 1279,
        "ansible_memtotal_mb": 8004,
        "ansible_pkg_mgr": "apt",
        ...
        "ansible_system": "Linux",
        ...
    },
    "changed": false,
    "verbose_override": true
}

app2.trifork.nl | success >> {
    "ansible_facts": {
        ...
        "ansible_architecture": "x86_64",
        ...
        "ansible_distribution": "Ubuntu",
        ...
        "ansible_domain": "trifork.nl",
        "ansible_fqdn": "app2.trifork.nl",
        "ansible_hostname": "app2",
        "ansible_interfaces": [
            "lo",
            "eth0"
        ],
        ...
        "ansible_machine": "x86_64",
        "ansible_memfree_mb": 583,
        "ansible_memtotal_mb": 2009,
        "ansible_pkg_mgr": "apt",
        ...
        "ansible_system": "Linux",
        ...
    },
    "changed": false,
    "verbose_override": true
}

These are Ansible facts, Ansible can also use extra facts gathered by ohai or facter.

Let’s review some of the Ansible facts:

ansible_pkg_mgr: This tells which package manager is in use on the remote Linux computer. This is important if you want to use the ‘apt’ or ‘yum’ module and want to make your scripts (playbooks) distro-agnositic.
ansible_distribution: This tells which Linux distribution is installed on the remote computer.
ansible_architecture: If you want to know which OS architecture it is.

Next time we’ll use these facts together with modules in a playbook example.