Playbook Example

  • In here I will examile a real use case example by creating and executing Ansible playbooks. I will install Nginx in all hosts and explore the different options for targeting OS variations with Ansible packages.

  • Use Ansible to install and configure project website, taking into account variances between the linux distributions of Nginx on both CentOS and Ubuntu.

  • Use Jinja2 templates to customise the website.

Let's first create our ansible config file ansible.cfg:

[defaults]
inventory = hosts
host_key_checking = False

Next our group vars for centos and ubuntu hosts:

group_vars/centos:

---
ansible_user: root
...

group_vars/ubuntu:

---
ansible_user: root
...

Next our host file hosts:

[control]
ubuntu-c

[centos]
centos[1:3]

[ubuntu]
ubuntu[1:3]

[linux:children]
centos
ubuntu

Next our playbook itself for installing EPEL on CentOS hosts:

---
# YAML documents begin with the document separator ---

# The minus in YAML this indicates a list item.  The playbook contains a list
# of plays, with each play being a dictionary
-

  # Hosts: where our play will run and options it will run with
  hosts: linux

  # Vars: variables that will apply to the play, on all target systems

  # Tasks: the list of tasks that will be executed within the play, this section
  # can also be used for pre and post tasks
  tasks:
    - name: Install EPEL
      yum:
        name: epel-release
        update_cache: yes
        state: latest
      when: ansible_distribution == 'CentOS'

  # Handlers: the list of handlers that are executed as a notify key from a task

# Three dots indicate the end of a YAML document
...

Now we can execute the playbook:

$ ansible-playbook nginx_playbook.yaml 

PLAY [linux] *****************************************************************************************************************

TASK [Gathering Facts] ******************************************************************************************************************************
ok: [centos2]
ok: [centos1]
ok: [centos3]
ok: [ubuntu1]
ok: [ubuntu2]
ok: [ubuntu3]

TASK [Install EPEL] ******************************************************************************************************************************
skipping: [ubuntu1]
skipping: [ubuntu2]
skipping: [ubuntu3]
changed: [centos1]
changed: [centos3]
changed: [centos2]

PLAY RECAP *******************************************************************************************************************
centos1                    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
centos2                    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
centos3                    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
ubuntu1                    : ok=1    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
ubuntu2                    : ok=1    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
ubuntu3                    : ok=1    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0

Now let's install Nginx in all hosts by slightly modifying the playbook nginx_playbook.yaml:

---
# YAML documents begin with the document separator ---

# The minus in YAML this indicates a list item.  The playbook contains a list
# of plays, with each play being a dictionary
-

  # Hosts: where our play will run and options it will run with
  hosts: linux

  # Vars: variables that will apply to the play, on all target systems

  # Tasks: the list of tasks that will be executed within the play, this section
  # can also be used for pre and post tasks
  tasks:
    - name: Install EPEL
      yum:
        name: epel-release
        update_cache: yes
        state: latest
      when: ansible_distribution == 'CentOS'

    - name: Install Nginx CentOS
      yum:
        name: nginx
        update_cache: yes
        state: latest
      when: ansible_distribution == 'CentOS'

    - name: Install Nginx Ubuntu
      apt:
        name: nginx
        update_cache: yes
        state: latest
      when: ansible_distribution == 'Ubuntu'

  # Handlers: the list of handlers that are executed as a notify key from a task

# Three dots indicate the end of a YAML document
...

Once we execute it, the output should be something similar to below:

$ ansible-playbook nginx_playbook.yaml

PLAY RECAP *******************************************************************************************************************
centos1                    : ok=3    changed=2    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
centos2                    : ok=3    changed=2    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
centos3                    : ok=3    changed=2    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
ubuntu1                    : ok=2    changed=1    unreachable=0    failed=0    skipped=2    rescued=0    ignored=0   
ubuntu2                    : ok=2    changed=1    unreachable=0    failed=0    skipped=2    rescued=0    ignored=0   
ubuntu3                    : ok=2    changed=1    unreachable=0    failed=0    skipped=2    rescued=0    ignored=0

or we can simply use Nginx module for that like below in nginx_playbook.yaml:

---
# YAML documents begin with the document separator ---

# The minus in YAML this indicates a list item.  The playbook contains a list
# of plays, with each play being a dictionary
-

  # Hosts: where our play will run and options it will run with
  hosts: linux

  # Vars: variables that will apply to the play, on all target systems

  # Tasks: the list of tasks that will be executed within the play, this section
  # can also be used for pre and post tasks
  tasks:
    - name: Install EPEL
      yum:
        name: epel-release
        update_cache: yes
        state: latest
      when: ansible_distribution == 'CentOS'

    - name: Install Nginx
      package:
        name: nginx
        state: latest

  # Handlers: the list of handlers that are executed as a notify key from a task

# Three dots indicate the end of a YAML document
...

Next let's add a task to restart Nginx in our playbook:

---
# YAML documents begin with the document separator ---

