Blog · October 18, 2026 · 12 min read

Kubernetes on Hetzner: k3s in Production

Diagram: six servers spread across three locations, connected by a private network, with a load balancer in front
Graphic: HumanITy

Kubernetes runs reliably on Hetzner Cloud, but you operate it yourself: as of October 18, 2026, Hetzner does not offer its own managed Kubernetes service. Hetzner provides the building blocks, meaning cloud servers, private networks, load balancers, volumes, and object storage, plus an official cloud controller manager and a CSI driver for Kubernetes. You set up the cluster itself with a distribution such as k3s, or you hire a service provider that runs it on Hetzner for you.

I run my own services, including this website, on a k3s cluster on Hetzner Cloud. In this article I show how that cluster is built and why: three locations, no public IP addresses on the nodes, everything as code. You can find all my articles on running Kubernetes collected on the Kubernetes page.

Does Hetzner offer managed Kubernetes?

No, not as its own product. On hetzner.com you will find cloud servers, load balancers, volumes, object storage, and private networks, but no Kubernetes service where Hetzner runs the control plane for you. Kubernetes appears on the product pages as a use case: Hetzner explicitly names private networks for "operating a Kubernetes cluster", and when asked whether its load balancers can be integrated with Kubernetes, Hetzner points to its official cloud controller manager on GitHub.

If you search for "Hetzner managed Kubernetes", you therefore get two kinds of results. One kind is guides and tools for building the cluster yourself. The other is service providers that set up and run a cluster on Hetzner infrastructure for you. That is those companies' offering, not Hetzner's, and your contract is with them.

For your decision this means: on Hetzner you get affordable European infrastructure and full control over Kubernetes, but upgrades, security, and troubleshooting in the control plane are on you. I explain how that compares with managed Kubernetes and your own data center in Kubernetes On-Premises or Cloud?.

My cluster at a glance

My cluster is not a lab setup, it is the environment my website and my own services run on. The building blocks:

Area What I use
Kubernetes distribution k3s
Infrastructure Hetzner Cloud, entirely via Terraform with the Hetzner provider hcloud
Nodes 3 control plane nodes and 3 agent nodes, all ARM servers of type CAX21
Locations Falkenstein, Nuremberg, and Helsinki, network zone eu-central
Network no public IPv4 or IPv6 on the nodes, private network, access via a bastion host, outbound traffic via a NAT gateway, WireGuard encryption in the cluster network
Entry point Hetzner Load Balancer (LB11) in front of Traefik as ingress, with Proxy Protocol
Operating system openSUSE MicroOS with custom snapshots built with Packer, kured for orderly reboots
Hetzner integration Cloud Controller Manager and CSI driver for volumes
Deployments ArgoCD pulls Helm values from the Git repository
Data and certificates CloudNativePG for databases, cert-manager for certificates
Observability Prometheus, Grafana, Alertmanager; logs with OpenSearch and Fluent Bit
Security Falco, Gatekeeper, Trivy Operator; secrets encrypted with SOPS/age in the repository
Terraform state remote in Hetzner Object Storage (S3)

The rest of this article walks through the decisions behind it.

Highly available across three locations

The three control plane nodes sit in Falkenstein, Nuremberg, and Helsinki, one per location. The three nodes for the applications run in Falkenstein (two) and Nuremberg (one). The reason for three control plane nodes: the control plane needs a majority to agree on changes to the cluster state. The k3s documentation puts it like this for embedded etcd: a highly available cluster must consist of an odd number of servers so etcd can maintain quorum, and quorum is (n/2)+1. With three servers, one can fail without the cluster losing its ability to act. A fourth server would not improve that.

Spreading across three data centers has a cost that the etcd documentation states openly: every vote has to cross location boundaries, which costs latency, and the data is replicated between all locations. For my setup, the benefit outweighs it, because losing an entire location does not take control of the cluster down with it. If Falkenstein fails, though, two of the three application nodes are gone; the cluster stays manageable but has much less capacity. If you put all three servers in the same data center, you are protected against losing a server, but not against losing the building.

Whether the spread actually looks the way you planned it, you can see from the labels the cloud controller manager writes to the nodes:

kubectl get nodes -L topology.kubernetes.io/region,topology.kubernetes.io/zone
kubectl get nodes -o custom-columns=NAME:.metadata.name,ARCH:.status.nodeInfo.architecture

The first command shows region and zone per node, the second the processor architecture. According to the cloud controller manager changelog, the zone labels will no longer be set automatically in the next major release; check the project page before relying on them. On my cluster every node says arm64, and that has a consequence I explain further down.

A network without public IP addresses

None of my nodes has a public IPv4 or IPv6 address. The servers only talk to each other over a private Hetzner network, and traffic in the cluster network is additionally encrypted with WireGuard. For administration I get in through a single bastion host, and outbound traffic, for example pulling container images, goes through a NAT gateway that can also be built highly available if needed.

The benefit: a node is simply not reachable from the internet, not even if a service accidentally listens on an open port. The attack surface shrinks to two points, the bastion host and the load balancer.

From the outside, requests come in through a Hetzner Load Balancer of type LB11, which passes them on to Traefik, the ingress controller that ships with k3s. Proxy Protocol is enabled between the two. Without it, Traefik would only see the load balancer as the sender of every request; with it, the real client IP arrives, which matters for logs, rate limiting, and troubleshooting. How Ingress and ingress controllers work together is explained in Kubernetes Ingress and Ingress Controllers.

Operating system and updates

The nodes run openSUSE MicroOS, an immutable operating system with automatic updates. Immutable means the base system is not changed package by package but updated as a whole, and a faulty update can be rolled back. I build the server images with Packer as custom snapshots, so every new node starts from the same state.

