Skip to main content
RunBook Academy

← All labs in Linux

Lab · advanced · ~90 min

Lab: Rolling kernel upgrade on a cluster

B · Nested virtualisationC · Simulation

Objectives

  • Perform a rolling kernel upgrade
  • Validate the new kernel
  • Return every drained node to service
  • Test the GRUB rollback
  • Document the change

Prerequisites

This lab performs a rolling kernel upgrade on a cluster node by node. By the end you will have a working procedure and a tested rollback.

Tasks

Task 1: Capture baseline

# Current kernel
uname -r > /tmp/kernel-before.txt

# Cluster status
sudo pcs status > /tmp/cluster-before.txt

# Service health
curl -sf http://<vip>/health > /tmp/health-before.txt

Task 2: Configure GRUB for fallback

# Note the current default
sudo grub2-editenv list | grep saved_entry

# Set the new kernel to be the one-time boot
sudo grub2-editenv list
# Check that the new kernel is set as default (after install)

Task 3: Install the new kernel

On node1 (canary):

sudo dnf install kernel

# Record the exact version. Every other node gets this one.
rpm -q kernel | tail -1 > /tmp/kernel-target.txt

The new kernel is installed alongside the old. Write the exact version down now: node2 and node3 must receive the version node1 validated, not whatever the repository holds when you get to them.

Task 4: Drain node1

sudo pcs node standby node1

# Confirm the drain finished before you touch the node.
# "standby" is a request; resource migration takes time.
sudo pcs status nodes
sudo pcs status resources | grep node1    # must return nothing

Do not proceed while any resource is still listed on node1. Draining is asynchronous. A stop that is still in progress looks identical to a drain that has completed if you only read the node state.

Task 5: Reboot into the new kernel

On node1, and only on node1:

# Confirm the old kernel entry is still present as a fallback
sudo grubby --info=ALL | grep -E '^(index|kernel)'

sudo reboot

Wait for the host to come back. SSH in and verify:

uname -r
# Should show the new kernel

sudo pcs status
# Node1 should be a cluster member again - but still in standby

Node1 rejoins the cluster on boot, and it rejoins in standby. Standby is stored in the CIB, so it survives the reboot. The node is a member, it is not running anything, and pcs status reports this as normal.

Task 6: Validate node1 while it is still drained

Validate the node before you let it carry traffic. On node1:

# The kernel that is running must be the kernel you installed
uname -r
rpm -q kernel                     # running vs installed must agree

# Boot-time errors
sudo journalctl -k -b --priority=err

# The things kernel upgrades break: network and storage drivers
ip -br link
sudo multipath -ll                # if multipath is in use
sudo pvs && sudo vgs

# Critical services on this host
sudo systemctl --failed

If validation fails, roll back before returning the node:

sudo grubby --info=ALL             # find the old kernel index
sudo grubby --set-default-index=1  # persistent: survives every reboot
sudo reboot

Use grubby --set-default-index rather than grub2-reboot. grub2-reboot is a one-shot override: the node boots the old kernel once and then boots the bad kernel again on its next reboot, which is typically a fencing event weeks later with nobody watching.

Task 6b: Return node1 to service

This is the step that gets skipped, and skipping it is how a “successful” upgrade ends with a cluster that runs nothing.

# From any cluster member
sudo pcs node unstandby node1
sudo pcs status nodes              # node1 must appear under Online, not Standby

# Confirm it is actually carrying work again
sudo pcs status resources
sudo pcs status --full | grep -A5 -i failed    # must be empty

Only now is the service validated end to end:

curl -sf http://<vip>/health
time curl -sf http://<vip>/

Task 7: Hold for 24 hours

After node1 is back in service, hold for 24 hours. Monitor:

  • Error rates in logs.
  • Performance metrics.
  • Health check status.

A node in standby is not being tested. The hold only means something once the node is carrying resources again, which is the other reason Task 6b cannot be deferred.

If anything goes wrong, drain node1 again and roll it back.

Task 8: Update node2 and node3

Repeat the whole cycle for one node at a time. Never drain two nodes at once: on a 3-node cluster that leaves a single node holding everything with no failover margin, and on a 2-node cluster it loses quorum.

For each node in turn - node2, then node3:

# Substitute your own values before running:
TESTED_VERSION=6.8.0-51.52

# --- from an in-service node ---
sudo pcs node standby node2
sudo pcs status resources | grep node2     # must return nothing

# --- now SSH to node2; every command below runs ON node2 ---
ssh node2
hostname                                   # must print node2
sudo dnf install kernel-"$TESTED_VERSION"
sudo grubby --info=ALL                     # old entry still present
sudo reboot

# --- after node2 is back, from any node ---
ssh node2 uname -r                         # must be the new kernel
ssh node2 'rpm -q kernel'                  # running vs installed agree
ssh node2 'sudo journalctl -k -b --priority=err'

sudo pcs node unstandby node2              # RETURN IT TO SERVICE
sudo pcs status nodes                      # node2 under Online
sudo pcs status --full | grep -A5 -i failed  # empty before the next node

Install the exact version you validated on node1, not a bare dnf install kernel. A bare install picks up whatever the repository holds today, which may be a newer build than the one your canary proved. Then hold 24 hours and repeat for node3.

Task 9: Final validation

After all nodes are updated, the check is not “the cluster looks fine”. The check is “no node is left drained”.

# Node states - this is the assertion that matters.
# No node may be in standby or maintenance.
sudo pcs status nodes

# Same answer from the CIB, script-friendly:
sudo crm_mon -1 | grep -iE 'standby|maintenance'   # must return nothing

# All resources running, and where you expect them
sudo pcs status resources

# No failed actions anywhere
sudo pcs status --full | grep -A5 -i failed

# Synthetic monitoring through the VIP
curl -sf http://<vip>/health

# 24h monitor
journalctl -k --since "24 hours ago" --priority=err

Task 10: Document

KERNEL UPGRADE RECORD
Date: 2026-08-09
Change: kernel 5.14.0 to 5.15.0
Reason: Security update / simulated
Nodes: 3-node cluster, one at a time
Hold: 24 hours per node

Validations:
- node1: boot PASS, network PASS, storage PASS, services PASS
- node2: boot PASS, network PASS, storage PASS, services PASS
- node3: boot PASS, network PASS, storage PASS, services PASS

Returned to service (unstandby):
- node1: YES, carrying resources, verified 14:20
- node2: YES, carrying resources, verified 16:05
- node3: YES, carrying resources, verified 17:40
Standby/maintenance grep at close: no output (PASS)

Rollback tested: yes, in staging
Rollback method: grubby --set-default-index (persistent)
Rollback duration: 2 minutes per node

Result: success

The “returned to service” block is not paperwork. It is the only line in the record that distinguishes a completed upgrade from a cluster that has been quietly drained to nothing.

Deliverables

  • · Change record
  • · Validation results
  • · Rollback tested
  • · Every node unstandby and carrying resources at the end

Verification status

Last reviewed
2026-08-09
Executed end to end
not yet run on hardware

The commands and configuration here have been reviewed against the verified software versions, but nobody has run this lab start to finish on a system meeting its prerequisites. Treat the Expected Outcome as the intended result rather than an observed one, and keep the Cleanup section to hand.