Ansible Architecture and Inventory
Ansible control node (where you run playbooks), managed nodes (target systems, require Python and SSH access), inventory (list of managed hosts). Inventory formats: INI (simple, grouped with [groupname]), YAML (hierarchical, children/vars blocks). Dynamic inventory: scripts or plugins that query external sources (AWS EC2, GCP, Foreman) and return JSON. Inventory variables: host_vars/hostname.yml (per-host), group_vars/groupname.yml (per-group). Variable precedence (highest to lowest): extra vars (-e), task vars, block vars, role vars, include_vars, set_fact, registered vars, play vars, host_vars, group_vars, inventory vars, role defaults. Ansible configuration: ansible.cfg searched in: environment variable ANSIBLE_CONFIG, ./ansible.cfg (current directory), ~/.ansible.cfg, /etc/ansible/ansible.cfg. Key settings: inventory, remote_user, become, become_method, host_key_checking, roles_path.
Playbooks, Modules, and Variables
Playbook structure: hosts (target inventory group), become (privilege escalation), vars, tasks (name + module + parameters), handlers (triggered by notify), pre_tasks, post_tasks, roles. YAML gotchas: indentation is significant (2 spaces standard), strings with colons need quotes, booleans are yes/no or true/false. Essential modules for RHCE: yum/dnf (package management), service (start/stop/enable), copy (files to managed nodes), template (Jinja2 templates), file (create/modify files and directories), user/group (user management), firewalld (firewall rules), nmcli (network configuration), lineinfile/blockinfile (edit config files), command/shell (run commands — avoid when a module exists). Jinja2 templating: {{ variable }} for variable substitution, {% if condition %} for conditionals, {% for item in list %} for loops. Filters: {{ var | default('fallback') }}, {{ list | join(',') }}, {{ string | upper }}. ansible_facts variables: ansible_hostname, ansible_os_family, ansible_default_ipv4.address.
Roles, Collections, and Galaxy
Role directory structure: tasks/main.yml (task list), handlers/main.yml, templates/ (Jinja2 .j2 files), files/ (static files for copy), vars/main.yml (high-precedence vars), defaults/main.yml (low-precedence defaults), meta/main.yml (dependencies, metadata). Create role with ansible-galaxy init rolename. Use roles in playbooks with roles: key or include_role/import_role tasks. Role dependencies in meta/main.yml.galaxy_info: automatically include prerequisite roles. Ansible Galaxy: community role repository. ansible-galaxy install namespace.rolename. Ansible Collections: packaging format for roles, modules, plugins, and playbooks. Install with ansible-galaxy collection install namespace.collection. Use FQCN (Fully Qualified Collection Name): ansible.builtin.yum, community.general.ufw.
Advanced Playbook Features and Troubleshooting
Conditionals: when: clause (evaluate Jinja2 expression — note: no {{ }} in when clauses). Loops: loop: (replaces with_items), with_items (legacy), with_dict, loop_control (label, index_var). Error handling: ignore_errors: yes, failed_when: (custom failure condition), block/rescue/always (try/catch/finally equivalent). Tags: tag tasks with tags: [configure, deploy] and run with --tags or skip with --skip-tags. Check mode (--check): dry run, shows what would change without making changes. Diff mode (--diff): shows file content differences. Useful combination: -CD for review before applying. Vault: ansible-vault encrypt file (encrypt at rest), ansible-vault create file (create encrypted), --ask-vault-pass or --vault-password-file at runtime. Encrypt individual variables with !vault | syntax. Troubleshooting: -v (verbose), -vvv (connection debug), -vvvv (full debug including SSH). Use ansible all -m ping to verify connectivity.