skip to content

What is an Ansible collection, how does it relate to roles, and what does a fully qualified name such as community.general.timezone refer to?

level: middleimportance: should knowfreq 50%

answer

  1. engine and content ship separately now
  2. namespace dot collection dot thing
  3. packaging unit, not an organising unit
  4. roles can live inside one
  5. short names resolve through a search path

basics

~20 s

A collection is Ansible's packaging and distribution unit: a namespace.name bundle of modules, plugins, roles and playbooks. Content inside it is addressed by fully qualified collection name, such as community.general.timezone, and installed with ansible-galaxy collection install.

solid answer

~40 s

Since the 2.10 split, `ansible-core` ships only a small built-in set of modules and everything else lives in collections. A collection is a versioned package identified by `namespace.name` - `community.general`, `amazon.aws`, `ansible.posix` - containing `plugins/modules`, other plugin types, `roles/` and `playbooks/`, described by a `galaxy.yml`. Content is referenced by its fully qualified collection name: `community.general.timezone` means the `timezone` module in the `community.general` collection, and `ansible.builtin.copy` is the core `copy` module. Roles and collections are not competitors - a collection is the shipping container and a role can be one of the things inside it, referenced as `namespace.name.rolename`. You install collections with `ansible-galaxy collection install`, usually from a pinned `requirements.yml`. Writing FQCNs everywhere is now standard practice because short names resolve through a search path and can silently bind to the wrong module.

code

yaml · 10 lines
yaml
# requirements.yml
collections:
  - name: community.general
    version: "8.6.1"
  - name: amazon.aws
    version: "7.5.0"

roles:
  - src: geerlingguy.nginx
    version: "3.1.4"

go deeper

for a junior

Be able to read an FQCN - namespace, collection, then the module or role name - and know that collections are installed with ansible-galaxy collection install rather than pip.

for a middle

Explain the 2.10 split between ansible-core and content, what a collection contains, and that a collection is a distribution package that may itself ship roles addressed as namespace.collection.rolename.

for a senior

Diagnose the module-not-found upgrade case, argue for FQCNs on determinism grounds, and say when you would publish content as a collection rather than a standalone role.

for a principal

Decide where shared content lives for the organisation: namespaces you own, public Galaxy versus a private hub, and the release and versioning policy for internal collections consumed by many teams.

## Why collections exist Up to Ansible 2.9 the project shipped as one enormous repository: thousands of modules for every cloud, network vendor and database, all released on the engine's schedule. A fix to a single cloud module waited for the next Ansible release. The 2.10 split separated the **engine** (`ansible-core`) from the **content** (collections), so each collection versions and releases independently. The `ansible` package on PyPI is a curated bundle of `ansible-core` plus a large set of collections; installing `ansible-core` alone gives you only `ansible.builtin`. ## What is in a collection A collection is a directory tree with a `galaxy.yml` manifest and roughly this shape: ``` my_namespace/my_collection/ galaxy.yml plugins/ modules/ lookup/ filter/ roles/ playbooks/ docs/ ``` So it can carry modules, any plugin type, complete roles, and even playbooks. `ansible-galaxy collection init my_namespace.my_collection` scaffolds it, `ansible-galaxy collection build` produces a tarball, and `ansible-galaxy collection publish` pushes it to Galaxy or a private hub. ## Roles versus collections They answer different questions. A **role** is a unit of *organisation* inside your automation - a directory layout for one coherent piece of configuration. A **collection** is a unit of *distribution* - a versioned, namespaced package. The relationship is containment: a collection may ship zero, one or many roles, addressed as `namespace.collection.rolename`: ```yaml - hosts: web tasks: - name: Apply a role that ships inside a collection ansible.builtin.import_role: name: my_namespace.my_collection.webserver ``` Standalone roles installed from Galaxy still work - `ansible-galaxy role install geerlingguy.nginx` - and remain common. But new shared content, especially anything that includes custom modules or plugins, is published as a collection, because a collection can version its plugins alongside its roles while a standalone role's `library/` directory cannot be depended on cleanly. ## Fully qualified collection names An FQCN has three dot-separated parts: namespace, collection, content name. - `ansible.builtin.copy` - the `copy` module built into `ansible-core`. - `community.general.timezone` - the `timezone` module from `community.general`. - `amazon.aws.ec2_instance` - the EC2 instance module from `amazon.aws`. Short names such as `copy:` still resolve, through a search path that prefers `ansible.builtin` and then any collections listed in the play's `collections:` keyword. The reason to write FQCNs anyway is determinism: a short name's meaning depends on what is installed and on the search order, so the same playbook can bind a different module on a different control node. Linting tools flag bare module names for exactly this reason, and FQCNs also make the dependency obvious to a reader - `amazon.aws.ec2_instance` tells you which collection must be installed, `ec2_instance` does not. ## Installing and declaring ```yaml # requirements.yml collections: - name: community.general version: "8.6.1" - name: amazon.aws version: "7.5.0" roles: - src: geerlingguy.nginx version: "3.1.4" ``` `ansible-galaxy collection install -r requirements.yml` installs the collections; `ansible-galaxy role install -r requirements.yml` installs the standalone roles. Collections resolve to a collections path (project-local with `-p`, otherwise a user or system path); roles resolve to `roles_path`. A collection may also declare its own dependencies on other collections in `galaxy.yml`, which `ansible-galaxy` resolves at install time. ## What interviewers are checking That you know the ecosystem you are working in is post-split: that a missing module is usually a missing *collection* rather than a broken Ansible, that `requirements.yml` is where dependencies are declared, and that FQCNs are not verbosity for its own sake. A candidate who still describes Ansible as "one big install with every module" is describing 2.9.

  • A playbook that worked on Ansible 2.9 now fails with a module-not-found error. What is the likely cause?
    The module moved into a collection during the 2.10 split and the control node has only `ansible-core`, or the curated bundle installed does not include it. Find the owning collection, add it to `requirements.yml` with a pinned version, install it with `ansible-galaxy collection install -r`, and switch the task to the fully qualified name so the dependency is visible in the code.
  • Why write ansible.builtin.copy rather than just copy?
    Short names resolve through a search path that depends on what is installed and on the play's `collections:` keyword, so the same task can bind a different module on a different control node. The FQCN removes that ambiguity and documents which collection a reader needs installed. Linters flag bare module names for this reason.
  • When would you publish a collection instead of a standalone Galaxy role?
    Whenever the content includes custom modules, filters or lookups, or when several roles share code and should be versioned together. A collection versions plugins and roles as one artifact with a namespace, which a standalone role's `library/` directory cannot do cleanly. A single self-contained role with no plugins is still fine to publish on its own.

saying these in an interview costs you the question

  • Says collections replaced roles entirely
  • Thinks every module still ships with ansible-core
  • Cannot parse namespace.collection.content in an FQCN
  • Installs collections with pip install
  • Treats FQCNs as optional verbosity with no benefit

context