← All TILs · ansible

--limit in practice: every play, run_once per batch, and the facts of hosts left out

ansible - 2026-10-03

Twelfth entry in the Ansible inventory from scratch series. Item 11 covered host patterns, the expressions that choose hosts, and --limit, the option that keeps only the hosts of a run that also match another pattern. This entry is about what --limit does beyond choosing hosts: to a playbook with several plays, to tasks that run once, to what one host knows about another, and when it matches nothing. Everything below ran with ansible-core 2.21.4, on item 11's inventory without its extra sources: app holds app1, app2 and stg-app1, db holds db1 and stg-db1, and group_vars/ gives each environment's hosts an env variable.

--limit applies to every play

A playbook is a list of plays, each with its own hosts: pattern. The example's site.yml has two: one on db, then one on app. --limit narrows each of them, not just the first:

A skipped play doesn't stop the run. That's convenient for running part of a site playbook, and a trap when a later play counts on something an earlier one did on hosts the limit left out. ansible-playbook site.yml --limit app --list-hosts shows each play's hosts before anything runs: hosts (0) for the db play.

run_once runs once per batch

serial: 2 on a play makes Ansible run it on two hosts at a time: the whole play on the first batch, then the whole play on the next. run_once: true on a task runs it on one host only, and the Ansible docs, Controlling playbook execution, say which: "the first host in your batch of hosts". With serial, that's once per batch:

So --limit can change how many times a run_once task runs, because it changes the batches. A task that must run exactly once in a play with serial belongs in a play of its own.

What a host outside the limit still has

hostvars is the variable that holds every host's variables, so a task on app1 can read hostvars.db1.env. The example's facts.yml gathers facts on db in a first play, then prints, from the app play, what app1 knows about db1:

Without --limit --limit app
ansible_limit not set app
groups.db db1 stg-db1 db1 stg-db1
hostvars.db1.env, an inventory variable prod prod
hostvars.db1.ansible_facts.system, a fact Linux missing

Two ways to get the facts back

When the limit matches nothing

The example

The series' companion repository, abdelhousni/ansible-inventory-series, holds the inventory and the four playbooks. run.sh runs each case above and prints the debug messages, warnings and skipped plays; its ansible.cfg sets forks = 1, one host at a time, so the output comes in the same order on every run. Its CI runs it on every push and compares the output with the expected one.

Sources

Created 2026-10-03T13:13:46+02:00 · Edit