Ansible Playbook - what is it and why its amazing ?

Working with Ansible , you can use Ad-Hoc commands if you want to automate simple task or you will use playbook and roles if you want to automate more complex tasks or series of tasks and keep a certain degree of organization.

Ansible playbook is the ansible orchestration language in Ansible that we will define what we want to do and which state we want on our servers.
A playbook is the term that Ansible uses for a configuration management script.

Basically, it will be a set on instruction we want Ansible to achieve on our servers using the Ansible Module.

There are thousands of modules already present.

Ansible Module Inventory

It can be simple or very complex. Today, as it’s an brief introduction, we will focus on a simple playbook to change settings of Proxy on our Linux Servers.

Ansible Playbook

Before making our first playbook, let’s focus on the theory.

PLAYBOOK YAML file format

Ansible is using YAML file format.

YAML is a file format easier for humans to read and write, like JSON.

A YAML syntax needs to follow the correct indentation and one needs to be a little careful while writing the syntax. I will recommend you to use YAML IDE or any extension/plugins on your favorite IDE to work with YAML file.

💡 I’m using Visual Studio Code with these extensions or directly Vim but Visual Studio code is free and really good and useful.

  • YAML Support by Red Hat - provides YAML support through yaml-language-server with built-in Kubernetes and Kedge syntax support.
  • Ansible Syntax Highlighting Extension - YAML & Jinja2 support.
  • Visual Studio Code extension for Ansible - provides autocompletion, syntax highlighting.
  • The remote SSH extension remote-ssh

visual_studio_code_ansible

You can have a look on this page for further information on best tools and applications to use with Ansible : Ansible Editors

Comments start with a number sign ‘#’ like a lot of programming language as bash, python.

# this is a beautiful comment

⚠️ YAML does not support multi line comments.

Strings and thus paramaters can be quoted or not, it’s not mandatory but I always prefer to do as it’s mandatory in some scenarios like using the {{ braces }} for variables substitution.

- name: "super playbook"
# without quote 
- name: second playbook super
  debug:
    msg: "{{ variable }}"

Booleans are very flexible on Ansible and you can use booleans as below :

  • True, true, TRUE, yes, Yes, YES, y, Y, on, On, ON
  • False, false, FALSE, No, no, NO, n, N, off, Off, OFF

Ansible Playbook

Module arguments are passed as strings and use Ansible internal conventions, which are:

  • yes, on, 1, true
  • no, off, 0, false

Ex: YAML Format

---
- name: Update postinstall.sh on template
  gather_facts: True
  become: True
  hosts: template

  tasks:

  - name: Replace postinstall on /usr/local/bin/
    copy:
      src: /etc/ansible/playbook/files/PostInstall.sh
      dest: /usr/local/bin/PostInstall.sh
      backup: yes
      validate: ls %s

🔥 I’m trying to follow the ansible convention and use True or False on the playbook and yes and no on module arguments.

Lists in YAML are like arrays in Python, they are delimited with ‘-’ , but you can use as well inline format for lists

---
### Inline list
win_updates_category_names: ['CriticalUpdates', 'SecurityUpdates', 'UpdateRollups', 'FeaturePacks', 'DeveloperKits','Connectors' ]

### lists 
win_updates_category_names:
  - CriticalUpdates
  - SecurityUpdates
  - UpdateRollups

Dictionaries are like Dictionaries in python key:value. Playbook are using keyword to configure play and task, or roles and they are mostly Dictionaries.

---
- name: Update postinstall.sh on template
  gather_facts: True
  become: True
  hosts: template

Now that we know more about YAML, let’s focus on the playbook itself and the relation between each entity, play, tasks and hosts.

Terminology of Ansible Playbook

Playbook is a single YAML File ( extension .yml ) and is the script containing one or more play or roles.

Play - Define a set of tasks/instruction to be run on hosts - it’s the link between the tasks and the hosts.

Task - An action to be play on the host using one module - Execute a command - Install a Package - Change a file - Create user and group - And so on…

Ansible relationship diagram

Let’s see each of them more deeply…

The Playbook

A playbook is a list of plays or roles.

It can contains one or more plays or roles or an import of list of plays from another playbook using the keyword ‘import_playbook’.

It’s the only thing which can be run by the Ansible command : ansible-playbook

