Introduction to Ansible

5329

Ansible kind of exploded into popularity almost immediately after its release in 2012, and has become a staple for network administrators. In today’s article, we’re just going to immediately dive in and give you a good idea of what Ansible does and how you can get the most out of it.

Ansible is an open source automation platform. What that means is that it lets you manage software installations, updates, configurations and tasks within your network environment. It’s especially handy in situations where you need to carry out sequential operations. It’s also comparably easy to use, when put against other similar solutions.

The good:

  • Low barrier for entry, and general ease of use.
  • Very helpful with scaling of homogenous environment.
  • Easy host management using Playbooks.
  • Very secure since it uses SSH to connect.
  • Allows sequential execution of scheduled tasks (ie, it won’t start a new taks before finishing another one).
  • Easy to install and configure.

The bad:

  • SSH connections can get slow in scaled environments.
  • As the platform continues to develop, it sometimes breaks backwards compatability.
  • No GUI to manage playbooks

Ansible is free and open-source remote server manager available for Linux, Mac and BSD. There is also an enterprise version called Ansible Tower, which is a web based solution and makes everything even easier. However, we’ll just stick to the free version for this article.

Installing Ansible is pretty simple. Using Ubuntu or Debian the command is easy:

# apt install ansible

If you’re running CentOS or Fedora, you can use EPEL to install it using this:

# yum install epel-release -y ; yum install ansible -y

Once you have Ansible installed, you’ll need to add your remote servers to its configuration file, located in /etc/ansible/hosts:

# vim /etc/ansible/hosts
[remote-hosts]
host1
host2
...
192.168.1.29

Then you’ll need to add an open SSH key from your Ansible server to your remote servers (/root/.ssh/authorized_keys):

# ssh-keygen
# cat /etc/ansible/hosts | xargs -i ssh-copy-id {}

Afterwards, it’s easy to check your connections through the ansible ping command, being sure to include the “all” tag to have go through every connected server :

# ansible -m ping all
host1 | success >> {
  "changed": false,
  "ping": "pong"
}
...
host2 | success >> {
  "changed": false,
  "ping": "pong"
}

The host file allows for a lot of flexibility in terms of how you manage servers, allowing you to group them, assig SSH ports and more. For instance, I have a setup with two backends running on Cent OS 7, a load balancer on Ubuntu and a database server also running on Ubuntu. So let’s group them together with Ansible: 

 

# cat /etc/ansible/hosts
[backend]
backend-node-1
backend-node-2

[balancer]
balancer-0

[dbs]
mysql-server-0

[ubuntu-hosts]
balancer-0
mysql-server-0

[centos-hosts]
backend-node-1
backend-node-2

We can also use Ansible to add services. Let’s add the “httpd” service to our backend:

# ansible backend -m service -a "name=httpd state=stopped"
backend-node-1 | success >> {
  "changed": true,
  "name": "httpd",
  "state": "stopped"
}
backend-node-2 | success >> {
  "changed": true,
  "name": "httpd",
  "state": "stopped"
}

But the real draw of using Ansible is their playbooks system. Like the sports reference of the name implies, a playbook is a set of instructions for Ansible to follow in sequential order. Playbooks are written in a script called YAML which is surprisingly intuitive to the point where you should be able to get used to it only after a few minutes of use. So writing and editing playbooks is relatively easy as well. 

Here, for instance, is what a playbook for installing NGinx will look like. First, we need to create a directory structure for the playbook:

# mkdir handlers 
# mkdir tasks
# mkdir templates
# mkdir vars

“Handlers” directory is used for processing periodical assignments, like restarting services and such. “Tasks” will have you executables. “Templates” will have your configuration templates, and “vars” are there to keep shared variables used by the playbook.

Now let’s fill in our handler:
 

# vim handlers/main.yml
---
- name: restart nginx
service: name=nginx state=restarted enabled=yes

Finally, let’s get Ansible installed:

# vim tasks/main.yml
---
- name: Install EPEL repo in CentOS
  yum: name=epel-release state=present
  when: ansible_os_family == "RedHat"

- name: Install nginx package
  apt: name=nginx state=present

- name: Create directory for configs
  file: dest=/srv/{{ s_name }} state=directory

- name: Copy virtualhost config
  template: src=default.conf dest=/etc/nginx/conf.d/{{ s_name }}.conf

- name: Copy index.html to directory
  template: src=index.html dest=/srv/{{ s_name}}/index.html
  notify: restart nginx

With this code, we’re installing the EPEL repository fpr RHEL-based distros as this repo contains the nginx packet. The code installs the nginx packet, creates a /srv/[host name here without brackets] to store configurations that are then copied to it along with the indexing template. 

Template for virtual hosts will look like this:

# vim templates/default.conf
server {
listen 80;
server_name {{ s_name }};
root /srv/{{ s_name }};
location / { index index.html index.htm; }
}

This is the index file template:

# vim templates/index.html
My name is {{ s_name }}

You might’ve noticed that the brackets in that code designate variables where Ansible stores your server names, which are stored in the vars directory:

# vim vars/main.yml
---
s_name: "{{ ansible_fqdn }}"

For our example, the variable server_name will correspond the server name, and will show up when you run the hostname -f command on our remote server.

You might’ve also noticed lines that look like this in the tasks/main.yml file:

when: ansible_os_family == "RedHat"

Ansible can identify the running OS on the host, and uses that information to make decisions as to how to proceed with the install. For instance, we don’t need to install the EPEL repository when putting NGinx on an Ubuntu platofrm, so some of these commands won’t be executed for hosts that aren’t RHEL-based.

All that’s left is creating the actual playbook file:

# vim nginx-install.yml
---
- name: Install nginx on remote hosts
hosts: backend
roles:
- nginx

Now to run the playbook:

# ansible-playbook nginx-install.yml
...
PLAY RECAP ********************************************************************
backend-node-1 : ok=6 changed=5 unreachable=0 failed=0
backend-node-2 : ok=6 changed=5 unreachable=0 failed=0

Alright, let’s check if our web-server works:

# curl backend-node-1
My name is backend-node-1
# curl backend-node-2
My name is backend-node-2

Hopefully, this guide gave you a good idea of how to setup Ansible. And if you got any questions, feel free to hit us up on Twitter and Facebook, and follow and like our pages to stay updated with releases and more articles!

Ansible itself is very modular, and you can check out what’s available here: Modules by category.

And full documentation of Ansible and how to use it can be found here: Documentation.

-Until next time!