Start with the incident, because the controls only make sense once you
have seen what they are for.
A shared database becomes slow at 02:12. Application servers start
failing their health checks. The monitoring system fires
ServiceUnhealthy for each of them. A rulebook responds by restarting
the service on the affected host.
The restarted service reconnects, hammers the already-slow database
harder than a warm one would, fails its next health check, and fires the
alert again. Meanwhile eleven other hosts are doing the same.
By 02:22 the rulebook has performed four hundred restarts. The database
is now unusable, because four hundred connection storms arrived while it
was struggling.
The incident lasted ten minutes and the automation caused nine of them.
Every element of that is ordinary. The alert was correct: the service was
unhealthy. The remediation was reasonable: restarting a hung service is
what an operator would have done. The rulebook worked exactly as
designed.
What was missing was any recognition that the action feeds the source.
The amplification loop
Draw the model from the previous lesson again, and then draw the arrow
nobody draws:
+----------------------------------------------+ | | v | [ source ] --> [ condition ] --> [ action ] ------+ alert matches restarts fires the service
The feedback arrow is the one that turns a rule into a loop. It is
invisible in a linear description — “when the service is unhealthy,
restart it” contains no hint of it — and it is present far more often than
teams expect, because most remediations touch the thing being monitored.
That is what makes them remediations.
Rate limiting: throttle
The rulebook mechanism for event storms is the throttle node on a rule.
The upstream documentation states the problem it exists for:
“When we have too many events within a short time span (event storm) and
the condition matches, we would trigger the action multiple times within
that time period.”
“When the condition matches for the first time we trigger the action and
then suppress further action till the time window expires.” This is the
one you want for remediation: respond fast, do not respond again while the
first response is still settling.
once_after — wait, then react once for everything.
Collect the unique events until the window expires, then act once. Good
for summarising and notifying; bad for anything time-critical, because you
have deliberately added five minutes of delay.
accumulate_within — react only if it happens enough.
Fire when the count reaches the threshold inside the window. This is a
noise filter: it distinguishes one flap from a real pattern.
Serialisation: lock
lock is a different control and the two get confused constantly.
The documentation: “An optional string based lock ensures sequential
execution of this action when execution strategy is set to parallel. It
can also be a string field from the event payload. The locks are per
ruleset, if a lock is in place all actions that use the same lock will
wait till the earlier action has completed.”
Everything this course teaches about blast radius applies to the playbook
an event triggers. --limit, serial, max_fail_percentage,
preconditions — all of it, unchanged.
There is one addition that is specific to event-driven automation, and it
is the control most often missing:
A cap on how many hosts a single firing may change, enforced inside
the playbook, independent of what the event said.
The reasoning: the event payload determines the target. The payload comes
from a system you do not control, over a transport that can be wrong,
duplicated or malicious. A rule that targets whatever the event names has
delegated its hosts: line to the monitoring system.
- name: Event-triggered remediation hosts: "{{ target_hosts }}" gather_facts: false any_errors_fatal: true tasks: - name: Refuse to remediate more than the permitted number of hosts ansible.builtin.assert: that: - ansible_play_hosts_all | length <= 3 fail_msg: >- Refusing: this remediation is capped at 3 hosts and the event resolved to {{ ansible_play_hosts_all | length }}. A fleet-wide symptom is an incident, not a remediation - page instead. run_once: true tags: [always]
This is the guardrail pattern from Part XXIV, and the fail_msg carries
the actual argument: if the symptom is fleet-wide, the cause is
probably shared, and the response should be a human rather than a
hundred restarts.
The kill switch
Every automated response needs a way to be stopped by a human under
pressure, and there are three properties that matter.
Fast. Seconds. If it requires a merge request, it is not a kill
switch.
Reachable. By whoever is on call at 03:00, without a laptop, without
a VPN they may not be able to reach, and without the permissions of the
person who built the rulebook.
Verifiable. The person who pulls it can confirm within seconds that it
took effect. “I disabled it, I think” is not an incident-management state
anybody should be in.
Practical implementations, from coarse to fine:
Mechanism
Speed
Granularity
Note
Stop the rulebook process
Immediate
Everything
The blunt instrument. Make sure the supervisor does not restart it
shutdown action on a control event
Seconds
Everything in that ruleset
A kill switch expressible in the rulebook itself
Disable the job template the rule triggers
Seconds
One response
Platform-side, leaves the rulebook running and failing loudly
A precondition on a flag the play reads
One run
One response
Works with no platform. The flag must live where a responder can change it in seconds
Approval above a threshold
The bridge between fully automated and fully manual is the approval node
from lesson 5, applied by blast radius:
Blast radius of the response
Control
Read-only — diagnostics, ticket, notification
Fully automatic
One host, reversible, service-level
Automatic with throttle, lock and a cap
Several hosts, or irreversible on one
Approval node, with the diagnostics already gathered
Fleet-wide, or data-affecting
Page a human. No automated path exists
The middle row is where the design effort pays off. A workflow that runs
diagnostics automatically and then waits for approval before changing
anything gives the responder the thing they actually want at 03:00 —
evidence, already collected — without giving the rule the authority to act
on it.
That arrangement is often better than either extreme. It is faster than a
human doing the diagnosis, and safer than a rule doing the remediation.
Knowledge check
Knowledge check · 5 questions
Q1. A rulebook restarts a service when its health check fails. During a shared-database slowdown it performs four hundred restarts in ten minutes across twelve hosts. What is the structural defect?
Q2. Which statements about throttle and lock are accurate? Select all that apply.
Q3. A cooldown of five minutes after each remediation is sufficient protection against a service that flaps every six minutes.
Q4. You add an assertion to an event-triggered playbook refusing to run when the event resolves to more than three hosts. What is the best justification for this cap?
Q5. A kill switch that has never been tested should be treated as a plan rather than as a control.
Passing score: 75%. Answers are checked in this browser.