Take five minutes to look at what you just created: a highly available control plane, the system components Syself manages for you, and the health checks that replace failing nodes automatically. Every command here only reads state, so nothing can break anything. ## Prerequisites - `KUBECONFIG` pointed at your workload cluster, with every node `Ready`. Complete [Access your new cluster](/docs/hetzner/apalla/getting-started/access-your-new-cluster) first. ## Look at your nodes You already confirmed every node is `Ready` on the previous page. Look closer at what each one is: ```console vars $ kubectl get nodes NAME STATUS ROLES AGE VERSION mycluster-abc12-xyz01 Ready control-plane 10m v1.36.3 mycluster-abc12-xyz02 Ready control-plane 9m v1.36.3 mycluster-abc12-xyz03 Ready control-plane 8m v1.36.3 mycluster-md-0-def34-xyz04 Ready 7m v1.36.3 ``` Each row is a real server running in Hetzner. The three `control-plane` nodes run Kubernetes itself: the API server your `kubectl` commands talk to, the scheduler that decides where pods run, and etcd, the database that stores all cluster state. Each control plane node holds a full copy of etcd. Writes need agreement from a majority, two out of three, so the cluster keeps accepting changes when one control plane node fails. That is what "highly available" means here, and it is the same layout you would run in production. The node with `` in the `ROLES` column is your worker. Your applications run there. If a node shows `NotReady`, give it another minute. The system pods take a moment to start on first boot. If a node stays `NotReady` for more than five minutes, check the events section below. ## See what runs in kube-system The system components run in the `kube-system` namespace. Syself installs and manages them for you; you never installed or configured any of them. ```console $ kubectl get pods -n kube-system ``` All pods should show `Running`. The names tell you what each one does: | Pods | What they do | | ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | | `etcd-...`, `kube-apiserver-...`, `kube-controller-manager-...`, `kube-scheduler-...` | Kubernetes itself. One set per control plane node, so each of these exists three times. Losing one node loses one copy, not the cluster. | | `cilium-...` | The network plugin (CNI, Container Network Interface). An agent on every node gives pods their IP addresses and routes their traffic. | | `coredns-...` | DNS inside the cluster, so pods find services by name. | | `metrics-server-...` | Collects CPU and memory usage from the nodes. Feeds `kubectl top` below. | | `ccm-...` | The Hetzner cloud controller manager. It connects the cluster to Hetzner, for example creating a Hetzner Load Balancer when you expose an application. | | `csi-...` | The Hetzner storage driver (CSI, Container Storage Interface). It attaches Hetzner volumes to nodes as persistent storage for your pods. | You may know `kube-proxy` from other clusters. It is not here: Cilium handles Service traffic directly in the kernel, so there is no kube-proxy to run. A pod in `Pending` for more than a few minutes usually means the node it needs is not yet ready. `kubectl get pods -A` shows pods across all namespaces; on a fresh cluster, nearly everything lives in `kube-system`. ## Check node health conditions ```console $ kubectl describe node ``` Look at the `Conditions` section near the bottom of the output. On a healthy node, `Ready` is `True` and the pressure conditions (`MemoryPressure`, `DiskPressure`, `PIDPressure`, `NetworkUnavailable`) are `False`. These conditions are more than a status display. A health daemon on every node watches kernel logs, `kubelet` (the agent that runs on every node and manages its pods), the container runtime, disk state, and clock sync, and records problems as conditions on the node. Syself Autopilot acts on them. Pressure on its own does not make Syself Autopilot replace a node; it means the node is running low on that resource. Replacement is driven by the `Ready` condition staying `Unknown` or `False`, or by the health daemon reporting a hard failure, for example a read-only filesystem, a kernel deadlock, or a tampered OS image. When that happens, Syself Autopilot reboots the server first. If the node is still unhealthy, Syself Autopilot drains it (moving its pods to other nodes) and replaces the server with a fresh one. There is no step where you SSH into a broken node and repair it by hand. [Self-healing and node replacement](/docs/hetzner/apalla/concepts/operations/self-healing-and-node-replacement) explains the full sequence and its timeouts. ## See the machines behind the nodes Every node is backed by a Machine object in the management cluster, not the workload cluster you have been querying so far. The Machine is the record Syself Autopilot works from: which server backs the node, and what state it is in. Point this one command at the file you saved back in [Access the management cluster](/docs/hetzner/apalla/getting-started/access-the-management-cluster), the one `KUBECONFIG` pointed at before you switched it to the workload cluster on the previous page: ```console $ kubectl --kubeconfig= get machines ``` Each machine shows its phase. `Running` means the server is provisioned and has joined the cluster. When Syself Autopilot replaces a failed node, this is where you see it: the old Machine goes away and a new one moves through `Provisioning` to `Running`, with no input from you. ## Check events Events record what has happened in the cluster and are the first place to look when something is off. ```console $ kubectl get events -n kube-system --sort-by='.lastTimestamp' ``` On a fresh, healthy cluster you mostly see informational events about pods starting. Warnings appear in the `TYPE` column as `Warning`. A stream of `Warning` events for the same object usually points to a real problem. ## Check resource usage Once `metrics-server` is running (usually within a minute of cluster creation), you can see how much CPU and memory each node uses: ```console $ kubectl top nodes ``` And per-pod usage: ```console $ kubectl top pods -A ``` On a fresh cluster the numbers are low. The system components leave most of each node's capacity for your applications. ## Before you move on Check that your cluster is in good shape before deploying an application: - All nodes show `Ready` with no pressure conditions. - All pods in `kube-system` show `Running`. - No `Warning` events are repeating for the same object. - `kubectl top nodes` returns data (not `error: metrics not available yet`). If everything checks out, you have a running, highly available cluster with networking, DNS, storage, and self-healing in place. The next step puts it to work: [Deploy your first app](/docs/hetzner/apalla/getting-started/deploy-your-first-app). ## Related - [Deploy your first app](/docs/hetzner/apalla/getting-started/deploy-your-first-app) - [Reference: node health conditions](/docs/hetzner/apalla/reference/node-health-conditions) - [Concepts: self-healing and node replacement](/docs/hetzner/apalla/concepts/operations/self-healing-and-node-replacement) - [Concepts: networking](/docs/hetzner/apalla/concepts/internals/networking) - [Troubleshooting: cluster creation fails](/docs/hetzner/apalla/clusters/troubleshooting/cluster-creation-fails)