Ansible OEL 8 DevOps · OEL 8 · Roles

AnsibleCollections — FQCN and Building Your Own

What a collection is, how it differs from a role, why fully-qualified collection names are now mandatory, the most useful community collections for database work, and how to package a collection of your own.

A role is one bundle of automation (tasks + handlers + templates). A collection is a versioned tarball that bundles many roles, modules, plugins, and docs together under a namespace.

RoleCollection
Containstasks, handlers, vars, templatesroles + modules + plugins + docs
Naminggeerlingguy.mysqlcommunity.mysql
Distributiongit repo via Galaxyversioned tarball via Galaxy or Hub
Modules?Custom modules in library/First-class — that's the main use case
FQCN: namespace.collection.module community mysql mysql_db namespace collection module A collection bundles: Modules mysql_db mysql_user mysql_query Roles install_mysql configure_mysql create_users Plugins filters lookups callbacks Docs README CHANGELOG One collection · many roles + modules · single versioned tarball

Since Ansible 2.10, every module ideally lives inside a collection. The full name is namespace.collection.module — for example, the copy module is ansible.builtin.copy, and the MySQL DB module is community.mysql.mysql_db.

YAML — FQCN in playbooks
---
- hosts: databases
  tasks:
    # FQCN — preferred for ALL modules (clearer, future-proof)
    - name: Install MySQL
      ansible.builtin.dnf:
        name: mysql-server
        state: present

    - name: Create database
      community.mysql.mysql_db:
        name: myapp
        state: present

    - name: Open firewall
      ansible.posix.firewalld:
        port: 3306/tcp
        state: enabled

    # Short form still works for ansible.builtin (deprecated for community.*)
    - name: Render config
      template:                # ← same as ansible.builtin.template
        src: my.cnf.j2
        dest: /etc/my.cnf
⚠ Warning: ansible-lint warns on bare module names from non-builtin collections. New code should always use FQCN. The lint rule is fqcn[action]; you can suppress per-task with a noqa comment but better to just spell it out.
BASH — collection install commands
# Install latest version of a single collection
ansible-galaxy collection install community.mysql

# A specific version
ansible-galaxy collection install community.mysql:3.10.0

# Into a project-local path
ansible-galaxy collection install community.mysql -p ./collections

# List installed collections
ansible-galaxy collection list

# Update one
ansible-galaxy collection install community.mysql --upgrade

The same requirements.yml can pin both roles and collections — they go in separate top-level keys:

YAML — requirements.yml with collections
---
collections:
  - name: community.mysql
    version: ">=3.10.0,<4.0.0"     # version range, not exact pin
  - name: community.postgresql
    version: 3.6.0
  - name: ansible.posix
    version: 1.5.4
  - name: community.general
  # private from a git repo
  - name: company.platform
    source: git+https://gitlab.example.com/platform/ansible-collection.git
    version: v0.4.0

roles:
  - name: geerlingguy.docker
    version: 7.4.0
BASH — install both
# Installs both collections AND roles in one command
ansible-galaxy install -r requirements.yml

# To install ONLY collections:
ansible-galaxy collection install -r requirements.yml -p ./collections

# To install ONLY roles:
ansible-galaxy role install -r requirements.yml -p ./roles
CollectionWhat it gives you
community.mysqlmysql_db, mysql_user, mysql_query, mysql_replication, mysql_variables, mysql_info
community.postgresql30+ modules covering DBs, users, schemas, extensions, replication, pg_hba, tablespaces
community.mongodbReplica sets, sharded clusters, users, indexes, balancer state
community.generalThe catch-all — archive, ini_file, cron, htpasswd, hundreds more
ansible.posixfirewalld, mount, sysctl, selinux, authorized_key
community.cryptoOpenSSL keys, certs, CSRs, x509 manipulation

Collections are the right unit when you want to ship multiple related roles + custom modules together. Skeleton with one command:

BASH — collection skeleton
# Create a collection skeleton
ansible-galaxy collection init company.platform
cd company/platform

# Layout
ls -la
# galaxy.yml         ← collection metadata (name, version, deps)
# README.md
# docs/
# meta/
# plugins/
#   modules/         ← custom modules go here
#   filter/          ← custom filters
#   lookup/
# roles/             ← roles bundled with the collection
#   common/
#   mysql/
#   proxysql/
# playbooks/         ← optional bundled playbooks
YAML — galaxy.yml metadata
---
namespace: company
name: platform
version: 1.0.0
readme: README.md
authors:
  - Platform Team <platform@example.com>
description: Internal platform automation collection
license:
  - MIT
tags:
  - infrastructure
  - mysql
  - proxysql
dependencies:
  community.mysql: ">=3.10.0"
  ansible.posix: ">=1.5.0"
repository: https://gitlab.example.com/platform/ansible-collection-platform
BASH — build & publish a collection
# Build a tarball
ansible-galaxy collection build
# → company-platform-1.0.0.tar.gz

# Publish to a hub
ansible-galaxy collection publish \
  company-platform-1.0.0.tar.gz \
  --server my_hub \
  --token $MY_HUB_TOKEN

# Or distribute via git — others install with:
# ansible-galaxy collection install \
#   git+https://gitlab.example.com/platform/ansible-collection-platform.git,v1.0.0
✅ Tip: Start with roles. Move to collections only when you have 4-5 related roles plus custom modules / filters that genuinely belong together. The community.mysql collection is a good shape to imitate: many MySQL modules + a couple of MySQL roles + reusable filters, all versioned together.