# The minus in YAML this indicates a list item.  The playbook contains a list
# of plays, with each play being a dictionary
-

  # Hosts: where our play will run and options it will run with
  hosts: linux

  # Vars: variables that will apply to the play, on all target systems

  # Tasks: the list of tasks that will be executed within the play, this section
  # can also be used for pre and post tasks
  tasks:
    - name: Install EPEL
      yum:
        name: epel-release
        update_cache: yes
        state: latest
      when: ansible_distribution == 'CentOS'

    - name: Install Nginx
      package:
        name: nginx
        state: latest

    - name: Restart nginx
      service:
        name: nginx
        state: restarted

  # Handlers: the list of handlers that are executed as a notify key from a task

# Three dots indicate the end of a YAML document
...

Now let's had a handler to add a http health check to make sure Nginx is running:

---
# YAML documents begin with the document separator ---

# The minus in YAML this indicates a list item.  The playbook contains a list
# of plays, with each play being a dictionary
-

  # Hosts: where our play will run and options it will run with
  hosts: linux

  # Vars: variables that will apply to the play, on all target systems

  # Tasks: the list of tasks that will be executed within the play, this section
  # can also be used for pre and post tasks
  tasks:
    - name: Install EPEL
      yum:
        name: epel-release
        update_cache: yes
        state: latest
      when: ansible_distribution == 'CentOS'

    - name: Install Nginx
      package:
        name: nginx
        state: latest

    - name: Restart nginx
      service:
        name: nginx
        state: restarted
      notify: Check HTTP Service

  # Handlers: the list of handlers that are executed as a notify key from a task
  handlers:
    - name: Check HTTP Service
      uri:
        url: http://{{ ansible_default_ipv4.address }}
        status_code: 200 

# Three dots indicate the end of a YAML document
...

Next let's create group vars for HTML location for Nginx in different hosts, and create a jinja template for HTML.

First let's nodify the playbook to deploy the HTML file inside Nginx:

---
# YAML documents begin with the document separator ---

# The minus in YAML this indicates a list item.  The playbook contains a list
# of plays, with each play being a dictionary
-

  # Hosts: where our play will run and options it will run with
  hosts: linux

  # Vars: variables that will apply to the play, on all target systems

  # Tasks: the list of tasks that will be executed within the play, this section
  # can also be used for pre and post tasks
  tasks:
    - name: Install EPEL
      yum:
        name: epel-release
        update_cache: yes
        state: latest
      when: ansible_distribution == 'CentOS'

    - name: Install Nginx
      package:
        name: nginx
        state: latest

    - name: Restart nginx
      service:
        name: nginx
        state: restarted
      notify: Check HTTP Service

    - name: Template index.html-base.j2 to index.html on target
      template:
        src: index.html-base.j2
        dest: "{{ nginx_root_location }}/index.html"
        mode: 0644

  # Handlers: the list of handlers that are executed as a notify key from a task
  handlers:
    - name: Check HTTP Service
      uri:
        url: http://{{ ansible_default_ipv4.address }}
        status_code: 200 

# Three dots indicate the end of a YAML document
...

Next our group vars for centos and ubuntu hosts:

group_vars/centos:

---
ansible_user: root
nginx_root_location: /usr/share/nginx/html
...

group_vars/ubuntu:

---
ansible_user: root
nginx_root_location: /var/www/html
...

Now let's add the ansible_managed variable in the ansible.cfg:

[defaults]
inventory = hosts
host_key_checking = False
ansible_managed = Managed by Ansible - file:{file} - host:{host} - uid:{uid}

Now we can use the ansible_managed variable inside any of our templates.

Now let's load out variables in the playbook.

---
# YAML documents begin with the document separator ---

# The minus in YAML this indicates a list item.  The playbook contains a list
# of plays, with each play being a dictionary
-

  # Hosts: where our play will run and options it will run with
  hosts: linux

  # Vars: variables that will apply to the play, on all target systems
  vars_files:
    - vars/logos.yaml

  # Tasks: the list of tasks that will be executed within the play, this section
  # can also be used for pre and post tasks
  tasks:
    - name: Install EPEL
      yum:
        name: epel-release
        update_cache: yes
        state: latest
      when: ansible_distribution == 'CentOS'

    - name: Install Nginx
      package:
        name: nginx
        state: latest

    - name: Restart nginx
      service:
        name: nginx
        state: restarted
      notify: Check HTTP Service

    - name: Template index.html-logos.j2 to index.html on target
      template:
        src: index.html-logos.j2
        dest: "{{ nginx_root_location }}/index.html"
        mode: 0644

  # Handlers: the list of handlers that are executed as a notify key from a task
  handlers:
    - name: Check HTTP Service
      uri:
        url: http://{{ ansible_default_ipv4.address }}
        status_code: 200 

# Three dots indicate the end of a YAML document
...

Add unarchive task in the playbook to unarchive the code of our hidden game.

    - name: Unarchive playbook stacker game
      unarchive:
        src: playbook_stacker.zip
        dest: "{{ nginx_root_location }}"
        mode: 0755

Last updated