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.