beginner~4h

Core Components: API Server, etcd, Scheduler, Controller Manager, Kubelet & Kube-Proxy

This chapter goes deeper into each of the six components. Interviewers frequently ask you to walk through what happens when you run kubectl apply -- this chapter gives you precision on each of the six

Learning objectives

  • Name each core control plane and node-level component, and state its one specific job.
  • Explain why the API server is the ONLY component that talks to etcd directly.
  • Trace a single request through every core component it touches, from kubectl to a running container.

📖 Story

Imagine an office where only the front desk is allowed to open the filing cabinet — every other department, no matter how important, has to go through the front desk to read or update any file, rather than reaching into the cabinet themselves. This isn't bureaucratic inefficiency for its own sake — it means the front desk can enforce consistent rules (who's allowed to see what, validating that a request makes sense) on every single access, instead of trusting every department to enforce those rules correctly on their own.

The six core components, precisely

  • API server — the front desk. The ONLY component that talks to etcd directly; every read and write to cluster state goes through it, and it enforces authentication, authorization, and validation on every request.
  • etcd — the filing cabinet (covered in Chapter 1) — the cluster's actual stored state.
  • Scheduler — decides which worker node a newly-created Pod should run on, based on that Pod's resource needs and each node's available capacity (and other constraints, covered in the Scheduling chapter).
  • Controller manager — runs the various control loops (the ReplicaSet controller, the Deployment controller, and many others) that continuously reconcile actual state with desired state.
  • kubelet — runs on every worker node; takes instructions for Pods assigned to its node and actually starts/stops their containers via the container runtime.
  • kube-proxy — runs on every worker node; implements the networking rules that let Kubernetes Services (covered in the Networking chapters) actually route traffic to the right Pods.

Why centralizing all etcd access through one component matters

Because the API server is the sole gatekeeper, it's the ONE place authentication, authorization (RBAC, covered in the Security chapter), and validation rules need to be enforced — every other component, and every external tool like kubectl, goes through this same, consistently-enforced front door, rather than each needing its own separate security logic for talking to etcd directly.

The scheduler's decision process

When a new Pod has no assigned node yet, the scheduler evaluates every candidate worker node against that Pod's requirements: does the node have enough free CPU/memory (its resource requests), does it satisfy any node-affinity or taint/toleration rules (covered fully in the Scheduling chapter), and among all nodes that qualify, which one scores best by the scheduler's internal ranking (spreading load evenly is a common default consideration). Once decided, the scheduler writes that binding decision back through the API server into etcd.

The controller manager's watch mechanism

Rather than repeatedly polling etcd on a fixed interval, controllers use the API server's watch mechanism — an efficient, long-lived connection that pushes notifications the instant a relevant object changes, rather than the controller needing to repeatedly ask "has anything changed yet?" This is what makes Kubernetes' reconciliation feel near-instantaneous (a crashed Pod gets noticed and replaced within seconds) despite being built on a fundamentally polling-adjacent control-loop pattern underneath — the watch mechanism is what removes the actual polling delay.

kubelet and kube-proxy, per-node

Each node's kubelet independently watches (again, via the API server's watch mechanism) for Pods assigned specifically to its own node, and manages their entire lifecycle locally — starting containers, running health checks, reporting status back. kube-proxy, separately, watches for Service and Endpoint changes and updates that node's networking rules (commonly via iptables or IPVS, extending directly from the Docker Networking chapter's iptables-based port mapping) so traffic to a Service correctly reaches one of its backing Pods, wherever they're actually running.

  1. kubectl apply -f deployment.yaml sends an HTTP request to the API server.
  2. The API server authenticates the request, checks authorization (RBAC rules), validates the object's structure, and writes the new Deployment object into etcd.
  3. The controller manager's Deployment controller, watching for exactly this kind of change via the API server, notices the new Deployment and creates a corresponding ReplicaSet object (again, through the API server, into etcd).
  4. The ReplicaSet controller (also inside the controller manager) notices the new ReplicaSet needs Pods, and creates Pod objects with no node assigned yet.
  5. The scheduler, watching for unscheduled Pods, evaluates candidate nodes and assigns one, writing that decision back through the API server.
  6. The assigned node's kubelet, watching for Pods scheduled to its own node, notices the assignment and instructs the local container runtime to start the container(s).
  7. kube-proxy on every node updates its local networking rules if this Pod is a backend for any existing Service, ensuring traffic can reach it once it's ready.
  • A kubectl get pods command timing out — almost always an API server or etcd health problem, not a worker-node issue, since every kubectl read goes through the API server.
  • A Pod stuck in Pending state indefinitely — commonly a scheduler problem: no candidate node satisfies the Pod's resource requests or scheduling constraints, and the scheduler has nowhere valid to place it.
  • A crashed Pod being automatically replaced within seconds — the controller manager's watch-based reconciliation noticing the discrepancy almost immediately, rather than on some longer polling interval.
  • A newly-created Service not routing traffic correctly to its Pods — often traced to a kube-proxy issue on the relevant nodes, since it's specifically responsible for translating Service definitions into actual per-node networking rules.
  • A large cluster's API server showing high latency under heavy load — a signal that control plane capacity (covered in Chapter 1) needs attention, since every single one of these core components' interactions ultimately funnels through it.
  • When diagnosing any cluster issue, identify which core component is actually responsible for the behavior in question first — a scheduling problem, an networking problem, and an API-availability problem all look different and point to entirely different components.
  • Never attempt to have anything talk to etcd directly, bypassing the API server — this defeats the consistent authentication/authorization/validation enforcement the API server exists to provide.
  • Monitor each core component's health independently (API server latency, etcd health, scheduler and controller-manager activity) rather than only monitoring application-level metrics, since a control-plane-level issue often manifests as a vague, confusing application-level symptom otherwise.
  • Understand kubelet's per-node, independent operation — a problem specific to one node's kubelet affects only that node's Pods, not the whole cluster, which is a useful diagnostic signal in itself.
  • Rely on the watch-based reconciliation model's near-instant reaction time as a genuine operational assumption (a crashed Pod really will be replaced within seconds), rather than building unnecessary manual remediation around a slower assumption.

