Ansible structure layout – the best approach

This is called Ansible structure layout – the best approach that we used to use it as a template for our projects. This may be not the best but you can customized it as to fit your own.

Directory Layout

The top level of the directory would contain files and directories like so:             # inventory file for production servers
stage.ini                 # inventory file for stage environment

   group1                 # here we assign variables to particular groups
   group2                 # ""
   hostname1              # if systems need specific vars, put them here
   hostname2              # ""

site.yml                  # master playbook
webservers.yml            # playbook for webserver tier
dbservers.yml             # playbook for dbserver tier

roles/{ common, nginx, php7.1,...}

How to Arrange Inventory, Stage vs Production

  • production.ini: contains the inventory of all production hosts
  • stage.ini: contains the inventory of all staging hosts

It is suggested that you define groups based on the purpose of the host (roles) and also geography or data center location (if applicable):

# file: production





# webservers in all geos

# dbservers in all geos

# everything in the atlanta geo

# everything in the boston geo

Group And Host Variables

We can also assign variables to all hosts in a group or specific group or specific hosts. Let’s set those now:

# file: group_vars/atlanta
# file: group_vars/webservers
apacheMaxRequestsPerChild: 3000
apacheMaxClients: 900

If we had any default values or values that were universally true, we would put them in a file called group_vars/all:

# file: group_vars/all

We can define specific hardware variance in systems in a host_vars file, but avoid doing this unless you need to:

# file: host_vars/
foo_agent_port: 86
bar_agent_port: 99

Playbooks Are Separated By Role

Playbook webservers.yml is used for all hosts in group webservers with roles common, nginx

# file: webservers.yml
- hosts: webservers
    - common
    - nginx

Task And Handler Organization For A Role

Below is an example tasks file that explains how a role works. Our common role here just sets up NTP, but it could do more if we wanted:

# file: roles/common/tasks/main.yml

- name: be sure ntp is installed
  yum: pkg=ntp state=installed
  tags: ntp

- name: be sure ntp is configured
  template: src=ntp.conf.j2 dest=/etc/ntp.conf
    - restart ntpd
  tags: ntp

- name: be sure ntpd is running and enabled
  service: name=ntpd state=running enabled=yes
  tags: ntp

Here is an example handlers file. As a review, handlers are only fired when certain tasks report changes and are run at the end of each play:

# file: roles/common/handlers/main.yml
- name: restart ntpd
  service: name=ntpd state=restarted

Let’s run your playbook

What about just reconfiguring NTP on everything? Easy.:

ansible-playbook -i production webserver.yml --tags ntp

What about just reconfiguring my webservers?:

ansible-playbook -i production webservers.yml

What about just my webservers in Boston?:

ansible-playbook -i production webservers.yml --limit boston

What about just the first 10, and then the next 10?:

ansible-playbook -i production webservers.yml --limit boston[0-10]
ansible-playbook -i production webservers.yml --limit boston[10-20]

And of course, just basic ad-hoc stuff is also possible.:

ansible boston -i production -m ping
ansible boston -i production -m command -a '/sbin/reboot'

Stage vs Production

As also mentioned above, a good way to keep your stage (or testing) and production environments separate is to use a separate inventory file for stage and production. This way you pick with -i what you are targeting. Keeping them all in one file can lead to surprises!

Also published on Medium.

Leave a Reply

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