— Kubernetes cluster, 2:17 AM —
You're cleaning up kube-system. Routine task.
You spot a pod with a weird name. Looks stuck. Looks like a leftover.
You delete it:
$ kubectl delete pod kube-scheduler-control-plane -n kube-system
✅ pod "kube-scheduler-control-plane" deleted
You refresh. The pod is back.
You delete it again. It comes back again.
You --force delete it. Still comes back.
Nothing looks wrong. The cluster is healthy. The pod refuses to die.
You don't know why. You're about to.
This is one of the most disorienting things you can experience in Kubernetes. You delete something. It comes back. You didn't write a Deployment. There is no ReplicaSet. The pod just refuses to leave.
The answer has nothing to do with Deployments or ReplicaSets. It has everything to do with a concept that most tutorials either explain wrong or skip entirely — and that gap follows engineers from their first cluster all the way into senior-level interviews.
The Interview Question
Three months after that exact situation, you're in an interview for a senior Kubernetes engineer role. The interviewer puts down their pen and asks:
“If kubelet is a worker node component, how does it manage Static Pods on the master node?”
Most people pause here. Not because the answer is technically complicated. But because the question contains a wrong assumption they absorbed from a diagram and never questioned.
Fix the assumption and the answer is immediate. Keep the assumption and you spend two minutes constructing an elaborate non-answer while the interviewer waits.
Let's fix it.
What Every Tutorial Gets Wrong
Here's the diagram you've seen in 90% of Kubernetes intro courses:
What every tutorial shows: Master Node Worker Node ├── API Server ├── kubelet ← "kubelet lives here" ├── Scheduler ├── kube-proxy ├── Controller Manager └── Application Pods └── etcd Logical conclusion: kubelet = worker node thing. Understandable. Also wrong.
Makes sense. Master node does the thinking. Worker nodes do the running. kubelet manages pods on workers. Clean separation. Logical model.
Most people build on top of that diagram and produce an answer like this:
The interviewer is not satisfied.
Interviewer keeps going:
❓ “If kubelet runs on every node — what is actually different about a control-plane node versus a worker node?”
❓ “What is the difference between a Static Pod and a DaemonSet? They both seem to pin pods to nodes.”
❓ “If the API Server is itself a pod — and pods need the API Server to be created — how does a cluster ever boot for the first time?”
❓ “What is a mirror pod, and why does kubectl delete not permanently remove a static pod?”
❓ “What happens to the cluster if someone deletes a file from /etc/kubernetes/manifests/ on a Friday afternoon?”
The problem: this diagram shows roles, not what is actually installed on each node. It is a simplified teaching model. And one piece missing from that diagram is responsible for every mistake this article covers.
The Mental Model — Read This Before Anything Else
Before we go into any technical depth, here is the analogy that makes everything click. Think of how food delivery works.
| Food Delivery World | Kubernetes World |
|---|---|
| DoorDash app — the interface you use to order | API Server — the normal interface for creating pods |
| Dispatcher who assigns orders to drivers | Scheduler — picks which node a pod lands on |
| Kitchen staff on every floor of every building | kubelet — runs on every node, manages pods there |
| Ordering through the app → driver delivers | Normal pod — goes through API Server → Scheduler → kubelet |
| Restaurant owner's family walking in the back door | Static Pod — bypasses the app, goes directly to kubelet |
| Back door key + a note on the fridge | /etc/kubernetes/manifests/ — the file kubelet reads |
| App shows the family's meal as a read-only entry | Mirror pod — visible in kubectl but kubelet controls it |
| Nobody can cancel the owner's family order through the app | kubectl delete doesn't permanently remove a static pod |
Hold that model. Everything below maps to the same pattern — except with YAML files and systemd services instead of fridge notes and back doors.
What kubelet Actually Is
Here is the one sentence that fixes the wrong assumption:
kubelet is a node agent. It runs on every node in a Kubernetes cluster — including the control-plane node.
It is not a worker-node component. It never was. The tutorials that drew it only on the worker side were simplifying. That simplification has been quietly causing confusion at every level — beginners, mid-level engineers, and seniors who have been using Kubernetes for years without ever questioning the diagram.
The corrected picture:
What actually runs on each node: Control Plane Node Worker Node ├── kube-apiserver ├── kubelet ├── kube-scheduler ├── kube-proxy ├── kube-controller-manager └── Application Pods ├── etcd ├── kubelet ← yes, here too └── kube-proxy
The difference between a control-plane node and a worker node is not about which software is installed. It is about which control-plane services are present and what workloads are allowed to run there. kubelet is on both types of node. Always has been.
Q1: Does kubelet Only Run on Worker Nodes?
The wrong answer: yes, kubelet is a worker-node component.
This is like saying building managers only work at branch offices, not at headquarters. Every building has one — doesn't matter how important the building is. The fact that the HQ has more critical things happening inside doesn't mean nobody manages the building.
kubelet is the building manager. It runs on every node. On worker nodes it manages application pods. On the control-plane node it manages the control-plane pods — API Server, etcd, Scheduler, Controller Manager. Same job. Different tenants.
🚨 Interview Trap
Q2: What Are Static Pods?
The wrong answer: “pods that don't move between nodes.”
That is a DaemonSet — a scheduling policy that pins one pod per node. A Static Pod has nothing to do with movement. The word “static” refers to how the pod is defined: by a static file on disk, not through a dynamic API call. That is the entire distinction.
Normal Pod path:
kubectl apply -f pod.yaml
↓
API Server (validates, stores in etcd)
↓
Scheduler (picks a node)
↓
kubelet on that node (starts the pod)
─────────────────────────────────────
Static Pod path:
cp nginx.yaml /etc/kubernetes/manifests/
↓
kubelet (detects file, starts the pod)
↓
Done. Nothing else involved.
A Static Pod is any pod defined by a YAML manifest file placed in a directory that kubelet watches. On most clusters, that directory is:
/etc/kubernetes/manifests/Drop a file in — pod starts. Remove the file — pod stops. No kubectl apply. No API Server involved. No Scheduler assignment. kubelet handles the full lifecycle on its own.
You drop a YAML file here:
/etc/kubernetes/manifests/nginx-static.yaml
kubelet is watching that directory.
↓
kubelet detects the new file
↓
Pod starts on this node.
↓
No kubectl apply. No API Server call. No Scheduler.
↓
kubectl get pods shows it — as a read-only mirror.
🧠 Memory Trick
Q3: Who Actually Starts kube-apiserver?
The wrong answer: “the control plane” or “Kubernetes itself.”
Kubernetes cannot start itself any more than a restaurant can cook its own first customer. Someone has to turn the lights on before any of the normal operations begin.
Go look at what lives in the manifests directory on a real cluster:
ls /etc/kubernetes/manifests/
etcd.yaml
kube-apiserver.yaml
kube-controller-manager.yaml
kube-scheduler.yamlThose four files start the entire control plane. Not a Helm chart. Not a Deployment. Not some hidden bootstrap service. Four YAML files in a directory that kubelet is watching.
When the node boots, kubelet starts as a systemd service — it needs nothing else to run. It reads those four files. It starts all four pods directly, as static pods. The cluster comes alive from those four files and nothing else.
kube-apiserver starts because kube-apiserver.yaml is in that directory. That is the complete answer.
⚡ Pro Tip
kube-apiserver-control-plane, etcd-control-plane. That suffix is kubelet's naming convention for static pods. Any time you see a pod name ending with the node name, kubelet created it from a manifest file on disk.Q4: The Bootstrap Problem
This is where it really clicks — or where most explanations quietly skip the hard bit.
In Kubernetes, creating a pod normally requires the API Server. The Scheduler assigns it to a node. kubelet starts it. That is the chain.
But the API Server is itself a pod. So is etcd. So is the Scheduler.
So: if pods need the API Server to be created — but the API Server is a pod that needs to be created — who goes first? You cannot use the thing to create the thing. The cluster would never boot. This is called the bootstrap problem. It is a genuine circular dependency with no obvious solution.
Static Pods are the solution.
Node boots up
↓
kubelet starts (systemd service — needs nothing else to run)
↓
kubelet reads /etc/kubernetes/manifests/
↓
etcd.yaml → etcd pod starts
kube-apiserver.yaml → API Server starts
kube-scheduler.yaml → Scheduler starts
kube-controller-manager.yaml → Controller Manager starts
↓
Cluster is alive. Four pods. Four files. That's the whole foundation.
kubelet is a systemd service. It starts on node boot. It does not need the API Server — it reads manifest files from disk. Those files tell it to start etcd, kube-apiserver, kube-scheduler, and kube-controller-manager. kubelet starts all four as static pods. No API Server involved in any of that.
Once those four pods are running, the API Server is alive and the cluster handles everything else through normal channels. But the first boot is kubelet, working completely alone, reading four files.
😅 Senior Engineer Confession
Q5: Why Does kubectl delete Not Work on Static Pods?
Back to the pod that wouldn't die from the opening.
You run kubectl delete pod nginx-static-control-plane. The pod disappears. Three seconds later it is back.
This is the equivalent of crossing someone's name off the building directory and wondering why they still live in the apartment. The directory is decorative. The person is still there.
Here is what is actually happening. What you see in kubectl get podsfor a static pod is called a mirror pod — a read-only reflection that kubelet registers with the API Server so you can observe the pod using standard tools. But the API Server does not control it. kubelet does.
When you delete the mirror pod, you have removed the reflection. kubelet immediately re-registers it because the manifest file is still on disk and the pod is still running. Nothing changed on kubelet's side. The mirror reappears within seconds.
The only way to actually stop a static pod is to remove the manifest file:
sudo rm /etc/kubernetes/manifests/nginx-static.yamlFile gone → kubelet stops managing it → pod stops → mirror disappears and stays gone.
🚨 Interview Trap
--force --grace-period=0.” You cannot — not permanently. Force delete removes the mirror faster. kubelet recreates it within seconds because the manifest file is still there. The --force flag has no effect on static pods. Remove the file.Q6: What Happens If a Static Pod Crashes at 3 AM?
kubelet does not just start static pods. It keeps watching them.
If the container inside a static pod crashes, kubelet detects it and restarts it. Automatically. No alert needed. No human needed. No other Kubernetes component needed.
Static pod container crashes at 3 AM
↓
kubelet detects the failure (watching continuously)
↓
kubelet restarts the container (no human, no other component needed)
↓
Pod is running again
↓
You wake up. Everything is fine. You never know it happened.
This matters enormously for the control plane. If kube-apiserver crashes at 3 AM — bad memory pressure, a node hiccup, a kernel OOM event — kubelet on the control-plane node catches it and brings it back on its own. By the time anyone opens a laptop, the cluster has already recovered.
🔥 Production Reality
Create Your First Static Pod
The best way to understand this is to feel it directly. On a kubeadm cluster or any lab environment, these steps work exactly as described.
Step 1 — Create the manifest file
sudo nano /etc/kubernetes/manifests/nginx-static.yamlapiVersion: v1
kind: Pod
metadata:
name: nginx-static
spec:
containers:
- name: nginx
image: nginx:latestSave the file. Do not run kubectl apply. Do not restart anything. Just save the file and wait five seconds.
Step 2 — Verify it started
kubectl get pods
NAME READY STATUS NODE
nginx-static-control-plane 1/1 Running control-planeThe node name is appended automatically: nginx-static-control-plane. That is kubelet's naming convention. Any pod whose name ends with the node name is a static pod managed directly by kubelet from a manifest file on disk.
Step 3 — Try to delete it the wrong way
kubectl delete pod nginx-static-control-planeWait a few seconds. Run kubectl get pods again. It is back. Now you have felt it directly instead of just reading about it.
Step 4 — Delete it the right way
sudo rm /etc/kubernetes/manifests/nginx-static.yamlWait a few seconds. Pod is gone. Stays gone.
🧠 Memory Trick
Two Production Disasters
Disaster 1: The Deletion Loop (30 people, startup, staging)
A junior DevOps engineer doing routine kube-system cleanup. They run kubectl get pods -n kube-system and spot pods with names like kube-scheduler-control-plane. Never seen these before. Looks like something stuck from a previous operation.
They delete the pod. It comes back. They delete it six more times. They add --force --grace-period=0. Still comes back. They open a Slack thread: “I can't delete this pod — is the cluster broken?”
Senior engineer joins 20 minutes later. First question:“SSH into the control-plane node and run ls /etc/kubernetes/manifests/.”
There it is. kube-scheduler.yaml. kubelet had been doing its job the entire time. The pod was not stuck — it was the Scheduler, running as a static pod. Had they successfully deleted it, new pods would have stopped being scheduled across the cluster. The deletion loop was the safe outcome.
Time lost: 25 minutes. Root cause: one missing piece of context about static pods.
Disaster 2: The Manifest Edit That Took Down the API Server
A platform team doing a planned upgrade. They need to add a new audit policy flag to kube-apiserver. Standard procedure on this team: edit the manifest in place, let kubelet pick up the change.
An engineer SSHes into the control-plane node and opens /etc/kubernetes/manifests/kube-apiserver.yaml in vim. Types the new flag. Makes a one-character typo in the flag name. Saves the file.
kubelet detects the file change in under two seconds. Restarts kube-apiserver with the broken config. kube-apiserver fails to start.
kubectl stops responding. The team cannot use kubectl to diagnose the problem because there is no API Server to talk to. They have to SSH back to the control-plane node, open the manifest file directly, find the typo, fix it, save. kubelet picks up the corrected file and restarts kube-apiserver. Cluster back online. Total downtime: 8 minutes.
🔥 Production Reality
kube-apiserver.yaml and introduce a syntax error, the API Server goes down before you finish blinking. Always validate YAML before saving to the manifests directory. Always have a direct SSH session open to the control-plane node before touching these files — because if the API Server goes down, kubectl goes with it.The Wall of Shame
Six mistakes. All extremely common. Most made by experienced engineers.
1. Running kubectl delete on a static pod and expecting it to stay deleted
“This is the Kubernetes equivalent of evicting a tenant by crossing their name off the door buzzer. They still live there. kubelet puts the name back in five seconds. The buzzer is decorative.”
What happens: Mirror pod disappears and immediately reappears. Nothing changes for the actual pod.
Fix: Remove the file from /etc/kubernetes/manifests/.
2. Editing the mirror pod in kubectl to change the pod's configuration
“This is like trying to change what an actor is doing by editing their Wikipedia page. The page updates from the actor — not the other way around. The mirror is a reflection. Reflections do not control the object.”
What happens: Kubernetes rejects or reverts the edit. The manifest file on disk is unchanged.
Fix: Edit the file directly in /etc/kubernetes/manifests/ on the node.
3. Assuming kubelet only runs on worker nodes
“This assumption is so common it has its own recurring Slack thread format: ‘Why is kubelet running on my master node? Did kubeadm do something wrong?’ Nothing is wrong. It is supposed to be there. It has always been there.”
What happens: Confusion, debugging time wasted, occasionally someone tries to remove kubelet from the control-plane.
Fix: kubelet is a node agent. It runs on every node, full stop.
4. Editing manifests without a direct SSH session already open
“Editing kube-apiserver.yaml through a kubectl exec session. The exec goes through the API Server. The moment kube-apiserver restarts with bad config, your exec session dies and you cannot get back in via kubectl. You have locked yourself out using the building's own electronic lock.”
What happens: API Server goes down, kubectl stops working, you need direct node access to fix it anyway.
Fix: Always have SSH open to the control-plane node before touching these files.
5. Confusing Static Pods with DaemonSets
“A DaemonSet is a scheduling policy: run one pod on every node in the cluster. A Static Pod is a file on a disk: run this pod on this node because the file is here. One goes through the API Server. The other bypasses it entirely. They are not the same concept with different names.”
What happens: Wrong interview answers, incorrect architecture decisions about control-plane deployment.
Fix: DaemonSets → API Server → Scheduler. Static Pods → file on disk → kubelet. Different path entirely.
6. Not knowing where to look when a control-plane component won't start
“Spending 40 minutes describing the problem in Slack when you could have opened the filing cabinet in 30 seconds. The manifests directory is the filing cabinet. kubelet logs are the incident report. Between those two things you can diagnose almost any control-plane startup failure.”
What happens: Long incident resolution times that should be 5-minute fixes.
Fix: First stop — ls /etc/kubernetes/manifests/ and journalctl -u kubelet -f.
Best Practices
- Never touch manifest files without direct SSH access to the control-plane node. If the API Server goes down mid-edit, kubectl goes with it. You will need SSH to fix it anyway — open it before you start.
- Validate YAML before saving to the manifests directory. Use
kubectl --dry-run=client -f file.yamlbefore moving it in, or runyamllinton it. kubelet applies immediately with no confirmation dialog. - Recognize static pods by their name suffix. Pod name ends with the node name (
-control-plane,-node01, etc.) = static pod. Manage it through the file, not through kubectl. - Use
journalctl -u kubelet -fwhen a control-plane component won't start. The manifest might be syntactically valid but kubelet might be rejecting a specific flag. kubelet logs will tell you exactly why. - Do not use static pods for application workloads. Static pods on the control-plane are for control-plane components only. For everything else — Deployments, DaemonSets, StatefulSets.
- Confirm the manifests directory path if something seems off. The default is
/etc/kubernetes/manifests/but it is configurable in the kubelet config. Runcat /var/lib/kubelet/config.yaml | grep staticPodPathto confirm what your cluster is actually watching.
FAQ
Is kubelet a control-plane component or a worker node component?
Neither. kubelet is a node agent — it runs on every node in the cluster regardless of its role. The control-plane / worker distinction describes which Kubernetes components are present, not whether kubelet is installed. kubelet is always installed. Always running. On every node.
Can Static Pods run on worker nodes too, or only the control-plane?
Any node. If a file is in the manifests directory on a worker node, kubelet on that worker starts it as a static pod. The reason you mostly see static pods on the control-plane is that control-plane components are deployed this way — not because static pods are limited to control-plane nodes.
How does kubeadm create Static Pods when initializing a cluster?
kubeadm init generates the four manifest files — etcd.yaml, kube-apiserver.yaml, kube-scheduler.yaml, kube-controller-manager.yaml — and drops them into /etc/kubernetes/manifests/. kubelet is already running (started by systemd before kubeadm ran). It detects the new files and starts all four pods. The cluster is alive. That is literally all kubeadm does for the control plane.
What is the difference between a mirror pod and a static pod?
A static pod is the actual pod — managed by kubelet from a file on disk. A mirror pod is a read-only copy of it that kubelet registers with the API Server so the pod appears in kubectl get pods. The mirror is a reflection. The static pod is the object. They are not two different things — one is the real thing, the other is how you observe it.
What happens if I accidentally delete a manifest file from /etc/kubernetes/manifests/?
kubelet detects the file is gone and stops the pod. If you delete kube-apiserver.yaml, the API Server pod stops immediately. kubectl stops responding because there is no API Server. You need SSH on the control-plane node to restore the file. This is why backups of those four manifest files belong in version control.
People Also Ask
Can you scale Static Pods?▼
Can Static Pods use ConfigMaps?▼
Can Static Pods use Secrets?▼
Can Static Pods mount PVCs?▼
hostPath volumes (a directory on the node's filesystem) or emptyDir, but not PVCs. This is exactly why etcd stores its data in a hostPath volume at /var/lib/etcdrather than a PVC — it cannot depend on Kubernetes storage infrastructure to store the data that Kubernetes storage infrastructure depends on.Can Helm deploy Static Pods?▼
Why doesn't the Scheduler schedule Static Pods?▼
Can DaemonSets replace Static Pods?▼
How does Talos Linux deploy the control plane?▼
/etc/kubernetes/manifests/. kubelet — running as a system service on Talos — detects the files and starts etcd, kube-apiserver, kube-scheduler, and kube-controller-manager as static pods. The difference is that Talos manages the entire node OS as an immutable, API-driven system: manifest files and kubelet configuration are controlled through the Talos API rather than SSH and a text editor, which eliminates the “accidentally deleted a manifest file via vim” class of incident entirely.Interview Corner
Questions You Should Be Able to Answer at Any Level
Q: Does kubelet run only on worker nodes?
No. kubelet runs on every node — worker and control-plane alike. It is a node agent whose job is to manage pods on whatever node it is installed on.
Q: What is a Static Pod?
A pod defined by a YAML manifest file placed in a directory that kubelet watches (default: /etc/kubernetes/manifests/). kubelet creates and manages it directly — no API Server call, no Scheduler, no kubectl required.
Q: Who manages Static Pods?
kubelet. Exclusively. The API Server holds a mirror pod — a read-only reflection — but it cannot modify or delete the static pod. kubelet owns the full lifecycle: create, restart, delete.
Q: How does kube-apiserver start when the cluster boots?
kubelet reads kube-apiserver.yaml from /etc/kubernetes/manifests/ and starts it as a static pod. The API Server does not start itself — kubelet starts it before the API Server even exists.
Q: Why are control-plane components deployed as Static Pods?
The bootstrapping problem. Normal pods need the API Server to be created. But the API Server is itself a pod. Static Pods break the circular dependency — kubelet brings the entire control plane up from disk files without needing any Kubernetes component to already be running.
Q: Can you permanently delete a Static Pod with kubectl?
No. kubectl delete pod removes the mirror. kubelet recreates it immediately because the manifest file is still on disk. To actually remove a static pod, delete the manifest file from /etc/kubernetes/manifests/.
Q: What is a mirror pod?
A read-only representation of a static pod that kubelet registers with the API Server. It makes the pod visible in kubectl, but it cannot be used to control or modify the pod. Editing or deleting the mirror has no lasting effect.
Q: How do you identify a Static Pod from kubectl output?
The node name is appended to the pod name — e.g., kube-apiserver-control-plane. That suffix is kubelet's naming convention. No other pod type does this automatically.
🎤 The 60-Second Answer
🎤 Say This Out Loud Until You Own It
“The question contains a misconception. kubelet isn't a worker-node component — it's a node agent that runs on every node in the cluster, including the control-plane node.
On the control-plane node, kubelet manages what are called Static Pods: pods defined by YAML files placed in /etc/kubernetes/manifests/. kubelet watches that directory. A file appears — pod starts. File is removed — pod stops. No API Server, no Scheduler, no kubectl needed for any of that.
This is how Kubernetes solves the bootstrapping problem. The four control-plane components — etcd, kube-apiserver, kube-scheduler, kube-controller-manager — are all Static Pods. When the node boots, kubelet starts as a systemd service, reads their manifest files from disk, and starts all four directly. The API Server cannot start itself. kubelet starts it.
If you try to delete a static pod with kubectl, it comes back immediately. kubectl deletes the mirror pod — a read-only reflection in the API Server. kubelet recreates the mirror within seconds because the manifest file is still there. The only way to actually stop a static pod is to remove the file from disk.”
If you can say that without looking at notes, you genuinely understand it. That is the offer.
Key Takeaways
- →kubelet is a node agent — it runs on every node, including the control-plane node.
- →Static Pods are managed by kubelet via YAML files in /etc/kubernetes/manifests/.
- →File added = pod starts. File removed = pod stops. No API Server needed.
- →The four control-plane components are all static pods — this solves the bootstrap problem.
- →kubectl delete on a static pod removes only the mirror. kubelet recreates it instantly.
- →The -<node-name> suffix on a pod name is kubelet's signature on static pods.
- →Editing a manifest file applies immediately. No confirmation. Validate before you save.
- →kubelet auto-restarts crashed static pods — this is how the control plane self-heals at 3 AM.
The pod that wouldn't die at 2:17 AM was not broken. It was doing exactly what it was designed to do. kubelet was watching the manifest file on disk, saw that the pod should be running, and put it back every time you deleted the mirror. The cluster was working correctly. You just didn't have the model yet.
The interview question — “if kubelet is a worker node component, how does it manage static pods on the master?” — is not really about static pods. It is about whether you understood what kubelet actually is. Fix that one sentence and everything else follows: the static pods, the bootstrap problem, the deletion behavior, the mirror pod, the self-healing.
One wrong sentence in a tutorial caused all of it. One correct sentence clears all of it.
About the author
Ravi Kapoor
Senior DevOps Engineer & Technical Writer
Ravi is a senior DevOps engineer with 9 years of experience building cloud-native infrastructure at Atlassian and multiple fintech companies. CKA and AWS Solutions Architect Professional certified, he has managed Kubernetes clusters serving millions of daily users and contributes to open-source tooling.
Targeting a Kubernetes or DevOps Role?
AiResumeFit matches your resume to Kubernetes, cloud, and DevOps job descriptions — improving your ATS score in seconds.
Optimize My Resume →