Ansible in depth · Lesson 2 · 30 min

Roles & collections

Your playbook sets up a web server. Soon you'll want the same web server setup in another project, plus a database setup, plus a monitoring agent. Copy-pasting tasks between playbooks is how bugs get fixed in one place and not the other. A role packages everything for one job (tasks, handlers, templates, defaults) into a folder any playbook can use with one line. Collections are how roles and modules are shared with the world.

You will learn

  • The standard role layout, made with ansible-galaxy role init
  • Turning a playbook into a role, and the TASK [role : name] output
  • defaults/ (easy to override) vs vars/ (hard to override)
  • Collections and FQCNs: ansible.builtin., ansible.posix., community.general.
  • ansible-doc, ansible-galaxy collection list and requirements.yml

What's in a role

ansible-galaxy role init --init-path roles web
roles/web/
├── defaults/main.yml    default values: the LOWEST priority, meant to be overridden
├── files/               plain files for the copy module
├── handlers/main.yml    handlers (Restart Apache)
├── meta/main.yml        author, license, and dependencies on other roles
├── tasks/main.yml       the tasks: a plain LIST, no hosts: or play around it
├── templates/           .j2 templates. src: index.html.j2 is found here automatically
├── tests/               a tiny test playbook
├── vars/main.yml        internal variables: high priority, not meant to be changed
└── README.md            what it does, and which variables you can set

Only tasks/main.yml is required. Delete the folders you don't use.

Playbook → role

Your whole playbook shrinks to this:

---
- name: Set up the web servers
  hosts: web
  become: true
  roles:
    - web

Ansible finds roles/web next to the playbook (or in ~/.ansible/roles and /etc/ansible/roles), runs its tasks first, then any tasks: in the play. The output labels them so you know where each task came from: TASK [web : Install Apache].

defaults vs vars

defaults/main.ymlvars/main.yml
PriorityLowest of all: group_vars, host_vars and play vars all beat itHigh: beats group_vars and host_vars
ForSettings the user of the role is meant to change: site_title: "Welcome"Internal constants the role needs, like a list of package names

Put almost everything in defaults, and write them down in the role's README. That list is the role's “settings menu”.

Collections and FQCNs

Modules come in collections, named namespace.collection. The full name of a module is its FQCN (fully qualified collection name):

FQCNComes with
ansible.builtin.template, .package, .service…ansible-core: always there
ansible.posix.firewalld, .authorized_keythe ansible package, or ansible-galaxy collection install ansible.posix
community.general.ufw, containers.podman.podman_container, amazon.aws.ec2_instancethe same, thousands of modules

Short names (template:) still work, but the FQCN is unambiguous, so it's what linters ask for.

ansible-galaxy collection list           # what's installed
ansible-doc ansible.builtin.template     # a module's manual, offline
ansible-galaxy collection install -r requirements.yml   # what a project needs (internet)
requirements.yml
collections:
  - name: ansible.posix
    version: ">=1.5.0"
  - name: community.general

Check requirements.yml into git, so a new teammate (or your CI pipeline) gets exactly the same collections.

Practice: turn the playbook into a role 🧱

The project is where the last lesson ended. Make a web role, move the tasks, handlers and template into it, and slim site.yml down to five lines. The ready-made pieces are in examples/role/.

Quick check

1. A role's defaults/main.yml says site_title: "Welcome", and group_vars/web.yml says "CHT Tickets". Which wins?

2. What goes in a role's tasks/main.yml?

3. What does ansible.posix.firewalld tell you that firewalld doesn't?

Finished the missions and the quiz? Mark it done to track your progress.