Where can a variable be defined in Ansible, and which definition wins if the same name is set in several places?
From lowest to highest priority: group variables in the inventory, group_vars files, host variables in the inventory, host_vars files, gathered facts, play variables (vars, vars_files), task variables, and extra variables on the command line. The higher one overrides; the rule of thumb is "more specific beats more general".
* Higher rungs override lower ones; extra vars (-e) always win. *
The ladder follows two ideas:
- Narrow beats broad. A value for one host is more specific than a value for a whole group, and a value for one task is more specific than one for the whole play. So host variables beat group variables, and task variables beat play variables.
- Closer to the run beats further away. The inventory describes the environment; the playbook describes this job; the command line describes this one run. That is why
--extra-vars/-eoverrides everything: it is the operator saying "for this run, use this value".
In short: inventory variables < playbook variables < extra variables.
Precedence can be used on purpose (a group default that one special host overrides). Where you don't need that, give variables unique names, so there's never a question of which definition wins.
Go deeper:
Variable precedence: where should I put a variable? (official docs) — the full 22-step list, of which this is a simplified version.
Controlling how Ansible behaves: precedence rules (official docs) — how variables fit in with config settings and command-line options.