Skip to main content
>_ supraj.dev
// PUBLISHED ON JUNE 17, 2026 12 min read

Kubernetes Architecture & Components Overview

A human-friendly breakdown of the Kubernetes control plane, worker nodes, and core cluster services — with real production context, examples, and best practices.

#Kubernetes #Architecture #Control Plane #EKS #Production

You’re about to run applications in production on Kubernetes. Before you dive into YAML and deployments, you need to understand who does what inside a cluster. Think of this chapter as your mental model — the map you’ll reference every time something breaks.

Let’s walk through the control plane, the worker nodes, and the core objects that glue everything together.


The Control Plane — The Brain of the Cluster

The control plane is the set of components that make global decisions about the cluster. It’s the management layer — it schedules workloads, responds to events, and maintains the desired state.

If the cluster were an airport, the control plane would be the air traffic control tower. The workers (nodes) are the runways and gates where actual planes (your containers) operate.

Control Plane Architecture
// API
API Server

Entry point for all interactions

// STORE
etcd

Cluster brain & state

// CONTROL
Controller Mgr

Desired state enforcer

// SCHEDULER
Scheduler

Pod placement decisions

API Server — The Front Door

Everything talks to the API server. kubectl, CI/CD pipelines, the scheduler, controllers, even the nodes themselves — every single interaction goes through this single endpoint.

Real-World Analogy

The API server is like a bank teller. You (or any system) submit a request — “create a deployment”, “scale this service” — and the teller validates your identity (auth), checks your permissions (RBAC), and writes the transaction to the ledger (etcd). If the teller is down, nobody does anything.

In production, your API server must be highly available. On EKS, AWS runs it across three Availability Zones automatically. If you’re self-managing, you need at least three control plane nodes with a load balancer in front.

etcd — The Source of Truth

etcd is a distributed key-value store that holds the entire cluster state — every deployment, every secret, every node, every config map. It’s the cluster’s memory.

! Production Rule

Never run etcd with fewer than 3 members. etcd uses a quorum-based consensus protocol (Raft). With 3 nodes, you can lose 1 and still operate. With 2 nodes, losing 1 means quorum is lost and the cluster stops. Always use an odd number — 3 or 5.

Here’s what your etcd backup strategy should look like in practice:

etcd-backup.sh
# Backup etcd (self-managed clusters)
ETCDCTL_API=3 etcdctl snapshot save /backup/etcd-snapshot-$(date +%Y%m%d).db \
  --endpoints=https://127.0.0.1:2379 \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key

# On EKS — etcd is managed by AWS, but back up cluster resources with Velero
velero backup create daily-backup --include-cluster-resources=true --ttl 168h
Pro Tip

If you’re on EKS, AWS handles etcd durability for you. But don’t skip Velero backups — etcd isn’t the only thing that matters. You still need to back up your PVCs, CRDs, and custom resources.

Controller Manager — The Desired State Enforcer

The controller manager runs controllers — loops that watch the current state of the cluster and work to make it match the desired state.

If you set replicas: 3 on a Deployment and a node dies taking one pod with it, the controller manager detects the drift and schedules a replacement. It never sleeps, never gets distracted.

// WATCH LOOP

A controller constantly watches the API server for changes to the resource it manages (e.g., a Deployment).

// DETECT DRIFT

It compares the current state (3 pods running) against the desired state (3 replicas). If a pod is missing, it registers a deficit.

// RECONCILE

It creates a new Pod object via the API server or triggers other actions to bring the cluster back to the desired state.

Scheduler — The Pod Placement Engine

When a new pod is created (with no node assigned), the scheduler picks the best node for it. It evaluates:

  • Resource requirements — does the node have enough CPU/memory?
  • Affinity and anti-affinity rules — should this pod run near or away from other pods?
  • Taints and tolerations — is the pod allowed on this node?
  • Node health — is the node reporting ready?
Real-World Example

Imagine you’re deploying a payment processing service. You have 3 replicas and want them on separate nodes so a single node failure doesn’t take down payments. You add a podAntiAffinity rule, and the scheduler ensures each replica lands on a different node — even a different Availability Zone.

affinity:
  podAntiAffinity:
    preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 100
        podAffinityTerm:
          labelSelector:
            matchLabels:
              app: payment-service
          topologyKey: "topology.kubernetes.io/zone"

Worker Nodes — Where the Work Happens

Worker nodes are the machines (EC2 instances, bare metal, or VMs) that run your containerized applications. Each node runs three essential components:

