Documentation is tailored to each Cluster Stack release. Pick the one your cluster runs. {#if release === minor.latest} Right now you are on the latest ClusterStackRelease available for Kubernetes 1.27. ## Ready to move to a newer Kubernetes version? To move from Kubernetes 1.27 toward Kubernetes 1.36, follow [Upgrading the cluster to a new Kubernetes version](/docs/hetzner/apalla/clusters/upgrades/upgrade-to-a-new-kubernetes-version). ## Your other options - **Update an older ClusterStackRelease**: If your cluster uses an older release, select its actual version in the picker at the top of this page. The version-specific guide will show the relevant update steps. - **Check your cluster's version**: If you are not sure which Kubernetes version and Cluster Stack your cluster uses, [check the Kubernetes version and Cluster Stack](/docs/hetzner/apalla/clusters/configure/how-to-check-the-kubernetes-version-and-stack). {:else} A Cluster Stack release bundles the Kubernetes patch version, the in-cluster components, and the node image under one version number, tested together before any node boots. Updating within a Kubernetes minor moves your cluster from one release to the next on that same minor, here from hetzner-apalla-1-27-v15 to hetzner-apalla-1-27-v19. The Kubernetes minor itself does not change. {#if release.hasArmImages} ## Check for ARM-based nodes If your cluster isn't running ARM-based nodes, skip this step. ARM is temporarily not supported on this release. If your cluster has any, the update will fail unless you migrate them to x86 nodes first — see [Migrate ARM servers to x86 in your cluster](/docs/hetzner/apalla/servers-and-nodes/provision/migrate-arm-to-x86) for instructions. {/if} ## Preparing the clusterstack object Check if `autoSubscribe` is set to `true` or `false` in your clusterstack object and follow the steps for your case: > [!NOTE] > The `autoSubscribe` key in the clusterstack object indicates that Syself Autopilot will automatically fetch the latest ClusterStackRelease version and make it available for use. {#if upgrade.toMinorLatest.length === 1} The latest version is automatically available for you. You don't need to do anything. Keep reading the next steps. {:else} The latest version is automatically available for you, but you still need to specify the versions in between. For that, add [] to the `spec.versions` array in your Cluster Stack: ```yaml vars persistBlur title="clusterstack.yaml" apiVersion: clusterstack.x-k8s.io/v1alpha1 kind: ClusterStack metadata: name: hetzner-apalla-1-27 spec: provider: hetzner name: apalla kubernetesVersion: "1.27" channel: stable autoSubscribe: true versions: [] providerRef: name: hetzner-apalla-1-27 kind: HetznerClusterStackReleaseTemplate apiVersion: infrastructure.clusterstack.x-k8s.io/v1alpha1 ``` {/if} {#if upgrade.toMinorLatest.length === 1} You can go to the latest version directly. To make it available, add v19 to the versions array in your Cluster Stack object: ```yaml vars persistBlur title="clusterstack.yaml" apiVersion: clusterstack.x-k8s.io/v1alpha1 kind: ClusterStack metadata: name: hetzner-apalla-1-27 spec: provider: hetzner name: apalla kubernetesVersion: "1.27" channel: stable autoSubscribe: false versions: ["v19"] providerRef: name: hetzner-apalla-1-27 kind: HetznerClusterStackReleaseTemplate apiVersion: infrastructure.clusterstack.x-k8s.io/v1alpha1 ``` {:else} You need to specify the ClusterStackRelease versions in between using the `spec.versions` array in your Cluster Stack object. The following is the complete (and shortest) tested upgrade path to go from your current version to hetzner-apalla-1-27-v19: ```yaml vars persistBlur title="clusterstack.yaml" apiVersion: clusterstack.x-k8s.io/v1alpha1 kind: ClusterStack metadata: name: hetzner-apalla-1-27 spec: provider: hetzner name: apalla kubernetesVersion: "1.27" channel: stable autoSubscribe: false versions: ["v19"] providerRef: name: hetzner-apalla-1-27 kind: HetznerClusterStackReleaseTemplate apiVersion: infrastructure.clusterstack.x-k8s.io/v1alpha1 ``` {/if} ## Checking the available ClusterStackReleases Check if the `ClusterStackReleases` you need are available with: {#if upgrade.toMinorLatest.length === 1} ```console vars $ kubectl get clusterstackrelease NAME K8S VERSION READY AGE REASON MESSAGE hetzner-apalla-1-27-v15 v1.27.13 true 2d hetzner-apalla-1-27-v19 v1.27.16 true 1m ``` {:else} ```console vars $ kubectl get clusterstackrelease NAME K8S VERSION READY AGE REASON MESSAGE hetzner-apalla-1-27-v15 v1.27.13 true 2d ... ... true 1m hetzner-apalla-1-27-v19 v1.27.16 true 1m ``` {/if} Note down the values of the `NAME` and `K8S VERSION` columns from the release you want to upgrade to. In this case, hetzner-apalla-1-27-v19 and v1.27.16. ## Upgrading the cluster object Edit your cluster and change the `spec.topology.class` and `spec.topology.version` to match the `NAME` and `K8S VERSION` of the ClusterStackRelease, respectively. This can be achieved either by editing the resource inside the management cluster, or by updating it in your GitOps repository. {#if upgrade.toMinorLatest[0]?.kubernetes === minor.latest.kubernetes} In this case, you only need to update one version. > [!NOTE] > The manifest below uses `cluster.x-k8s.io/v1beta2`, the current API version for cluster manifests. `v1beta1` keeps working for now, but Syself recommends migrating: see [Migrate a manifest to v1beta2](/docs/hetzner/apalla/clusters/upgrades/migrate-a-manifest-to-v1beta2). ```yaml vars persistBlur title="cluster.yaml" apiVersion: cluster.x-k8s.io/v1beta2 kind: Cluster metadata: name: mycluster spec: topology: classRef: name: hetzner-apalla-1-27-v19 version: v1.27.16 controlPlane: replicas: 3 workers: machineDeployments: - class: workeramd64hcloud name: md-0 replicas: 1 failureDomain: nbg1 variables: overrides: - name: workerMachineTypeHcloud value: cpx42 variables: - name: region value: nbg1 - name: controlPlaneMachineTypeHcloud value: cpx42 ``` {:else} {/if} Once you apply it, the cluster rolls to the Cluster Stack version you specified: new nodes come up and the old ones are removed, one at a time. This is the same node replacement that happens during routine self-healing, so a workload set up to tolerate it — replicas spread across nodes with a `PodDisruptionBudget` — rides through the roll without downtime. If your workloads are not set up that way yet, see [Prepare workloads for upgrades](/docs/hetzner/apalla/clusters/availability/prepare-workloads-for-upgrades); it applies to any node replacement, not just updates. If you need to update to another version, wait for the current update process to finish. You can check if it's done by checking the nodes in your cluster: ```console $ kubectl get nodes ``` If you still have old nodes, this means the update is in progress. In this case, wait until the output shows only new nodes. ## Moving to a new Kubernetes minor instead of a new release on your current one? See [Upgrading the cluster to a new Kubernetes version](/docs/hetzner/apalla/clusters/upgrades/upgrade-to-a-new-kubernetes-version). ## Not sure which release your cluster is on? [Check the Kubernetes version and Cluster Stack](/docs/hetzner/apalla/clusters/configure/how-to-check-the-kubernetes-version-and-stack) for your cluster. {/if}