A Kubernetes cluster is a pile of parts that each look simple on their own: the CNI, the container runtime, the storage layer, the guards in front of the API server. Each one carries dependencies tangled into the others, so getting the combination right, keeping it secure, and holding it together through every upgrade is where the real work is.
Think of a car. You choose the model, the size, the options, and how you drive it. You don't rebuild the engine on the driveway, and you wouldn't pull two wheels off to turn it into a bicycle or cut the roof away to make a convertible. The parts that are hard to get right and dangerous to get wrong are engineered, integrated, and maintained by the people who build the car.
A Cluster Stack takes the same view of Kubernetes. It's a versioned bundle that pins three things together under one version number: the node operating system, the cluster topology, and the components that run inside the cluster. All three are built and tested together, before any node boots. A Dockerfile does this for a single container: you write the build once, and everyone who runs it gets the same image. A Cluster Stack does it for a whole cluster, so one definition gives you one version and one tested result.
Normally each of those pieces carries its own version, and keeping them compatible is your problem. A Cluster Stack folds all of them into one number. You point at a release and get the Kubernetes version, the CNI, the storage driver, the DNS, the cloud integration, and the admission guards, in a combination that was tested as a whole. One number to track instead of a dozen.
We came up with the Cluster Stack concept, put it forward for the 2023 public tender to build the Kubernetes-as-a-Service part of the Sovereign Cloud Stack, a German government initiative, and won — then built it there. We also build and maintain cluster-api-provider-hetzner, the open-source Cluster API provider for Hetzner, and we've run production this way since 2020.
A stack has three layers. Each one is pinned, and the three move together.
| Layer | What it is | What you still set |
|---|---|---|
| Node image | Syself Linux, an immutable OS. The kernel, container runtime, kubelet, and etcd are pinned to exact versions and hashes. | Nothing inside the image. It is sealed. |
| Cluster template | The topology, meaning the shape of the cluster, plus sensible defaults. | Replica counts, machine types, and region, through variables. |
| In-cluster components | The CNI, cloud integration, DNS, storage, and admission guards. Syself pins these and installs them when the cluster comes up. | Nothing. They ship inside the release. |
The node image has its own version inside the stack, and many releases reuse the same one. When a release only changes components, it updates the running cluster and leaves the nodes alone. When a release changes the image, every node is replaced from the new image. Nodes are never patched in place. You can see every component in a release, its version, and the current state of the CVEs that affect it in the Version Hub; we re-audit it daily, because CVEs surface over time.
So you never fix a node. When one breaks or falls behind, the platform throws it away and boots an identical replacement. That's the old "cattle, not pets" line: you don't name a server and nurse it back to health, you declare the machines you want and let the platform keep the fleet matching. It's the model behind Cluster API, the Kubernetes project for managing clusters and the machines under them, and the same replace-don't-patch idea as the immutable node OS.
You never install or upgrade the components yourself. They ship inside the release and move when the stack moves.
A release name has four parts: provider, flavor, track, and version. For example, hetzner-apalla-1-36-v2.
hetzner-apalla) say where the cluster runs and which flavor of stack it is. Today there is one flavor, apalla.1-36) is the release line for one Kubernetes minor version. Each Kubernetes minor gets its own track.v2) is one release within that track.So hetzner-apalla-1-36-v2 is the second release on the 1.36 track. When Syself ships a fix or a new component, it becomes v3 on the same track. Moving to a new Kubernetes minor means moving to a new track.
By default, every new release on your track becomes available to your clusters as it ships. That's the automatic part, and it doesn't touch anything you're running.
A cluster runs only the release its Cluster object names, and it moves to a new release only when you change that name. Until then, the new release sits available and unused. Clusters never update themselves.
The Cluster object is a plain, open-standard Kubernetes resource on the management cluster. You edit it with kubectl, with GitOps tools like Argo or Flux, or in the Syself console. Every change is an edit to that one object: to upgrade, you change the version field; to scale, you change a replica count. Controllers then reconcile the running cluster to match, and they fix drift on their own. Syself recommends keeping the object in Git.
When you do advance the version, the upgrade happens one node at a time, using the same cordon, drain, and replace steps as self-healing. The upgrade is atomic at the stack level. You do not sequence the CNI, then the storage driver, then the control plane, then the OS by hand. You change one field, and the platform rolls the whole tested combination. If you ever need to hold a cluster on an exact release, you can pin that version.
Because the failures that hurt most in Kubernetes are the combinations. A CNI that works on its own fails to load on a certain kernel. A storage driver fails against a specific control-plane version. Each piece passed its own tests, and together they fail.
A Cluster Stack tests the combination, not the parts.
The stack still adapts to the machine it lands on. If a GPU is detected while a node is being provisioned, the drivers and runtime components are installed automatically.
Syself operates the stack. You operate what runs on top of it.
| Syself manages | You own |
|---|---|
| OS builds and node images | Your workloads and manifests |
| Component and addon releases | Your GitOps configuration |
| Tested upgrade paths | Your Hetzner account and servers |
| CVE response in the stack | Deciding when to advance the version |
The one thing you touch on the platform side is the Cluster object. You upgrade, scale, and configure there. Everything else in the stack is Syself's job.
A Cluster Stack is opinionated on purpose, but that doesn't box you in. You still shape the machine sizes, the region, the replica counts, the feature set, and everything you run on top. We optimize the stack for the hardware and for what the provider offers, we own the security-relevant parts and maintain them, and running a cluster feels like running your workloads: the same Kubernetes objects, declared the same way.
And when the standard stack isn't enough, there's a team behind it. We do integrations and custom work, we offer SLAs and managed services, and a partner network of specialized agencies builds on the same foundation. You get things done; the parts underneath are handled by people who operate and fix them for a living.
A cluster runs its named release until you advance it, so a CVE fixed in a newer release doesn't reach you until you point the cluster there. A fix being available isn't the same as your cluster having it.
And before a minor-version move, scan your own manifests. A stack upgrade brings a tested platform, but it can't know whether a new Kubernetes minor removed an API your workloads still use.
No. A new release becomes available automatically, but your cluster keeps running the release its Cluster object names. It moves only when you change that name. You trigger every release, so you're in charge of the timing and can make sure everything's ready before a cluster moves.
An update stays within a Kubernetes minor: patches, CVE fixes, and new OS or addon revisions. The Kubernetes API and how the cluster behaves don't change, and an update never adds a feature. New features only ever arrive with a new Kubernetes minor, which is an upgrade. An upgrade brings that minor's features bundled together, and behaviour can change, including deprecated APIs that get removed. You trigger both, so you pick the moment and can check your workloads first.
No. The components are pinned inside the release and tested as a set. You move the whole stack, not one piece of it, so you never run an untested combination.
In the Cluster object on the management cluster. Edit the version field with kubectl, through GitOps, or in the console. The change is one field, and the platform rolls the cluster to match.
A good rule of thumb: treat the release name as the single source of truth for what a cluster runs, keep the Cluster object in Git, and advance the version on purpose rather than on a schedule. To see what that testing actually involves, read how Syself tests a Cluster Stack release. For the deeper mechanics, the declarative cluster management doc goes layer by layer.
Start with a 14-day free trial, and our step-by-step guides will walk you through your first cluster deployment in minutes.
Tags
In Syself Autopilot 1.36, a node-local proxy handles control-plane failover on every worker, so a load-balancer outage no longer marks the whole fleet NotReady.
Syself Autopilot 1.36 ships its own reverse tunnel so kubectl logs, exec, and pod metrics work—each node dials out, and the control plane never dials in.
KubeGate is Syself Autopilot 1.36's single front door to the Kubernetes API server—it controls who reaches the control plane and preserves the real client IP.