Worker Node Components
// AGENT
kubelet

Node registration & pod management

// RUNTIME
Container Runtime

containerd, CRI-O, etc.

// NETWORK
kube-proxy

Service routing & network rules

kubelet — The Node Agent

The kubelet is an agent that runs on every node. It registers the node with the control plane and ensures containers are running as instructed by the API server.

If the kubelet stops reporting, the control plane marks the node as NotReady after a timeout and reschedules the pods elsewhere. This is why monitoring kubelet health is critical.

Production Pitfall

On EKS, your node IAM role must have the correct permissions for the kubelet to register successfully. If you’re using custom AMIs or self-managed nodes, verify the kubelet bootstrap config — misconfigured kubelet flags are one of the most common causes of nodes failing to join the cluster.

Container Runtime — Actually Running Things

The container runtime is the software that pulls images and runs containers. In modern Kubernetes, that’s almost always containerd or CRI-O. Docker was deprecated as a runtime after Kubernetes 1.24.

kube-proxy — Network Rules Manager

kube-proxy maintains network rules on each node. It implements Kubernetes Services by managing iptables or IPVS rules, routing traffic to the right pods.

Performance Note

For large clusters (100+ nodes), IPVS mode performs better than iptables because it uses a hash table instead of a chain of rules. Switching is as simple as setting --proxy-mode=ipvs on kube-proxy — worth doing for production at scale.

Node Groups & Instance Diversity

In production, you rarely have a single pool of identical nodes. Different workloads have different needs:

Workload TypeRecommended InstanceWhy
Web APIs & microservicesGeneral-purpose (m7i, t3)Balanced CPU/memory
ML training / inferenceGPU (p4d, g5)CUDA cores, high memory bandwidth
Databases (in-cluster)Storage optimized (i7i, r7i)High IOPS, local NVMe
Batch / CI workersCompute optimized (c7i)High vCPU count, cost-effective
Best Practice

Use Managed Node Groups on EKS. They automatically use EKS-optimized AMIs, handle rolling upgrades, and integrate with IAM. Only use self-managed nodes if you need custom AMIs or specialized bootstrap scripts.


Pods & Higher-Level Controllers

The pod is the smallest deployable unit in Kubernetes. But in production, you almost never create pods directly — you use controllers that manage pods for you.

Deployments — The Workhorse

Deployments manage stateless applications. They handle:

  • Running a specified number of replicas
  • Rolling updates with zero downtime
  • Rollbacks to a previous version
  • Horizontal scaling (manual or via HPA)

A production-ready Deployment has three things you should never skip:

// HEALTH PROBES

Liveness probe — tells Kubernetes if the container is alive. If it fails, the pod is restarted.
Readiness probe — tells Kubernetes if the container is ready to serve traffic. If it fails, the pod is removed from Service endpoints.

// RESOURCE REQUESTS & LIMITS

Requests — what the scheduler guarantees the container gets.
Limits — the maximum the container is allowed to use. Never set limits without requests, and never over-request “just in case” — it wastes resources and money.

// ANTI-AFFINITY

Ensures replicas are spread across different nodes (and ideally different AZs) so a single failure doesn’t take down the entire service.

Here’s what a production-ready Deployment looks like:

deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: payment-api
  namespace: production
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  template:
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchLabels:
                  app: payment-api
              topologyKey: "topology.kubernetes.io/zone"
      containers:
        - name: app
          image: myapp/payment-api:v2.1.4
          ports:
            - containerPort: 8080
          resources:
            requests:
              cpu: 250m
              memory: 512Mi
            limits:
              cpu: 500m
              memory: 768Mi
          livenessProbe:
            httpGet:
              path: /healthz
              port: 8080
            initialDelaySeconds: 5
            periodSeconds: 10
          readinessProbe:
            httpGet:
              path: /ready
              port: 8080
            initialDelaySeconds: 3
            periodSeconds: 5
Why maxUnavailable: 0?

Setting maxUnavailable: 0 ensures that during a rolling update, the number of available replicas never drops below your desired count. The new pod starts up and receives traffic before the old one is terminated. This is how you achieve zero-downtime deployments.

StatefulSets — For Apps That Need Identity

StatefulSets are for stateful applications — databases, message brokers, anything that needs stable network identities and persistent storage.

