unit 7 · Secrets & scale
Strategies, serial & delegation
Who runs what, when — and where
you may want to read 12 · Playbook anatomy first — but nothing is locked
tl;dr
- linear (default) marches every host through a task before the next starts; free lets each host race ahead.
- serial: 1 turns a play into a rolling update — the whole play finishes on one batch before the next begins.
- delegate_to runs a task on a different host; run_once runs it a single time for the whole play.
why it matters Rolling updates are how teams ship without downtime. When a colleague says "we use serial 1" or "drain it from the LB first", you need to picture what runs where, and in what order.
Lesson 12 gave you the top-down rule: tasks run in order. How that order
plays out across hosts is the strategy’s job. The default,
linear, makes every run a marching band: all hosts finish task 1 before
any host starts task 2. You’ll meet linear, free, and
host_pinned; only the first two matter in practice.
Within a task, forks — the ansible.cfg setting from lesson 6 — caps how many hosts are worked on at once. Twenty forks against a hundred hosts means waves of twenty. linear still holds the line until the last host finishes. Forks is a throughput ceiling; it never changes ordering.
strategy: free drops the lockstep. Each host runs its own task list as
fast as it can, never waiting for the others — fine for patching fleets
where hosts don’t care about each other:
- name: Patch the estate
hosts: all
strategy: free # each host races ahead independentlyhost_pinned is a stricter cousin of free — a host that starts the play
keeps its worker until it finishes. File the name; you’ll rarely see it.
serial: the rolling update
Linear has a gap. A play that restarts a service restarts it on every host in the same task: your whole web tier goes down together, briefly but completely. The fix is serial , a play-header keyword that batches hosts: the whole play finishes on one batch before the next begins:
- name: Deploy the new build
hosts: web
serial: 1 # also takes "25%", or a list like [1, 5, "100%"]
tasks:
- name: Update the app
ansible.builtin.package:
name: myapp
state: latestserial: 1 is one host at a time — safest, slowest, and the one you’ll
hear in standups. A percentage (serial: "25%") trades safety
for speed. The list form is a canary pattern: one host, then five, then
everyone. Each wave starts only because the last survived. If a whole
batch fails, the play aborts and the remaining batches never run.
Delegation: run it over there
Before touching a web host, the load balancer should stop sending it
traffic. But the play targets web hosts, not the LB. That’s delegation : delegate_to
executes one task on a different machine while the play keeps “thinking
about” the original host. Its sibling run_once runs a task once for
the whole play. Caveat: under serial, it fires once per batch, not once
overall:
- name: Pull this host out of the load balancer
ansible.builtin.command: lb-cli drain {{ inventory_hostname }}
delegate_to: lb01 # runs ON lb01, once per web host
- name: Tell the channel the deploy started
ansible.builtin.command: notify-chat "deploying web tier"
run_once: true # one execution for the whole playThree neighbours to recognise but not stop for. throttle caps how many
hosts run one specific task at once — a per-task forks. local_action is
an older shorthand for delegate_to: localhost. ansible.builtin.wait_for
pauses until a port or file is ready, classically used between “restart the
service” and “put the host back in the LB”.
Nobody expects you to design a rolling update this month — recognition is
the goal. When you open a deploy playbook, read the play header first:
hosts, serial, strategy tell you the blast radius before you read a
single task. And when someone says “we use serial 1”, you hear the cost:
twenty hosts, twenty full passes. That slowness is the feature.
at work, this sounds like
- “We use serial 1.”
- The deploy play is a rolling update — it runs to completion on one host at a time, so the rest of the fleet stays up.
self-check — recall, not a test
1 forks and serial both limit "how many hosts at once" — what is the actual difference?
2 A task has delegate_to: lb01. Where does it execute, and what does inventory_hostname hold there?
3 Your colleague says the deploy play "uses serial 1" and there are 20 web hosts. Describe the run.