Automate K3s Upgrades

Oct 10, 2025

In the following post I explain how I leveraged Renovate and the system-upgrade-controller to automate K3s upgrades.

Prerequisites

My K3s cluster is managed via ArgoCD. This is required so that updated resources are automatically applied to your Kubernetes cluster.

Also you’ll need Renovate to automatically fetch updates for you.

How it works

Deploy System-Upgrade-Controller

First, deploy the system-upgrade-controller to your cluster. This tool from Rancher can coordinate in-cluster K3s upgrades.

If you are using ArgoCD, here is an example Application for the system-upgrade-controller.

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: system-upgrade
  namespace: argocd
  finalizers:
    - resources-finalizers.argocd.argoproj.io
spec:
  project: default
  revisionHistoryLimit: 1
  destination:
    name: in-cluster
    namespace: system-upgrade
  syncPolicy:
    automated:
      prune: true
      allowEmpty: true
  source:
    repoURL: https://kube-the-home.github.io/system-upgrade-controller-helm/
    targetRevision: 1.4.1
    chart: system-upgrade-controller
    helm:
      valuesObject: {}

Create a ‘Plan’ to upgrade your cluster

The ‘Plan’ is a custom resource that the system-upgrade-controller is using to decide if it should update your cluster.

Adapt the following ‘Plan’ to match your needs.

---
apiVersion: upgrade.cattle.io/v1
kind: Plan
metadata:
  name: k3s-server
  namespace: system-upgrade
  labels:
    k3s-upgrade: server
spec:
  concurrency: 1
  version: v1.34.1+k3s1
  nodeSelector:
    matchExpressions:
      - {key: kubernetes.io/hostname, operator: Exists}
  serviceAccountName: system-upgrade
  cordon: true
  upgrade:
    image: rancher/k3s-upgrade

Instruct renovate to update your ‘Plan’

Finally you have to instruct Renovate to automatically update your ‘Plan’.

Place this configuration in your repository’s renovate.json (or in your Renovate config file) so Renovate can detect and update the Plan YAML.

{
  "customManagers": [
    {
      "customType": "regex",
      "managerFilePatterns": [
        "/^custom-resources/system-upgrade/plan.yaml$/"
      ],
      "matchStrings": [
        "version:\\s*(?<currentValue>v[\\d.]+\\+k3s\\d+)"
      ],
      "depNameTemplate": "k3s-io/k3s",
      "datasourceTemplate": "github-releases",
      "versioningTemplate": "loose"
    }
  ]
}