Automatic updates occasionally require a reboot. To keep all nodes from rebooting at once, kured makes sure only one node at a time is drained and restarted. That keeps the control plane majority intact, and the applications move to other nodes first.

Storage, databases, and certificates

Persistent volumes come from Hetzner's CSI driver, which attaches Hetzner volumes as storage in Kubernetes. I run databases with the CloudNativePG operator, which manages PostgreSQL clusters including replication inside the cluster. cert-manager obtains and renews certificates for HTTPS. How to back up volumes and the cluster state is covered in Kubernetes Backup: etcd and Volumes.

Everything as code: Terraform, SOPS, and GitOps

The entire infrastructure comes from one Terraform repository with a single terraform apply: network, servers, load balancer, NAT gateway, and bastion host. The Terraform state does not live on my machine but remotely in Hetzner Object Storage, so it does not get lost and two versions cannot drift apart.

Secrets live encrypted in the same repository, with SOPS and age. Every piece of configuration is traceable in Git without a single password in plain text.

ArgoCD rolls out the applications. It pulls the Helm values from the repository and continuously reconciles the cluster against them. A release of this website therefore takes two steps: build a new container image and bump the image tag in the Helm values. ArgoCD does the rest. The details are in GitOps with ArgoCD: Deploy from Git.

Observability and security

For metrics and alerts I use Prometheus, Grafana, and Alertmanager; for logs, OpenSearch with Fluent Bit as the collector. On the security side, Falco watches container behavior at runtime, Gatekeeper enforces rules before an object lands in the cluster, and the Trivy Operator scans running images for known vulnerabilities. That is more than a small cluster strictly needs, but it is the setup I consider appropriate for production environments at companies too. How to start without introducing everything at once is shown in Kubernetes Monitoring with Prometheus.

What to watch out for on Hetzner

Keep the cloud controller manager up to date. Hetzner removed the server.datacenter field from its API response on July 1, 2026. According to the project page, cloud controller manager versions up to and including v1.30.0 have crashed since then; you need at least v1.30.1. The current version is v1.39.0 (October 6, 2026). It is a good example of why self-hosting means maintenance: the cluster runs until something underneath it changes.

ARM servers need ARM images. Hetzner's CAX servers use Ampere processors with ARM architecture. Every container image you start there has to be built for arm64. Most common images exist for both architectures; for your own images you have to set that up in your build pipeline.

Upgrades are on you. k3s follows Kubernetes releases; the current one is v1.37.1+k3s1 from September 30, 2026. According to the project, each Kubernetes version only receives about one year of patches, so a regular upgrade date belongs in your operations plan, not on the "when we have time" list.

You do not have to start from scratch. There are community projects that prepare exactly this path, for example kube-hetzner (Terraform, k3s, immutable openSUSE nodes) or hetzner-k3s (a command-line tool that creates a k3s cluster). Before using one, check how actively it is maintained and whether you understand what it creates for you. A cluster you cannot explain will surprise you at the first incident.

When to get help

Running your own cluster on Hetzner is very doable if someone on your team truly understands Kubernetes and has time for operations. Help pays off mainly in three places: before you build the cluster, because decisions on network, locations, and tooling are expensive to change later; when an existing cluster runs but nobody can say for sure whether it survives an outage; and when the knowledge sits with a single person.

That is exactly what I offer: consulting, cluster reviews, operations, and training and workshops for teams. What I do and for whom is on my page Kubernetes Expert: Consulting and Operations.

Frequently asked questions

Does Hetzner offer managed Kubernetes?

No. As of October 18, 2026, Hetzner has no managed Kubernetes service of its own. Hetzner provides servers, networks, load balancers, volumes, and object storage as well as an official cloud controller manager and CSI driver. You run the cluster yourself or through a service provider.

Is k3s suitable for production?

Yes. According to the project, k3s is a fully conformant, production-ready Kubernetes distribution, just packaged more leanly. I run my own production services on it. What matters is not the distribution but everything around it: several control plane nodes, backups, monitoring, and regular upgrades.

Why ARM servers instead of x86?

I use ARM servers of type CAX21 with 4 vCPUs (Ampere) and 8 GB of RAM. The performance is enough for my services, and the images I need exist for ARM. If your application only exists as an x86 image, use x86 servers; Kubernetes can also mix both architectures in one cluster.

What does a Kubernetes cluster on Hetzner cost?

That depends on the number and type of servers, load balancers, volumes, object storage, and traffic. Prices change, so I do not quote figures here; calculate with the current price list on hetzner.com. The bigger item is usually the working time for operations, as I show in Kubernetes Costs: What a Cluster Costs.

Do I really need three locations?

Not necessarily. Three servers in one location protect you against losing a server. If your application should also survive losing a data center, spread the control plane across three locations and accept the higher latency between them.

Where to go next

If you are still weighing whether running it yourself fits you at all, start with Kubernetes On-Premises or Cloud? and Kubernetes for SMEs: An Operating Model. If you want to get going, plan backups early with Kubernetes Backup: etcd and Volumes and rollouts with GitOps with ArgoCD: Deploy from Git.

My advice: start small, but as code from day one. A cluster you can rebuild with one command takes the fear out of every upgrade.

I explain the fundamentals of architecture, objects, and operations in depth in my Kubernetes Practical Guide (Rheinwerk Computing). You can find the official Hetzner integration in Hetzner's cloud controller manager on GitHub, and the distribution in the k3s project.

Kevin Welter

Kevin Welter

Developer, IT architect, author of technical books (Kubernetes, cloud infrastructures) and speaker. Runs his business with an AI workforce of fourteen AI employees and shows solo business owners in his community how to hire their first AI employee.

More about AI employees

Kubernetes from the basics to a production-ready cluster

Get the book