A pod created by a Deployment, a DaemonSet, or a Job exists because a controller, via the API server, decided so. A static pod follows a radically different logic: it’s managed directly by a node’s kubelet, from a local manifest file, never going through the API server to exist.

What makes a static pod different

The kubelet continuously watches a local directory (/etc/kubernetes/manifests by default): any YAML file dropped there becomes a directly managed pod, with no controller or scheduler involved. This exact mechanism is what lets the control plane itself run as ordinary Kubernetes pods: kube-apiserver, etcd, kube-scheduler often run as static pods on a kubeadm cluster, an elegantly solved chicken-and-egg problem (the control plane starts before an API server is even available to manage it).

# Any file dropped here becomes a pod managed
# directly by the kubelet, no API server involved
ls /etc/kubernetes/manifests/
# etcd.yaml  kube-apiserver.yaml  kube-scheduler.yaml

The mirror pod: a read-only window into the API

The kubelet publishes a read-only copy of every static pod into the Kubernetes API, a “mirror pod,” visible via kubectl get pods exactly like any other pod. This visibility is misleading: the mirror pod is only a reflection, never the source of truth, and modifying or deleting this reflection via the API has no effect on the real static pod managed by the kubelet.

# The mirror pod shows up normally,
# but deleting this reflection deletes nothing real
kubectl delete pod kube-apiserver-node1 -n kube-system
# The kubelet immediately recreates the pod,
# since the local manifest file still exists

Why kubectl delete fails silently

An attempt to delete a static pod via kubectl delete does delete the mirror pod in the API, but the kubelet, still watching the local manifest file, immediately recreates the real pod, republishing a new mirror pod almost instantly. This behavior looks like a command silently failing, when it actually succeeds perfectly on what it actually controls (the mirror pod), never touching the source of truth (the manifest file and the process the kubelet manages).

The right way to modify or delete a static pod

Modifying or deleting a static pod requires acting directly on the manifest file, on the node itself, never via the Kubernetes API.

# The only action with a real effect:
# modifying or moving the local manifest file
mv /etc/kubernetes/manifests/my-static-pod.yaml /tmp/
# The kubelet detects the file is gone
# and stops the corresponding pod

The kubelet watches this directory continuously: moving, modifying, or deleting the file triggers the same action on the pod side, almost immediately, never going through kubectl.

Takeaway

A static pod is managed directly by the kubelet from a local manifest file, an entirely different mechanism from API-server-managed pods, and that’s exactly what lets the control plane itself run before an API server is even available. The mirror pod visible via kubectl get pods is only a read-only reflection: deleting it via the API does nothing lasting, since the kubelet immediately recreates the real pod as long as the manifest file exists. The only action that matters happens on the node itself, a detail that avoids a classic confusion when troubleshooting a self-managed Kubernetes cluster.