← Back

2026

Kubernetes Static Pods: Before the Cluster Exists

Most pods go through the API server. Static pods skip all of that. They are defined by files on a node's filesystem and managed entirely by the kubelet. No scheduler. No controller. No API server required. This is how the control plane bootstraps itself.

Every pod you have ever created in Kubernetes went through the same path. You submitted a manifest to the API server. The scheduler picked a node. The kubelet on that node received the assignment and started the containers. The whole system worked together to make it happen.

Static pods skip all of that. They are defined by files sitting directly on a node, read by the kubelet on that node alone. No API server involved in creating them. No scheduler deciding where they go. No controller watching over them. The kubelet reads the file and runs the pod. That is the entire mechanism.

This sounds like a limitation but it is actually a design choice with a very specific purpose. Some things need to run before the rest of Kubernetes exists. The API server itself cannot be created through the API server. The components that form the control plane need something that works at a lower level. Static pods are that something.

How it works

The kubelet watches a directory on the node's filesystem. By default this is /etc/kubernetes/manifests on clusters set up with kubeadm. Any YAML file that appears in that directory is treated as a pod manifest and started immediately. Any file that disappears from that directory causes the corresponding pod to be stopped.

The kubelet polls the directory periodically and also responds to filesystem events. Changes to an existing file cause the pod to be restarted with the new configuration. The kubelet handles this entirely on its own. There is no need to run any kubectl command. Dropping a file into the directory is enough.

Worth noting

The static pod manifest directory is configured in the kubelet's config file, typically at /var/lib/kubelet/config.yaml, under the staticPodPath field. On some distributions it is set via a command-line flag instead. To find the actual path on a node, check the kubelet process arguments or its config file directly. Assuming the default path without verifying it is a common source of confusion.

Key properties

Static pods behave differently from regular pods in several important ways. Understanding these differences matters both for working with them and for understanding what they are not suited for.

Managed by the kubelet directly

The kubelet reads pod manifests from a directory on the host filesystem and ensures those pods are running. It does not consult the API server to create them. If a static pod crashes, the kubelet restarts it. If the manifest is removed from the directory, the kubelet stops the pod. The entire lifecycle is local.

Mirror pods in the API server

Even though static pods are not created through the API server, the kubelet creates a read-only mirror object for each one. The mirror pod appears in kubectl output and shows the pod's status. You cannot delete it with kubectl. Deleting the mirror pod only deletes the mirror. The kubelet immediately recreates it as long as the manifest file is still on disk.

Tied to a single node

A static pod always runs on the node where its manifest file lives. It cannot be rescheduled to another node. If the node goes down, the pod goes with it. There is no controller watching across nodes to reschedule it elsewhere. This is intentional for components that are supposed to be node-local.

No controllers needed

Static pods require none of the higher-level Kubernetes machinery. No Deployment, no ReplicaSet, no controller manager. They exist before those things do. This is precisely what makes them suitable for bootstrapping the components that everything else depends on.

What a static pod manifest looks like

The manifest format is identical to any other pod manifest. There is nothing special about the YAML itself. The only thing that makes it a static pod is where the file lives. Drop the same file into the static pod directory and it becomes a static pod. Submit it through the API server and it becomes a regular pod.

/etc/kubernetes/manifests/my-agent.yaml

apiVersion: v1

kind: Pod

metadata:

name: my-agent

namespace: kube-system

spec:

hostNetwork: true

containers:

- name: agent

image: my-registry/agent:v1.2.0

resources:

requests:

cpu: 50m

memory: 64Mi

volumeMounts:

- name: host-data

mountPath: /data

volumes:

- name: host-data

hostPath:

path: /var/lib/my-agent

restartPolicy: Always

The namespace field in the metadata is noted but has limited effect for static pods. The kubelet creates the pod in that namespace if it exists, but the namespace must already exist. For the kube-system namespace that is always the case. For custom namespaces that need to be created through the API server first, there is a bootstrapping dependency to think through.

Control plane components as static pods

On clusters set up with kubeadm, every control plane component runs as a static pod. This is the most important real-world use of static pods by a significant margin. It is also why the manifest directory on control plane nodes contains files you should not touch without understanding exactly what they do.

kube-apiserver

The API server is itself a static pod on control plane nodes in clusters set up with kubeadm. Its manifest lives in /etc/kubernetes/manifests/kube-apiserver.yaml. The kubelet starts it before any other Kubernetes object exists. Every other component that uses the API server depends on this pod being up.

kube-controller-manager

The controller manager runs all the built-in controllers that reconcile cluster state. Deployments, ReplicaSets, Jobs and most other resource types rely on it. It runs as a static pod on control plane nodes alongside the API server.

kube-scheduler

The scheduler watches for unbound pods and assigns them to nodes. Without it, pods created through the API would stay in Pending forever. It too is a static pod, bootstrapped by the kubelet the same way as the API server and controller manager.

etcd

The cluster's backing store for all resource state. In single control plane setups, etcd runs as a static pod on the same node. In high availability setups it is often managed separately, but kubeadm defaults to running it as a static pod. Everything Kubernetes knows about the cluster lives here.

You can inspect these pods with kubectl get pods -n kube-system. Their names are suffixed with the node name rather than a random string, which is one way to identify a mirror pod versus a regularly scheduled pod. kube-apiserver-controlplane01 is a mirror pod for a static pod running on the node named controlplane01.

Things that go wrong

Static pod problems are almost always diagnosed at the node level rather than through kubectl. The API server might not be available at all if a control plane static pod is misconfigured, which rules out kubectl entirely.

Editing mirror pods

The mirror pod visible in kubectl looks editable. It is not. Any change you make through kubectl to a mirror pod is discarded immediately. The actual configuration lives in the manifest file on disk. To change a static pod you must edit the file directly on the node. The kubelet detects the change and recreates the pod.

Expecting rescheduling

A static pod will not move to another node if its node becomes unavailable. Teams that add custom static pods expecting high availability behaviour are surprised when the pod simply disappears with the node. Static pods are for node-local concerns. Anything that needs to survive node failure should use a Deployment.

Misconfiguring the manifest directory

The kubelet reads static pod manifests from a directory configured in its config file under staticPodPath. If that path is wrong or the manifest is placed in the wrong location, the kubelet ignores it silently. No error appears in kubectl. You have to check kubelet logs on the node directly to diagnose this kind of problem.

Modifying control plane static pods carelessly

The manifest files in /etc/kubernetes/manifests are live configuration. Editing them restarts the component immediately. Editing the kube-apiserver manifest on a running cluster briefly takes the API server down. Changes to control plane static pods should be made with care, with a clear understanding of what the change does before the file is saved.

Where it fits

Static pods occupy the bottom of the Kubernetes workload hierarchy. They exist before the cluster does, run without the cluster's coordination machinery and do not move between nodes. In practice this means they are used for exactly one class of things: software that needs to run on a node before Kubernetes itself is fully operational, or software so tightly coupled to a specific node that rescheduling makes no sense.

For most workloads, static pods are the wrong tool. A DaemonSet handles the one-pod-per-node pattern with all the benefits of regular Kubernetes management: rolling updates, label selectors, visibility through standard kubectl commands and integration with the rest of the API. Static pods have none of that. They are unaware of each other across nodes and cannot be managed in bulk.

The right mental model is that static pods are infrastructure below Kubernetes rather than workloads running on top of it. Understanding them matters for anyone involved in cluster administration, control plane upgrades or troubleshooting a cluster that will not come up. Knowing that the API server is just a YAML file in a directory on a node and that editing that file is how you change its configuration, is the kind of knowledge that turns a confusing incident into a solvable one.