⚠️ Why this keeps happening

A Pod stuck in Pending produces no application logs at all — because its containers never actually started — which pushes engineers used to debugging application code toward looking in the wrong place entirely, when the actual answer lives in the scheduler's decision-making, not the application.

  • Debugging a Pending Pod by looking at application logs, when there are none to find yet, since the container never started — kubectl describe pod (showing scheduling events) is the actual right first step, not kubectl logs.
  • Assuming a networking problem is always a kube-proxy issue, when it could equally be a DNS problem, a Service misconfiguration, or a Network Policy blocking traffic (covered in the Networking chapters) — narrowing to the wrong component wastes diagnostic time.
  • Not realizing the controller manager runs MANY distinct controllers bundled together (Deployment, ReplicaSet, Node, and others), and assuming "the controller manager is fine" broadly when actually one specific controller within it is misbehaving.
  • Treating the API server as infinitely scalable, and being surprised when a very large cluster with many objects and frequent watches shows degraded API latency under load.
  • Confusing kubelet's per-node responsibility with a cluster-wide concern — a kubelet-level bug or misconfiguration on one specific node affects only that node, not the whole cluster, and should be diagnosed and fixed at that scope.
  • Monitor API server request latency and error rates as a primary control-plane health signal — since literally everything (kubectl, controllers, kubelet, kube-proxy) depends on it, its performance is a genuine bottleneck ceiling for the whole cluster.
  • Keep the number of watches and the volume of change events reasonable — an extremely high rate of object changes (a very chatty custom controller, for instance) can add real load to the API server and etcd.
  • Give the scheduler enough signal to make good decisions efficiently — accurate resource requests on Pods (covered further in the Scaling and Scheduling chapters) let it schedule effectively without excessive trial-and-error.
  • Monitor kubelet resource usage on nodes with very high Pod density — a kubelet itself consumes some of the node's resources to manage many Pods, and an overloaded kubelet can degrade that whole node's responsiveness.
  • For kube-proxy specifically, IPVS mode generally scales better than the older iptables mode for clusters with very large numbers of Services — worth considering explicitly for large-scale deployments.
  • Set up dedicated monitoring and alerting for each core component individually (API server, etcd, scheduler, controller manager) rather than relying solely on aggregate cluster health metrics.
  • Establish clear escalation paths distinguishing a control-plane-component issue from a worker-node or application issue, so on-call engineers can route incidents to the right area quickly.
  • Regularly review scheduler decisions and Pod placement patterns for large clusters, to catch systemic issues (a resource-request mismatch causing chronic scheduling difficulty) before they become acute.
  • Keep kubelet and kube-proxy versions consistent with the control plane's version, following your Kubernetes distribution's supported version-skew policy, to avoid subtle compatibility issues.
  • Document, for your specific cluster setup, exactly which component owns which class of symptom, as a quick-reference guide for incident responders less familiar with Kubernetes' internal architecture.
  1. Run kubectl describe pod on a Pod stuck in Pending state (deliberately create one requesting more resources than any node has available), and identify the scheduler's own event message explaining why.
  2. Use kubectl get events immediately after creating a Deployment, and identify the sequence of events showing the Deployment controller, ReplicaSet controller, and scheduler each doing their part.
  3. On a multi-node cluster, cordon (mark unschedulable) one node, and confirm new Pods are no longer scheduled onto it, while existing Pods on it continue running unaffected.
  4. Research which specific component (from this chapter's six) would be responsible for each of these symptoms: kubectl completely unresponsive; a Pod stuck Pending; a Service not routing traffic; a crashed Pod not being replaced.

✓ Quick recap

  • API server: the sole gatekeeper to etcd, enforcing authentication/authorization/validation on every single cluster state change.
  • etcd: the cluster's actual stored state, kept consistent via Raft consensus.
  • Scheduler: decides which node a new Pod should run on, based on resources and constraints.
  • Controller manager: runs the various control loops (Deployment, ReplicaSet, and others) that continuously reconcile actual state with desired state, using an efficient watch mechanism rather than fixed-interval polling.
  • kubelet (per node): starts/stops containers for Pods assigned to its node; kube-proxy (per node): implements the networking rules that make Services actually route traffic correctly.

Want a visual for this concept?

Generate a diagram tailored to “Core Components: API Server, etcd, Scheduler, Controller Manager, Kubelet & Kube-Proxy” — the AI picks whichever visual (flowchart, comparison, sequence, etc.) best fits.

Sign in to generate a visual →

Practice quiz

Next Step

Continue to Pods: Lifecycle, Init Containers & Sidecars← Back to all Kubernetes chapters