Ansible 101: #001 - Basics

Heyho! Welcome to my Ansible 101 Guide. I'm going to walk you through the most important aspects of Ansible. On the one hand, I'll try to explain all the mechanics in as much detail as possible and in an understandable way, but I'll also illustrate the whole thing with practical examples. I hope that works! Feedback from you is always welcome!

What is Ansible?
Let's start at the beginning. So what is this Ansible everyone is talking about? In a nutshell, it's an IT automation tool. Many people will have heard of it mainly in the context of configuration management, but Ansible can do much, MUCH more. A few small examples:

  • Package installations
  • Deploy entire virtual machines or cloud instances (AWS EC2, Azure VMs)
  • Configuration of the above
  • Install & configure applications

How does Ansible work?
Ansible works with SSH, so no agent software (other than the ssh agent, of course) is required on the target systems. Instead, the Ansible Controller (the box on which Ansible runs) must be able to establish an SSH connection to the Ansible targets. Tasks to be performed are then prepared as Python scripts, copied to the target and executed. The result is then returned to the Ansible controller.

Important: Idempotence and the declarative approach
This will come later, but it's so important to me that I can't resist getting on your nerves now. When we work with Ansible, we declare things, we don't write scripts.

Simply put, this means:
When an Ansible playbook is run for the first time, it will most likely change things to create the state declared in the playbook (explanation follows). If I run the same playbook again, without changing the parameters or target systems, there should be no further changes. This is called idempotency.

But you don't need to worry about that right now. Let's take a closer look at the various terms and mechanics:

Inventory
The Ansible inventory is the definition of all the target machines that we want to access with Ansible. An inventory can be divided into a number of groups.

[webservers]
web1.example-company.intra

[databases]
db1.example-company.intra

About Modules
Modules are the main tools in Ansible. For example, there is an Ansible module for installing packages on Debian (apt), appending one or more lines to a file (lineinfile) or creating a file from a template (template). Each module has its own parameter set.

If you want to get a first impression of how many possibilities Ansible offers, you can find a list of all integrated modules here:

https://docs.ansible.com/ansible/2.8/modules/list_of_all_modules.html

That's a lot, isn't it? :)

But don't let the number fool you. For us, just a few - very simple ones - are enough to do some really cool things!

Tasks
A task defines a task to be performed per target host. A task definition consists of calling a module and defining the module parameters. Here is a simple example:

- name: I am a task
  apt:
    name: apache2
    state: present

The task named in the example should make sure that the package named "apache2" is installed on the remote Debian system.

Playbooks
A Playbook is a collection of one or more Plays (explanation follows). A play is the execution of one or more tasks.

- hosts: webservers
  tasks:
    - name: install apache2
      apt:
        name: apache2
        state: present

    - name: start apache2
      systemd: 
        name: apache2
        state: started

Plays
A play defines a set of tasks to be performed on specific hosts. In the example above, the Apache web server is to be installed and started on all hosts in the webservers group.

# Play 1
- name: webserver play
  hosts: webservers
  tasks:
    - name: install apache2
      apt:
        name: apache2
        state: installed
    
    - name: start apache2
      systemd:
        name: apache2
        state: started

# Play2
- name: database server play
  hosts: databases
  tasks:
    - name: install mysql
      apt:
        name: mysql-server
        state: installed

    - name: start mysql
      systemd:
        name: mysql
        state: started

Handlers
Handlers are basically tasks that are only called when needed. In Ansible this is called "to notify". For example, we can design our playbook so that a task copies a config file and only restarts the associated service when changes are made to it.
Example:

- hosts: webservers
  handlers:
    - name: restart-apache
      ansible.builtin.systemd:
        name: apache2
        state: restarted
  tasks:
    - name: install apache
      ansible.builtin.apt: 
        name: apache
        state: installed
    
    - name: template apache config
      ansible.builtin.template:
        src: apache-config-template
        dest: /etc/apache2/apache2.conf
      notify: restart-apache

Two things are very important to know about handlers:

  • They are only called if the associated task also returns the status "changed".
  • They are always executed at the end of the playbook, NOT immediately after the calling task.

Roles
Roles are a relatively advanced mechanism, which we will discuss in more detail later. In short, certain tasks can be packed into reusable "packages" and used in multiple playbooks.

If all this seems a bit far-fetched, don't worry. We'll cover it all in detail. I'll also try to show you some application examples in between, so you can start working with Ansible if you want to.

In general, I think there is no better way to learn something than to try it out.

That's why we'll be looking at installing Ansible in the next part. After all, what's the point of talking about it if you can't do it yourself? Right? Exactly right!
Questions, criticism, suggestions for improvement... ?

... just leave a comment on this page or send me an e-mail:

[email protected]

See you soon!

mow