CrackOps
Interview PrepTracksLinuxAWS LabSoonInterview RoomSoon
Sign inStart free
CrackOps

Interview prep for the people who keep production up.

[email protected]
ProductInterview PrepTracksDashboardInterview Room
RolesDevOpsSREPlatformCloud
CompanyAboutContactPrivacyTerms
© CrackOps
Linux / IaC & Config Management / ansible-playbook

ansible-playbook

Run Ansible playbooks to configure servers

Intermediateansibleconfig-mgmtautomation

ansible-playbook runs a playbook: YAML plays that map groups of hosts to ordered tasks, with variables, templates, handlers and tags. The output shows every task per host and ends with the PLAY RECAP, the line you read first.

Syntaxansible-playbook PLAYBOOK.yml [-i INV] [--limit HOSTS] [--tags T] [-e 'k=v'] [--check] [--diff] [--syntax-check] [--list-tasks] [-v]

Watch it run

A teammate wrote site.yml. Check it parses and see exactly which tasks it would run, without touching a server.

devops@devops-lab: ~/ansible — zsh — 96×28
➜ ~/ansible
Step 1 of 2
ansible-playbook site.yml --syntax-check

Only parsing: YAML structure, known keywords, includes. It doesn't check that variables exist or modules work on the hosts.

Anatomy of a command

$
commandansible-playbook

Runs every play in the file, in order, against its hosts.

How it works

ansible-playbook parses the YAML and builds plays from it. For each play it resolves hosts from the inventory and merges variables from many sources by precedence (role defaults lowest, then inventory group_vars and host_vars, play vars, facts, and -e highest). Unless gather_facts is false it first runs setup on every host. Then, with the default linear strategy, it runs task 1 on all hosts (up to forks in parallel), waits for all of them, then task 2, and so on. Each task is a module executed over SSH as in ad-hoc mode; Jinja2 templates and variables are rendered on the control node. A host that fails or is unreachable is removed from the rest of the play while the others continue. Tasks that report changed can notify handlers, which run once at the end of the play (e.g. restart nginx only if its config changed). Finally PLAY RECAP sums ok, changed, unreachable, failed, skipped, rescued and ignored per host, and the exit code is non-zero if any host failed (2) or was unreachable (4).

The control node renders each task, pushes a small Python module to every host over SSH in parallel, and collects JSON results into the recap.

parse YAMLhosts + varsSSH + moduleSSH + moduleSSHsite.ymlplays + tasksInventoryweb: web1-3Control nodeansible-playbookweb110.0.1.23web210.0.2.41web310.0.3.77PLAY RECAPper host totals
1/7
Parse the playbook

ansible-playbook reads site.yml: one play for hosts: web with three tasks and a handler. Nothing is installed on the servers; everything starts here.

← → to step

Options you'll actually use

-i INVInventory (or from ansible.cfg)
-l, --limitRestrict to these hosts or groups
-t, --tags / --skip-tagsRun only, or skip, tagged tasks
-e 'k=v' / -e @file.ymlExtra variables (highest precedence)
-C, --checkDry run (modules that support check mode)
-D, --diffShow file and template differences
--syntax-checkParse the playbook only
--list-tasks / --list-hostsShow what would run, run nothing
--start-at-task NAMEResume a run from a given task
-b / -KBecome root / ask for the sudo password
-f NForks (parallel hosts)
-v ... -vvvvVerbosity: results, then connection debugging

Common mistakes

Using shell/command tasks for everything ('- shell: systemctl restart nginx')

They always report changed, break idempotence and can't run in check mode.

Use modules (ansible.builtin.service, apt, template) and a handler for restarts
Restarting a service as a normal task after the config task

It restarts on every run, even when nothing changed, causing needless blips.

notify: Restart nginx from the config task, with a handler
Running a new playbook against all of prod at once

A bad task breaks every server simultaneously.

--check --diff first, then --limit one host, then serial: 25% in the play for rolling batches
Ignoring 'changed' on runs that should be no-ops

Constant changes hide real drift and mean the task isn't idempotent.

Fix the task (changed_when, creates, proper modules) until a second run shows changed=0

Interview questions

Practice

Try these on a Linux machine of your own. Each task has a hint and a solution.

  1. 1

    Write the command that runs only the tasks tagged deploy from site.yml, on the db group only, with version=2.5.0.

  2. 2

    Read this RECAP line and say what happened: 'web2 : ok=6 changed=0 unreachable=0 failed=1 skipped=2 rescued=1 ignored=0'

  3. 3

    Write a playbook in ~/app/motd.yml that writes 'Managed by Ansible' to /etc/motd on all hosts, then check its syntax if ansible is installed (otherwise check the YAML parses with python3).

Related commands