The Play

The function of a play is to map a set of tasks defined against a particular host or a group of hosts.

The play always contains :

  • a host or a group of hosts, it can be a hostname, all, ungrouped or group name. These are set with the keyword : hosts
  • a list of tasks which will use module to be executed on each host. The task are configured using tasks block or a list of roles to be imported. The roles will be cover on the article.

And recommended :

  • a name to describe the usage of the play

Optionally few parameters/keyword Ansible play keyword

Few most commons keyword are by example :

# use adhoc command setup to get facts of the hosts
gather_facts: True|False 
# to become sudo 
become: True|False
# block to define variable
vars: 
  - user: "superman"
  - ntpserver "ntp.superdns.com"
# Location of file where variables are defined
vars_files: 
# list of variables to prompt for.
vars_prompt
# list of tags 
tags: 
  - install 
# to Enforce check mode ( Dry-run )
check_mode: True

The Tasks

A task is an action, a call to an ansible module. This tasks doesn’t know alone on which hosts it is supposed to run.

Every task must contain a key with the name of a module and a value with the arguments to that module.

The list of tasks should start on the play by the keyword : tasks

Let’s see what we’ve just learn in a playbook which will change proxy for Redhat based and Linux Vms :

The Playbook will contains 2 plays, one play for RedHat Hosts and one play for Debian Hosts

Our Inventory file is a below :

vim servertest.cfg

[redhat]
mt-ce-medcre[6:7]
mt-ce7-repo1

[debian]
mt-ub-graf1
mt-ub-postfix

---
# This is a play and the description 
- name: Update proxy for redhat
  gather_facts: True
  become: True
  hosts: redhat

  vars:
    - oldproxy: ["10.89.20.30", "super-proxy.vodafone.com"]
    - newproxy: "amazing-proxy.vodafone.mt"

  tasks:
    # this is a task 
   - name: gathering distribution facts
     # this is a module
     debug:
       msg: System {{ inventory_hostname }} - {{ ansible_os_family }} - {{ ansible_distribution }} - {{ansible_distribution_major_version }}

    # this is another task
   - name: get dns information
     # this is another module
     shell: cat /etc/resolv.conf
     register: dns

   - name: print DNS information
     debug: msg={{ dns.stdout_lines }}

   - name: "Change Proxy settings for redhat vms"
     replace:
       dest: /etc/yum.conf
       regexp: '{{ item }}'
       replace: '{{ newproxy }}'
       backup: yes
     with_items:
       - "{{ oldproxy }}"

- name: Update proxy for debian
  gather_facts: true
  become: yes
  hosts: debian

  vars:
    - oldproxy: ["10.89.20.30", "super-proxy.vodafone.com"]
    - newproxy: "amazing-proxy.vodafone.mt"

  tasks:

   - name: gathering distribution facts
     debug:
       msg: System {{ inventory_hostname }} - {{ ansible_os_family }} - {{ ansible_distribution }} - {{ansible_distribution_major_version }}

   - name: get dns information
     shell: cat /etc/resolv.conf
     register: dns

   - name: print DNS information
     debug: msg={{ dns.stdout_lines }}

   - name: "Change Proxy settings for Ubuntu vms"
     replace:
       dest: /etc/apt/apt.conf
       regexp: '{{ item }}'
       replace: '{{ newproxy }}'
       backup: yes
     with_items:
       - "{{ oldproxy }}"

Something important to notice is that each play are link with different hosts groups as the package manager is different if it’s debian or redhat based machines ( by default, apt and yum package manager ).

Let’s launch this playbook and change the proxy use by the package manager of our Vms.

ansible-playbook updateproxypackagemanager.yml -i servertest.cfg

Then, you will see the result/state of each tasks and finally the result of the recap :


< PLAY RECAP >
 ------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

mt-ce-medcre6              : ok=5    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
mt-ce-medcre7              : ok=5    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
mt-ce7-repo1               : ok=5    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
mt-ub-graf1                : ok=5    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
mt-ub-postfix              : ok=5    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

This end our article about the Playbook. Next time, we will speak about roles and notify/handlers.

< It is the end until the next episode... >
 ------------
        \   ^__^
         \  (- -)\_______
            (__)\       )\/\
                ||---- w |
                ||     ||