Files
best-practices/ansible.md
Paul O'Reilly 8aa400a5d4 distill: 49 best practices from 5 projects (2026-03-27..2026-04-05)
Add 37 new entries and update 7 existing entries across 13 topic files.
Major contributions from agent-runtimes (K8s secrets, CI, Docker gotchas),
cluster-bootstrap (ArgoCD SSA, etcd tuning, DB migrations, Compose networking),
and cluster-apps/octopus-deploy (Helm vs raw manifests, ArgoCD source types).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 01:10:07 +12:00

45 lines
2.7 KiB
Markdown

# Ansible
## Inventory and Execution
- Always pass `-i inventory.yml` explicitly or run from the directory containing `ansible.cfg`
- Playbooks that can't find inventory skip silently with no error — a common source of "it ran but nothing happened" confusion
- Variables that need customisation go in `inventory.yml` files, not scattered across role defaults
## Role Structure
- Roles follow standard structure: `tasks/main.yml`, `templates/*.j2`, `handlers/main.yml`
- Jinja2 templates have `.j2` extension and include a "managed by Ansible" header comment
## Template Safety
- **Never use placeholder values with `-e` for vars that template config files.** Using `-e "var=dummy"` will overwrite live configs with garbage. Either read real values, use `--skip-tags` to skip templating tasks, or restructure roles so sensitive templates are in a separate tag.
## Credential Safety
- Pass secrets via `@file` not `-e` on the command line — `-e "key=value"` exposes secrets in `ps` output
- Use temp files with `trap rm` cleanup: `-e "@${tmpfile}"`
## Module Gotchas
- `docker_compose_v2``state: restarted` is supported since community.docker 3.7.0. The old workaround (`recreate: always`) still works but is no longer necessary
- `ansible.builtin.unarchive` with `remote_src` and `extra_opts: --strip-components` is unreliable — use `get_url` + `command: tar` separately
- `get_url` won't re-download when the URL changes but the destination filename stays the same — use a version marker file to detect changes
## Service Restarts
- Some services (dnsmasq, etc.) need container restarts for config changes to take effect
- Ansible handlers handle this, but always verify the change took effect (e.g., `dig @<ip> <record> +short`)
## Docker Compose
- `network_mode: host` ignores `ports:` mappings — remove `ports:` to avoid warnings
## SOPS Vars Plugin Requires Running From ansible.cfg Directory
The `community.sops.sops` vars plugin is configured in `ansible.cfg`. Running `ansible-playbook` from a different directory (even with `-i /path/to/inventory.yml`) fails because the SOPS plugin isn't loaded, causing undefined variable errors for decrypted secrets. Always `cd` to the directory containing `ansible.cfg` before running playbooks that rely on SOPS-encrypted group_vars.
## Ansible file Task on Existing Directories Has Side Effects
An `ansible.builtin.file` task that ensures a directory exists (state: directory, owner/group/mode) will also change any pre-existing directory that doesn't exactly match, even if it belongs to a different service. In roles that manage multiple services, this can cause cross-service side effects. Scope directory tasks tightly with conditionals or use service-specific variable names.