Stage 4 · Provision
Dynamic Inventory & Scale
Rolling & Canary Updates
serial, max_fail_percentage, and safe fleet rollouts.
Serial Batch Execution
The serial keyword controls how many hosts Ansible processes at a time. Instead of updating all hosts simultaneously (which risks total outage), you update in batches and verify each batch before proceeding.
---
- name: Rolling update web servers
hosts: webservers
serial: 3 # Update 3 hosts at a time
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: 3 means Ansible processes 3 hosts, then the next 3, and so on. If a batch fails, subsequent batches are skipped.
Failure Thresholds
---
- name: Rolling update with safety
hosts: webservers
serial: "25%"
max_fail_percentage: 10
any_errors_fatal: no
tasks:
- name: Deploy new version
ansible.builtin.git:
repo: https://github.com/app/repo.git
dest: /opt/app
version: "{{ deploy_version }}"
- name: Restart application
ansible.builtin.service:
name: myapp
state: restarted
- name: Health check
ansible.builtin.uri:
url: http://localhost:8080/health
status_code: 200
retries: 5
delay: 10max_fail_percentage: 10 stops the rollout if more than 10% of hosts in a batch fail. This prevents cascading failures.
Together these settings implement canary deployment logic. A small batch goes first. If it fails, the rollout stops. If it succeeds, the next batch proceeds.
Canary Deployments
# Stage 1: Deploy to canary hosts
- name: Deploy to canary
hosts: canary
serial: 1
tasks:
- name: Update and verify
block:
- name: Deploy
ansible.builtin.package:
name: myapp
state: latest
- name: Health check
ansible.builtin.uri:
url: http://localhost:8080/health
status_code: 200
timeout: 30
# Stage 2: Deploy to all (only if canary succeeded)
- name: Deploy to production
hosts: webservers
serial: "25%"
max_fail_percentage: 5
tasks:
- name: Update application
ansible.builtin.package:
name: myapp
state: latestThe canary stage runs first with a single host. If it succeeds, the production stage proceeds. If it fails, the playbook stops.
Rolling Strategies
| Strategy | serial | Use Case |
|---|---|---|
| Full parallel | all | Dev/staging, fast updates |
| Batched | 3 | Production, moderate risk |
| Percentage | 25% | Large fleets, proportional batches |
| Single | 1 | Canary, highest safety |
Automated Rollback
- name: Deploy with rollback
block:
- name: Backup current version
ansible.builtin.copy:
src: /opt/app/
dest: "/opt/app-backup-{{ ansible_date_time.iso8601_basic_short }}/"
remote_src: yes
- name: Deploy new version
ansible.builtin.git:
repo: https://github.com/app/repo.git
dest: /opt/app
version: "{{ deploy_version }}"
- name: Health check
ansible.builtin.uri:
url: http://localhost:8080/health
status_code: 200
register: health
rescue:
- name: Rollback to previous version
ansible.builtin.copy:
src: "/opt/app-backup/{{ latest_backup }}/"
dest: /opt/app/
remote_src: yes
- name: Restart application
ansible.builtin.service:
name: myapp
state: restartedThe block/rescue pattern automatically rolls back if the health check fails. The backup step ensures you can always restore.
A rollback that has never been tested is not a rollback. Regularly test your rollback playbooks in staging to ensure they work when needed.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.