How do Ansible Collections work, and how do they change role distribution?
Quick Answer
Collections bundle modules, plugins, roles, and playbooks under a namespace.collection format. They replace the old flat Galaxy role model with versioned, namespaced packages that declare dependencies in galaxy.yml and are installed via ansible-galaxy collection install.
Detailed Answer
Think of a software package manager like npm or pip. Before collections, Ansible modules were either bundled into one massive ansible package or shared as standalone roles on Galaxy with no namespace protection -- two roles could define the same module name and clash. Collections are like scoped packages: community.aws.ec2_instance and amazon.aws.ec2_instance are unambiguous, versioned, and installed separately. This brings the same dependency management discipline that developers expect from application package managers.
Ansible Collections use the namespace.collection_name format, where the namespace is usually an organization (community, amazon, cisco) and the collection name groups related content. A collection can contain plugins (modules, filters, lookups, connection plugins), roles, playbooks, and documentation in a standard folder structure. The galaxy.yml file at the collection root defines metadata including version, dependencies on other collections with version ranges, and supported Ansible versions. Collections are packaged as .tar.gz archives and installed into COLLECTIONS_PATH, which defaults to ~/.ansible/collections.
Under the hood, when a playbook references a module like community.aws.s3_bucket, Ansible's plugin loader searches the collections path for the community/aws collection, then looks for the s3_bucket module inside its plugins/modules directory. These fully qualified collection names (FQCNs) remove all ambiguity -- the old s3_bucket shorthand could match multiple collections, but community.aws.s3_bucket is exact. The ansible-galaxy collection install command reads requirements.yml, resolves the dependency tree across collections, downloads compatible versions, and installs them. Version constraints use semantic versioning ranges like >=2.0.0,<3.0.0.
At production scale, collection management becomes a supply chain concern. Organizations should keep a requirements.yml with pinned collection versions, use a private Automation Hub (from Red Hat's Ansible Automation Platform) or Artifactory as a gateway to control which collection versions enter production, and run collection installs in CI rather than relying on developer machines. When multiple collections declare overlapping dependencies with incompatible version ranges, ansible-galaxy will fail to resolve them -- architects need to audit transitive dependencies and sometimes pin intermediate collections by hand.
The sneaky gotcha is the migration from the monolithic ansible package (which included hundreds of modules) to ansible-core plus individual collections. When Ansible 2.10 split the package, many modules moved from built-in to collections like community.general, community.aws, or ansible.posix. Playbooks that used short module names without FQCNs may silently pick up the wrong module or break after upgrading to ansible-core 2.16+ because the module is no longer included. Architects should enforce FQCN usage in all playbooks and roles through ansible-lint rules and treat collection version updates with the same care as application dependency updates.