Kubernetes Architecture

How a Kubernetes cluster is structured, how the control plane and worker nodes cooperate, and how kubectl talks to the API.

1. Why Kubernetes?

Running containers on a single host is easy. Running hundreds of microservices across dozens of machines is not. Kubernetes (K8s) solves the operational problems of distributed container orchestration:

Without K8sWith K8s
SSH into servers, run docker run manuallyApply a Deployment; scheduler places Pods automatically
Custom scripts for health checks and restartskubelet + controllers restart and replace failed Pods
Hard-coded IPs or external load balancers per serviceClusterIP Services with built-in DNS
Manual blue/green deploysRollingUpdate strategy with kubectl rollout undo
Kubernetes is not a PaaS. It provides primitives (Pods, Services, Deployments) that you compose into a platform. You still choose ingress, CI/CD, observability, and policy tooling on top.

2. Cluster Overview

A Kubernetes cluster consists of at least one control plane and one or more worker nodes. The control plane makes global decisions (scheduling, API, state storage). Worker nodes run your workloads.

┌──────────────────────────────────────────────────────────────────────┐
│                        CONTROL PLANE                                   │
│  ┌─────────────┐  ┌─────────────┐  ┌──────────────┐  ┌────────────┐  │
│  │ API Server  │  │  Scheduler  │  │  Controller  │  │   etcd     │  │
│  │  (REST)     │  │             │  │   Manager    │  │ (key-value)│  │
│  └──────┬──────┘  └──────┬──────┘  └──────┬───────┘  └─────┬──────┘  │
│         └────────────────┴────────────────┴─────────────────┘         │
│                    all components talk to API server                   │
└──────────────────────────────────────────────────────────────────────┘
         │                           │                           │
         ▼                           ▼                           ▼
┌─────────────────┐       ┌─────────────────┐       ┌─────────────────┐
│  Worker Node 1  │       │  Worker Node 2  │       │  Worker Node N  │
│  kubelet        │       │  kubelet        │       │  kubelet        │
│  kube-proxy     │       │  kube-proxy     │       │  kube-proxy     │
│  container rt   │       │  container rt   │       │  container rt   │
│  CNI plugin     │       │  CNI plugin     │       │  CNI plugin     │
│  ┌────┐ ┌────┐  │       │  ┌────┐ ┌────┐  │       │  ┌────┐         │
│  │Pod │ │Pod │  │       │  │Pod │ │Pod │  │       │  │Pod │ ...     │
│  └────┘ └────┘  │       │  └────┘ └────┘  │       │  └────┘         │
└─────────────────┘       └─────────────────┘       └─────────────────┘

High-availability control planes run multiple API server instances behind a load balancer, with etcd deployed as a 3- or 5-node quorum cluster. Worker nodes are cattle - add or remove them without manual reconfiguration.

Namespaces

Logical partitions inside a cluster. Resources in different namespaces can share the same physical nodes but are isolated by RBAC and naming.

kubectl get namespaces
# default, kube-system, kube-public, kube-node-lease  -  plus your own

kubectl create namespace production
kubectl get pods -n production

3. Control Plane Components

Every control plane component is a process (or Pod in managed clusters) that watches or writes cluster state through the API server. etcd is the sole source of truth for persisted state.

API Server (kube-apiserver)

The front door to the cluster. All clients (kubectl, kubelet, controllers, scheduler) communicate exclusively via the REST API. It validates requests, applies admission webhooks, persists objects to etcd, and serves watch streams.

# Direct API call (requires valid credentials)
kubectl proxy &
curl http://localhost:8001/api/v1/namespaces/default/pods

# Raw request with verbose output
kubectl get pods -v=8

etcd

A consistent, distributed key-value store holding all cluster data: Pod specs, Secrets (encrypted at rest), ConfigMaps, RBAC policies, and more. Only the API server reads and writes etcd directly.

# etcd data layout (simplified)
/registry/pods/default/nginx-abc123
/registry/deployments/production/api
/registry/secrets/kube-system/bootstrap-token-xyz
Backup etcd regularly. Losing etcd without a snapshot means losing the entire cluster state. Use etcdctl snapshot save or your cloud provider's automated backups on managed control planes.

Scheduler (kube-scheduler)

Watches for newly created Pods with spec.nodeName unset and selects a suitable node based on:

apiVersion: v1
kind: Pod
metadata:
  name: gpu-worker
spec:
  nodeSelector:
    accelerator: nvidia-tesla-v100
  tolerations:
    - key: "gpu"
      operator: "Equal"
      value: "true"
      effect: "NoSchedule"
  containers:
    - name: trainer
      image: ml-trainer:latest
      resources:
        requests:
          nvidia.com/gpu: 1

Controller Manager (kube-controller-manager)

Runs controller loops that watch API objects and drive the cluster toward desired state. Each controller is responsible for one resource type or relationship.

