Stage 4 · Provision
Playbooks & Variables
Error Handling & Strategies
failed_when, ignore_errors, serial rollouts, and free strategy.
Error Handling Basics
Ansible stops executing tasks on a host when a task fails. This default behavior prevents partial configurations. However, you often need more nuanced error handling — retrying, ignoring non-critical errors, or custom failure conditions.
- name: This will stop on failure
block:
- name: Task 1
command: echo "Step 1"
- name: This fails
command: /bin/false
- name: Task 3 — never runs
command: echo "Step 3"When task 2 fails, task 3 is skipped. The play continues with other hosts but this host stops at the failure.
Custom Failure Conditions
failed_when lets you define when a task should be considered failed. This is useful for commands that return non-zero exit codes in expected situations.
# Check if service is running
- name: Check nginx status
command: systemctl is-active nginx
register: result
failed_when:
- result.rc != 0
- result.rc != 3
# Only fail on specific error
- name: Run migration
command: /opt/app/migrate.sh
register: migration
failed_when: "'already applied' not in migration.stderr"failed_when accepts a list of conditions. The task fails if ALL conditions are true. Use it to handle expected non-zero exit codes.
Ignore Errors
- name: Try to stop old service
service:
name: old-service
state: stopped
ignore_errors: yes
- name: Check if port is free
wait_for:
port: 8080
state: stopped
timeout: 5
register: port_check
ignore_errors: yes
- name: Fail if port still in use
fail:
msg: "Port 8080 is still in use"
when: port_check is failedignore_errors: yes continues even if the task fails. The result is available via register for later decisions.
Ignoring errors masks real problems. Use it only when you expect certain failures and have a plan for them. Prefer block/rescue for error recovery.
Strategy Plugins
Strategy plugins control how Ansible executes tasks across hosts. The default is linear — all hosts run each task before moving to the next. Free strategy lets hosts proceed independently.
# Default: linear strategy
- name: All hosts run each task together
hosts: webservers
strategy: linear
tasks:
- name: Task 1
command: echo "A"
- name: Task 2
command: echo "B"
# Free strategy: hosts proceed independently
- name: Hosts run at their own pace
hosts: webservers
strategy: free
tasks:
- name: Wait for different times
wait_for:
timeout: "{{ delay }}"
vars:
delay: "{{ ansible_loop.index * 10 }}"free strategy is useful when hosts have different response times or when you want to maximize parallelism.
Serial Rollouts
# Roll out 25% at a time
- name: Rolling update
hosts: webservers
serial: "25%"
max_fail_percentage: 10
tasks:
- name: Update application
package:
name: myapp
state: latest
- name: Restart application
service:
name: myapp
state: restarted
- name: Verify application
uri:
url: http://localhost:8080/health
status_code: 200serial: 25% processes hosts in batches of 25%. If more than 10% fail, the entire play stops. This prevents rolling out a broken change to the entire fleet.
serial controls batch size. max_fail_percentage controls the failure threshold. Together they enable safe canary deployments — if a batch fails, the rollout stops before affecting all hosts.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.