Safe Upgrades & Rollbacks
Snapshot first, upgrade servers before agents one at a time, respect skew, and know that rollback means restore.
Upgrading k3s is low-drama if you follow the order and take a safety net first. The golden rule: an upgrade is easy to move forward and hard to move back, so the snapshot comes before anything else.
The safe sequence
- Take an on-demand etcd (or SQLite) snapshot.
- Upgrade server nodes first, one at a time, waiting for each to return
Readyand rejoin etcd quorum before touching the next. - Upgrade agents afterwards.
- Never let agents run a newer minor version than the servers — respect the Kubernetes version-skew policy (agents may trail servers, not lead).
Rollback reality
There is no k3s downgrade. A minor-version upgrade migrates the datastore schema, so "rolling back" really means restore the pre-upgrade snapshot onto the old binary. That is exactly why step 1 exists.
Fleet upgrades
For many nodes, the system-upgrade-controller drains, upgrades, and uncordons nodes from a declarative Plan, honouring the server-then-agent order for you.
Example
# system-upgrade-controller Plan: servers first, then agents
apiVersion: upgrade.cattle.io/v1
kind: Plan
metadata:
name: server-plan
namespace: system-upgrade
spec:
concurrency: 1 # one node at a time
version: v1.30.6+k3s1
nodeSelector:
matchExpressions:
- {key: node-role.kubernetes.io/control-plane, operator: In, values: ["true"]}
serviceAccountName: system-upgrade
cordon: true
upgrade:
image: rancher/k3s-upgradeWhen to use it
- An ops team takes a named etcd snapshot before every k3s upgrade so they can run cluster-reset if the new version causes an incompatibility.
- An operator uses the system-upgrade-controller to roll out k3s patch releases one node at a time with automatic cordon/drain, ensuring zero-downtime.
- A developer pins k3s to a specific minor version in staging for three weeks before promoting the same version pin to production.
More examples
Snapshot before upgrading
Takes a named etcd snapshot as a rollback point, then upgrades the server binary using the install script.
k3s etcd-snapshot save --name pre-v1.30-upgrade
kubectl get nodes
# Then upgrade the first server:
curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION=v1.30.0+k3s1 sh -Drain and upgrade a node
Safely drains the agent node before upgrading its k3s binary, then restores scheduling after the upgrade.
kubectl drain worker-01 --ignore-daemonsets --delete-emptydir-data
curl -sfL https://get.k3s.io | \
K3S_URL=https://server:6443 K3S_TOKEN=$TOKEN \
INSTALL_K3S_VERSION=v1.30.0+k3s1 sh -
kubectl uncordon worker-01System-upgrade-controller Plan
Defines an upgrade Plan that rolls out the stable k3s release to all agent nodes one at a time automatically.
apiVersion: upgrade.cattle.io/v1
kind: Plan
metadata:
name: k3s-agents
namespace: system-upgrade
spec:
concurrency: 1
nodeSelector:
matchLabels:
node-role.kubernetes.io/agent: 'true'
channel: https://update.k3s.io/v1-release/channels/stable
upgrade:
image: rancher/k3s-upgrade
Discussion