Each pod in a StatefulSet gets:

  • A stable hostname (e.g., db-0, db-1, db-2)
  • Its own persistent volume (that survives rescheduling)
  • Ordered, graceful deployment and scaling
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: postgres
spec:
  serviceName: postgres
  replicas: 3
  template:
    spec:
      containers:
        - name: postgres
          image: postgres:16
          volumeMounts:
            - name: data
              mountPath: /var/lib/postgresql/data
  volumeClaimTemplates:
    - metadata:
        name: data
      spec:
        accessModes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 100Gi
Think Twice Before Running Databases on Kubernetes

The guidance here is honest: managed databases (RDS, Aurora, ElastiCache) reduce operational burden significantly. Running stateful workloads on Kubernetes is doable — many companies do it — but you need solid backup strategies (Velero, pg_dump, snapshots), monitoring, and failover procedures. If your FinTech app loses a transaction, “but Kubernetes rescheduled the pod” won’t calm your compliance team.

DaemonSets — One Pod Per Node

DaemonSets ensure every node runs a copy of a pod. They’re perfect for:

  • Log shippers — Fluent Bit, Filebeat
  • Monitoring agents — Node Exporter, Datadog agent
  • Network plugins — Calico, Cilium
  • Security agents — Falco, Aqua
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluent-bit
  namespace: observability
spec:
  selector:
    matchLabels:
      app: fluent-bit
  template:
    spec:
      containers:
        - name: fluent-bit
          image: fluent/fluent-bit:3.0
          resources:
            requests:
              cpu: 100m
              memory: 128Mi
            limits:
              cpu: 200m
              memory: 256Mi

Jobs & CronJobs — One-Time & Scheduled Tasks

Jobs run a set of pods to completion — useful for batch processing, database migrations, or data exports. CronJobs add a schedule:

apiVersion: batch/v1
kind: CronJob
metadata:
  name: nightly-db-backup
spec:
  schedule: "0 2 * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
            - name: backup
              image: myapp/backup-tool:1.0
              command: ["pg_dump", "-Fc", "myapp_prod", "-f", "/backups/dump.sqlc"]
          restartPolicy: OnFailure
CronJob Concurrency Gotcha

Always set concurrencyPolicy: Forbid on CronJobs that shouldn’t overlap — like database backups. If the previous backup is still running when the next schedule fires, Kubernetes will skip the new run instead of letting them pile up.


Services — Stable Networking for Ephemeral Pods

Pods come and go. They get rescheduled, replaced, and restarted. Services provide a stable endpoint (a virtual IP and DNS name) that persists regardless of pod churn.

TypeWhen to UseExample
ClusterIP (default)Internal microservice communicationFrontend → backend API
NodePortDevelopment or debuggingDirect access to a specific node
LoadBalancerExposing a service externally (each creates a cloud LB)Simple single-service exposure
ExternalNameMapping a K8s service to an external DNS namePointing to a legacy service outside the cluster
Production Pattern: Ingress + ClusterIP

In production, you rarely use LoadBalancer services for every app. Instead, use ClusterIP for internal services and an Ingress (e.g., AWS ALB Ingress Controller, NGINX Ingress) to route external traffic. One LoadBalancer for many services saves money and simplifies management.


Namespaces — Organizing Your Cluster

Namespaces are virtual clusters within your physical cluster. They provide:

  • Isolation — separate teams, environments, or applications
  • Scope — for resource names (you can have a payment-api service in both staging and prod namespaces)
  • Policy boundaries — RBAC, network policies, and resource quotas apply at the namespace level
kubectl create namespace production
kubectl create namespace staging

kubectl config set-context prod --namespace=production
kubectl config set-context stage --namespace=staging
Namespace Strategy

Common approaches:

  • Per environment: production, staging, development
  • Per team: platform-team, payments-team, data-team
  • Per application: a namespace for each microservice

For multi-tenant clusters, use per-team namespaces with strict ResourceQuotas and NetworkPolicies.


What’s Next?

Now that you understand the architecture, the next guide will cover High Availability Architecture — designing your cluster to survive failures, including control plane redundancy, multi-AZ distribution, and upgrade strategies.

Chapter Review
  • The control plane (API server, etcd, controller manager, scheduler) manages the cluster — it’s the air traffic control
  • Worker nodes (kubelet, container runtime, kube-proxy) run your actual workloads
  • Pods are the smallest unit, but you use Deployments, StatefulSets, DaemonSets, and Jobs/CronJobs to manage them
  • Services provide stable networking for dynamic pods
  • Namespaces organize and isolate cluster resources