ansibleRun one task across many servers (ad-hoc)puppetEnforce server configuration with PuppetsshLog in to remote servers securelyterraform applyCreate, change or destroy real infrastructure
PreviousansibleNextpuppet
Linux / IaC & Config Management / ansible-playbook

ansible-playbook

Run Ansible playbooks to configure servers

Intermediateansibleconfig-mgmtautomation

ansible-playbook runs a playbook: YAML plays that map groups of hosts to ordered tasks, with variables, templates, handlers and tags. The output shows every task per host and ends with the PLAY RECAP, the line you read first.

Syntaxansible-playbook PLAYBOOK.yml [-i INV] [--limit HOSTS] [--tags T] [-e 'k=v'] [--check] [--diff] [--syntax-check] [--list-tasks] [-v]

Watch it run

A teammate wrote site.yml. Check it parses and see exactly which tasks it would run, without touching a server.

devops@devops-lab: ~/ansible — zsh — 96×28
➜ ~/ansible
Step 1 of 2
ansible-playbook site.yml --syntax-check

Only parsing: YAML structure, known keywords, includes. It doesn't check that variables exist or modules work on the hosts.

Anatomy of a command

$
commandansible-playbook

Runs every play in the file, in order, against its hosts.

How it works

ansible-playbook parses the YAML and builds plays from it. For each play it resolves hosts from the inventory and merges variables from many sources by precedence (role defaults lowest, then inventory group_vars and host_vars, play vars, facts, and -e highest). Unless gather_facts is false it first runs setup on every host. Then, with the default linear strategy, it runs task 1 on all hosts (up to forks in parallel), waits for all of them, then task 2, and so on. Each task is a module executed over SSH as in ad-hoc mode; Jinja2 templates and variables are rendered on the control node. A host that fails or is unreachable is removed from the rest of the play while the others continue. Tasks that report changed can notify handlers, which run once at the end of the play (e.g. restart nginx only if its config changed). Finally PLAY RECAP sums ok, changed, unreachable, failed, skipped, rescued and ignored per host, and the exit code is non-zero if any host failed (2) or was unreachable (4).

The control node renders each task, pushes a small Python module to every host over SSH in parallel, and collects JSON results into the recap.

parse YAMLhosts + varsSSH + moduleSSH + moduleSSHsite.ymlplays + tasksInventoryweb: web1-3Control nodeansible-playbookweb110.0.1.23web210.0.2.41web310.0.3.77PLAY RECAPper host totals
1/7
Parse the playbook

ansible-playbook reads site.yml: one play for hosts: web with three tasks and a handler. Nothing is installed on the servers; everything starts here.

← → to step

Options you'll actually use

-i INVInventory (or from ansible.cfg)
-l, --limitRestrict to these hosts or groups
-t, --tags / --skip-tagsRun only, or skip, tagged tasks
-e 'k=v' / -e @file.ymlExtra variables (highest precedence)
-C, --checkDry run (modules that support check mode)
-D, --diffShow file and template differences
--syntax-checkParse the playbook only
--list-tasks / --list-hostsShow what would run, run nothing
--start-at-task NAMEResume a run from a given task
-b / -KBecome root / ask for the sudo password
-f NForks (parallel hosts)
-v ... -vvvvVerbosity: results, then connection debugging

Common mistakes

Using shell/command tasks for everything ('- shell: systemctl restart nginx')

They always report changed, break idempotence and can't run in check mode.

Use modules (ansible.builtin.service, apt, template) and a handler for restarts
Restarting a service as a normal task after the config task

It restarts on every run, even when nothing changed, causing needless blips.

notify: Restart nginx from the config task, with a handler
Running a new playbook against all of prod at once

A bad task breaks every server simultaneously.

--check --diff first, then --limit one host, then serial: 25% in the play for rolling batches
Ignoring 'changed' on runs that should be no-ops

Constant changes hide real drift and mean the task isn't idempotent.

Fix the task (changed_when, creates, proper modules) until a second run shows changed=0

Interview questions

Practice

Try these on a Linux machine of your own. Each task has a hint and a solution.

  1. 1

    Write the command that runs only the tasks tagged deploy from site.yml, on the db group only, with version=2.5.0.

  2. 2

    Read this RECAP line and say what happened: 'web2 : ok=6 changed=0 unreachable=0 failed=1 skipped=2 rescued=1 ignored=0'

  3. 3

    Write a playbook in ~/app/motd.yml that writes 'Managed by Ansible' to /etc/motd on all hosts, then check its syntax if ansible is installed (otherwise check the YAML parses with python3).

Related commands

ansibleRun one task across many servers (ad-hoc)puppetEnforce server configuration with PuppetsshLog in to remote servers securelyterraform applyCreate, change or destroy real infrastructure
PreviousansibleNextpuppet