ControllerResponsibility
Deployment controllerManages ReplicaSets; performs rolling updates
ReplicaSet controllerMaintains the correct number of Pod replicas
Node controllerMonitors node health; evicts Pods from unreachable nodes
Job controllerRuns Pods to completion for batch work
EndpointSlice controllerPopulates backend lists for Services
Namespace controllerCreates/deletes resources when namespaces change
ServiceAccount controllerCreates default ServiceAccounts and tokens

Cloud-specific controllers (e.g. cloud node lifecycle, route controllers) run in the cloud-controller-manager on cloud-hosted clusters.

4. Worker Node Components

Worker nodes host Pods. Each node runs a fixed set of agents that register with the API server and maintain local runtime state.

kubelet

The primary node agent. Registers the node, watches PodSpecs assigned to its node, and instructs the container runtime to start/stop containers. Reports node and Pod status back to the API server.

# Check kubelet health and node status
kubectl get nodes -o wide
kubectl describe node worker-1

# kubelet logs (on the node itself)
journalctl -u kubelet -f

kube-proxy

Programs network rules on each node so Services work. Implements ClusterIP, NodePort, and LoadBalancer semantics via iptables, IPVS, or eBPF (depending on mode).

# Traffic flow for ClusterIP Service "api" on port 80
Client Pod  →  DNS resolves api.default.svc  →  virtual IP 10.96.0.10:80
             →  kube-proxy DNAT  →  one of Pod IPs :8080 (round-robin)

Container Runtime

Kubernetes talks to runtimes through the Container Runtime Interface (CRI). Supported runtimes:

RuntimeStatusNotes
containerdDefault (1.24+)Industry standard; used by Docker Engine internally
CRI-OSupportedLightweight; common on OpenShift
Docker EngineRemoved (1.24+)Requires cri-dockerd shim if still needed
# On a node  -  list running containers via crictl
sudo crictl ps
sudo crictl inspect <container-id>
sudo crictl logs <container-id>

CNI (Container Network Interface)

When kubelet creates a Pod sandbox, it calls the CNI plugin to assign an IP, configure routes, and set up the network namespace. See Networking & Services for CNI details.

┌─────────────────────────────────────────┐
│  Pod network namespace                  │
│  eth0  10.244.2.15/24                   │
│       │                                 │
│  veth pair ──► bridge cni0 on host      │
│              ──► overlay / BGP routing  │
└─────────────────────────────────────────┘

5. kubectl Mastery

kubectl is the CLI for the Kubernetes API. It reads kubeconfig (~/.kube/config) for cluster URL, credentials, and current context.

Essential commands

# Context and cluster info
kubectl config get-contexts
kubectl config use-context prod-eks
kubectl cluster-info

# CRUD operations
kubectl apply -f deployment.yaml      # declarative (preferred)
kubectl create deployment nginx --image=nginx:1.25
kubectl get pods -o wide -w           # watch mode
kubectl describe pod nginx-abc123
kubectl delete pod nginx-abc123 --grace-period=30

# Imperative edits
kubectl scale deployment api --replicas=5
kubectl set image deployment/api api=myregistry/api:v2.1
kubectl rollout status deployment/api
kubectl rollout undo deployment/api

Output formats

FlagUse
-o wideExtra columns (node, IP)
-o yamlFull manifest (includes cluster-managed fields)
-o jsonJSON output for scripting
-o jsonpath='{.items[*].metadata.name}'Extract specific fields
-o custom-columns=NAME:.metadata.name,STATUS:.status.phaseCustom table

Debugging shortcuts

kubectl logs pod/api-xyz -c api --previous    # crashed container logs
kubectl exec -it pod/api-xyz -c api -- sh     # shell into container
kubectl port-forward svc/api 8080:80          # local access
kubectl top pods -n production                # metrics (needs metrics-server)
kubectl api-resources                         # list all resource types
kubectl explain pod.spec.containers           # OpenAPI docs in terminal

Generating YAML

kubectl create deployment nginx --image=nginx --dry-run=client -o yaml > deploy.yaml
kubectl run debug --image=busybox --restart=Never --dry-run=client -o yaml
Prefer apply over create. kubectl apply uses server-side or client-side three-way merge and is idempotent. create fails if the object already exists.

6. API Resources & Objects

Everything in Kubernetes is an API object with apiVersion, kind, metadata, spec (desired state), and status (observed state).

Core object anatomy

apiVersion: apps/v1
kind: Deployment
metadata:
  name: api
  namespace: production
  labels:
    app: api
    team: platform
  annotations:
    deployment.kubernetes.io/revision: "3"
spec:          # what you want
  replicas: 3
  selector:
    matchLabels:
      app: api
  template:
    metadata:
      labels:
        app: api
    spec:
      containers:
        - name: api
          image: myregistry/api:1.2.0
