Getting started with Ansible

Relevant posts


What is Ansible ?

Ansible is an open-source configuration management tool i.e. for automating development or production environment setups, cloud provisioning, change management across multiple nodes. The thing which makes Ansible better then the other popular configuration management tools, like Puppet, Chef, etc is it’s agentless architecture. In the formal (Chef and Puppet) you are required to install the daeman/agent on all the nodes i.e. the controller/master node, as well as the nodes you need to manage (can be 100s or 1000s). In case of Ansible all you need to do is install the Ansible on the controller/master node, and it’ll ssh into all the ‘to be managed’ nodes (may require you to add the keys). This architecture not only makes the setup easy, but also reduces the network overhead, as continuous polling of controller node by the client nodes isn’t required. Ansible was initially supported and sponsored by Ansible, Inc (originally AnsibleWorks, Inc) – in October 2015 it was acquired by Red Hat.


Necessary Vocabulary

Let’s start with a brief intro of all the terminologies you need to know to get started with Ansible.
  • Controller Machine: the main machine where Ansible is installed (same as the Puppet master), this machine will be performing all the provisioning on the remote servers you need to manage.
  • Host: A host is simply a remote machine/node that Ansible controller manages. The Ansible controller gets to know about the hosts to manage via inventory file (briefed next).
  • Inventory: is a file where all the hosts to be managed by Ansible controller are listed. It’s an INI file, resides at Ansible controller – the default path is /etc/ansible/hosts.
  • Task: is a unit of provisioning i.e. install a package; restart a service, etc.
  • Play: Play is simply, a collection of (one or more) tasks for one or more hosts. For every play ‘host‘ (group of hosts) and ‘remote-user‘ must be specified.
  • Playbook: Playbook composed of one or more plays, is a complete configuration file, which you may put on version control. Ansible configuration is defined in YAML format.
  • Module: is what a task uses, it abstracts the real system commands and tools, for example ‘yum‘ module for package level tasks i.e. install, remove; ‘service‘ module for system service handling tasks i.e. restart, or stop, a system service. Ansible comes packed with a lot of built-in modules (almost for all the tasks), but for some custom task, you can write custom modules –  can be implemented in any language, including Perl, Bash, or Ruby – but can leverage some useful communal library code if written in Python. List of all the modules.
  • Facts: are the global variables Ansible uses to get dynamic system level info i.e. OS type, OS version, network interface info. Facts are used in Playbooks to keep the configuration dynamic i.e. installing Apache webserver depending on the OS type – apache2 for Ubuntu or httpd for CentOS.
  • Handlers: Handlers are a special type of tasks (defined in a same way as tasks, at the end of the conf file), to handle required follow through actions for a task i.e. restarting httpd after conf update (the task).  Handlers are called using ‘notify’ block inside tasks block.
  • Templates –  Templates are typically used to set up configuration files.

A Brief Explanation of Ansible conf file

Inventory

The first step after we you have Ansible setup, is to add the hosts in the inventory file. The hosts can be listed individually or in groups. A host can be defined using it’s IP address or hostname, whichever is accessible – optionally also the port number in case the host is not accessible on the default SSH port. The inventory file is an INI file which resides at Ansible controller – default location is in /etc/ansible/hosts.
An sample inventory file:
192.168.6.191

[test-servers]
192.168.40.193
192.168.40.194

[prod-servers]
192.168.40.195
192.168.40.196
This configuration file specifies five hosts. The first node is specified by its IP address and the latter four hosts are specified in two groups i.e. test-servers, and prod-servers.

Playbook

Playbook composed of one or more plays, is a complete configuration file, which you may put on version control. Ansible configuration is defined in YAML  i.e. install-httpd.yml.

Play

Play is simply, a collection of (one or more) tasks for one or more hosts. For every play ‘hosts‘ (group of hosts) and ‘remote-user‘ must be specified.
  • hosts – takes comma-separated host group names (as specified in the inventory) or individual hostnames.
  • remote-user : For each play in a playbook, you need to specify which hosts in your infrastructure to target and what remote user to complete the steps (i.e. tasks). Remote users can also be defined per task.
- hosts: test-servers
remote_user: nahmed
Note: The remote_user parameter was formerly called just user. It was renamed in Ansible 1.4 to make it more distinguishable from the user module (used to create users on remote systems).
An sample playbook with a single play:
ans6
The file is on github – install-httpd.yml

Tasks

A task is a single unit of provisioning – mainly it’s about specifying an Ansible module along with some required and optional parameters. All the tasks of a play (which itself a group of tasks) are indented under the ‘– task‘ block. For example to install apache using yum the task syntax ‘d be:
tasks:
- name: Install Apache Webserver
yum: pkg=httpd state=latest
or

Handlers

Handlers are simply the list of operations/tasks (not really any different from regular tasks) you need to run on change i.e. restarting Apache after conf update. Handlers are defined at the end using the ‘handler’ keyword (in same way as a task), and globally unique names. To call a handler action you need to use the ‘notify’ keyword at the end of a task and list the name of the handlers you need to trigger on the task’s success – in a play a handler will only be triggered once even if notified by multiple different tasks.
Ansible Handlers

An Ansible Demo

First you need to install Ansible, here’s a three nodes (one Ansible controller, and two remote hosts to be managed) step-by-step guide – Install Ansible on CentOS 7.
If you have Ansible installed, and key shared – the Ansible inventory we will be using for the demo:
[test-servers]
192.168.40.193
192.168.40.194
Once you have the Ansible setup ready, there are two ways to use ansible
  • Ad-Hoc – executing a task (command) on the remote host using Ansible’s comman-line tool.
  • Using Playbboks – permanently writing plays (group of tasks) for all or specific hosts or host groups, using YAML configuration specification language, that can be re-used and put to version control.

Approach 1. Ad-Hoc Commands

Let’s ping the 2 remote nodes using Ansible command-line tool – -m flag is to specify the Ansible module we need to use, and -all for all the hosts/groups in the inventory:
$ ansible -m ping all
Note: In case you have various groups of hosts, instead of all use the group name i.e.  ansible -m ping test-servers
Ansible ping
Let’s get the hostnames – using the Ansible’s shell module:
$ ansible -m shell -a "hostname" test-servers
Ansible shell

Approach 2. Using Playbooks

To demonstrated the Ansible Playbook execution we’ll be performing the following steps on the remote machines – automating the Apache installation and a simple HTML page deployment on two CentOS 7.1 machines:
  1. Install Apache web server i.e. httpd
  2. Place an index.html file at /var/www/html
  3. Enable Apache on system re-boots
  4. Restart Apache

Step 1 – Write the Playbook

The configuration for the above play in YAML
ans6
The file is on github – install-httpd.yml.

Step 2 – Execute the Playbook

Now that you’ve learned playbook syntax, how do you run a playbook? It’s simple. Let’s run a playbook using a parallelism level of 2:
$ ansible-playbook install-httpd.yml -f 2
The output:
Ansible playbook stdout

Step 3 – Verification

To verify if Apache has been installed, and index.html has been placed at /var/www/html – let’s access a remote host via it’s IP (Apache by default uses port 80):
Ansible success

Leave a Reply

Your email address will not be published. Required fields are marked *