Ansible Rolling Update: Upgrade RHEL/CentOS Packages Safely (Playbook)
By Luca Berton · Published 2024-01-01 · Category: installation
How to perform rolling updates on RHEL, CentOS, and Fedora using Ansible's yum module with serial and health checks. Zero-downtime upgrade playbook examples.

How to perform the rolling updates with Ansible in RedHat-like systems?
See also: Ansible yum Module: Install Packages on RHEL/CentOS (Examples & Playbook)
Ansible rolling update packages in RedHat-like systems
Today we're talking about rolling updates in RedHat-like systems using Ansible module yum and DNF. We already talked about these modules for installing packages but we would like to consider another use case. Both manage packages with the yum/DNF package manager.Parameters
name_string_state_string_update_cache_boolean_bugfix_boolean_security_boolean_
In the name could be a package or we could select all the packages of the system with the "\" star symbol.
The state for this case needs to be "latest" so we target the latest version for every package.
The "update_cache" is useful to forces the update of repository metadata before the installation, default no.
Other very interesting options are "bugfix" and "security" which allow you to update only packages marked as bugfix or security-related
See also: Install Google Chrome on Red Hat Using Ansible
Demo
Let's jump in a real-life Playbook to rolling update in RedHat-like systems with Ansible Playbook._yum.yml_
---
- name: rolling update Playbook
hosts: all
become: true
tasks:
- name: ensure pkg updated
ansible.builtin.yum:
name: nginx
state: latest
update_cache: true
- _yum-system.yml_
---
- name: rolling update Playbook
hosts: all
become: true
tasks:
- name: ensure system updated
ansible.builtin.yum:
name: "*"
state: latest
update_cache: trueConclusion
Now you know how to perform Rolling Update in RedHat-like systems.See also: Ansible yum Module: Manage RPM Packages on RHEL/CentOS (Guide)
What is a Rolling Update?
A rolling update upgrades servers one at a time (or in small batches) instead of all at once. This ensures:
- Zero downtime — some servers are always running
- Quick rollback — stop the update if problems appear
- Controlled risk — test changes on a few servers first
Complete Rolling Update Playbook
---
- name: Rolling update for web servers
hosts: webservers
serial: 1 # Update one server at a time
max_fail_percentage: 0 # Stop if ANY server fails
become: true
pre_tasks:
- name: Remove from load balancer
ansible.builtin.uri:
url: "http://lb.example.com/api/servers/{{ inventory_hostname }}/disable"
method: POST
delegate_to: localhost
- name: Wait for connections to drain
ansible.builtin.wait_for:
timeout: 30
tasks:
- name: Update all packages
ansible.builtin.yum:
name: '*'
state: latest
update_cache: true
register: update_result
- name: Show updated packages
ansible.builtin.debug:
msg: "{{ update_result.changes.updated | default([]) | length }} packages updated"
- name: Reboot if kernel was updated
ansible.builtin.reboot:
reboot_timeout: 300
when: update_result.changes.updated | default([]) | select('match', 'kernel') | list | length > 0
post_tasks:
- name: Verify application is healthy
ansible.builtin.uri:
url: "http://{{ inventory_hostname }}:8080/health"
status_code: 200
register: health_check
retries: 5
delay: 10
until: health_check.status == 200
- name: Add back to load balancer
ansible.builtin.uri:
url: "http://lb.example.com/api/servers/{{ inventory_hostname }}/enable"
method: POST
delegate_to: localhostSerial Strategies
# Update one at a time
serial: 1
# Update 2 at a time
serial: 2
# Update 25% at a time
serial: "25%"
# Progressive: 1, then 5, then all remaining
serial:
- 1
- 5
- "100%"Security-Only Updates
- name: Install security updates only
ansible.builtin.yum:
name: '*'
state: latest
security: true
bugfix: false
become: trueUpdate Specific Packages Only
- name: Update only web-related packages
ansible.builtin.yum:
name:
- nginx
- openssl
- curl
state: latest
become: trueExclude Packages from Update
- name: Update all except kernel
ansible.builtin.yum:
name: '*'
state: latest
exclude:
- kernel*
- docker*
become: trueFAQ
What's the difference between serial and forks?
serial: How many hosts complete the entire play before moving to the next batchforks: How many hosts execute tasks in parallel within a batch
serial controls the batch size. forks (default 5) controls parallelism within each batch.
How do I rollback if an update breaks something?
- name: Rollback last yum transaction
ansible.builtin.command: yum history undo last -y
become: trueShould I use yum or dnf module?
Use dnf for RHEL 8+, Fedora 22+, AlmaLinux, Rocky Linux. Use yum only for RHEL/CentOS 7. Or use package for cross-distro compatibility.
Related Articles
Category: installation
Watch the video: Ansible Rolling Update: Upgrade RHEL/CentOS Packages Safely (Playbook) — Video Tutorial