status:        # what the cluster reports (read-only via kubectl)
  replicas: 3
  availableReplicas: 3
  conditions: [...]

Common API groups

API GroupExamples
v1 (core)Pod, Service, ConfigMap, Secret, Namespace, PV, PVC
apps/v1Deployment, ReplicaSet, StatefulSet, DaemonSet
batch/v1Job, CronJob
networking.k8s.io/v1Ingress, NetworkPolicy
rbac.authorization.k8s.io/v1Role, RoleBinding, ClusterRole
autoscaling/v2HorizontalPodAutoscaler

Labels and selectors

Labels are key/value pairs on objects. Selectors connect resources: a Service selects Pods; a Deployment selects ReplicaSets; a ReplicaSet selects Pods.

metadata:
  labels:
    app: api
    env: production
    version: v2

# Service routes to Pods with matching labels
spec:
  selector:
    app: api
    env: production

Owner references and garbage collection

Child objects (Pods owned by ReplicaSets) have ownerReferences. Deleting a Deployment cascades to its ReplicaSets and Pods. Set orphanDependents or use --cascade=orphan to keep children.

kubectl delete deployment api --cascade=orphan   # keep ReplicaSets/Pods

7. The Reconciliation Loop

Kubernetes is built on the control loop pattern: observe current state, compare to desired state, act to reduce the difference, repeat.

         ┌──────────────────────────────────────────┐
         │           DESIRED STATE (spec)              │
         │   Deployment: replicas: 3, image: v2     │
         └──────────────────┬───────────────────────┘
                            │
    ┌───────────────────────▼───────────────────────┐
    │              API SERVER / etcd                 │
    └───────────────────────┬───────────────────────┘
                            │ watch
         ┌──────────────────┼──────────────────┐
         ▼                  ▼                  ▼
   Deployment ctrl    ReplicaSet ctrl     Scheduler
         │                  │                  │
         │ creates/         │ creates/         │ assigns
         │ updates RS       │ deletes Pods     │ nodeName
         ▼                  ▼                  ▼
   ReplicaSet          Pods (actual)      Worker Node
                            │
                     kubelet runs containers
                            │
                     status reported back ──► loop repeats

Example: scaling a Deployment

  1. You run kubectl scale deployment api --replicas=5
  2. API server updates Deployment spec in etcd
  3. Deployment controller sees spec.replicas=5, current RS has 3 Pods
  4. ReplicaSet controller creates 2 new Pods
  5. Scheduler assigns them to nodes; kubelet starts containers
  6. kubelet reports Pod status; Deployment status shows 5/5 available

Level-triggered vs edge-triggered

Kubernetes controllers are level-triggered: they reconcile the full desired state on every loop, not just the last change. If a Pod is deleted manually, the ReplicaSet controller recreates it without a new event. This makes the system resilient to missed events or restarts.

Finalizers

Objects with metadata.finalizers cannot be deleted until each finalizer is removed by its controller. Used for graceful cleanup (e.g. removing LoadBalancer IPs, volume detachment).

kubectl get pod stuck-terminating -o yaml | grep finalizers -A 3
# Remove finalizer only when you understand the risk (break-glass)
kubectl patch pod stuck-terminating -p '{"metadata":{"finalizers":[]}}' --type=merge

8. Cluster Setup Options

How you run Kubernetes depends on environment, team size, and operational appetite.

OptionBest forTrade-offs
Managed (EKS, GKE, AKS)Production, most teamsControl plane managed; you pay for nodes + control plane fee
kindLocal dev, CIMulti-node clusters in Docker; not for production
minikubeLocal learningSingle-node; addons for ingress, metrics
k3s / k3dEdge, IoT, lightweight prodStripped-down distribution; easy HA with embedded etcd
kubeadmSelf-managed on VMsOfficial bootstrap tool; you operate upgrades and etcd
Rancher / OpenShiftEnterprise multi-clusterExtra UI, policy, and platform features

kind quick start

# Install: go install sigs.k8s.io/kind@latest
kind create cluster --name dev --config - <<EOF
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
  - role: control-plane
  - role: worker
  - role: worker
EOF

kubectl cluster-info --context kind-dev
kubectl get nodes

minikube quick start

minikube start --cpus=4 --memory=8192 --driver=docker
minikube addons enable ingress
minikube addons enable metrics-server
kubectl get pods -A

Production checklist

9. Cheat Sheet

TaskCommand
Cluster infokubectl cluster-info
List nodeskubectl get nodes -o wide
Control plane Podskubectl get pods -n kube-system
Switch contextkubectl config use-context <name>
All API resourceskubectl api-resources
Explain a fieldkubectl explain pod.spec
Watch eventskubectl get events -A --sort-by=.lastTimestamp
Component statuskubectl get componentstatuses (deprecated; use node conditions)

Full cheat sheet: kubectl Cheat Sheet