Core Concepts#

Understanding what Kubernetes solves, how a cluster is structured, and the fundamental building blocks that everything else rests upon.


What Kubernetes Solves#

Before Kubernetes, deploying containers at scale meant manually managing placement, networking, scaling, and failure recovery. Kubernetes automates all of this:

ProblemWithout K8sWith K8s
Container placementManual SSH, docker runScheduler decides optimal node
ScalingWrite custom scriptskubectl scale or autoscaler
Self-healingMonitor + restart manuallyAutomatic restart, reschedule
Service discoveryHardcode IPs, use ConsulBuilt-in DNS and Services
Rolling updatesDowntime or custom toolingDeclarative rolling update strategy
ConfigurationBaked into image or env filesConfigMaps, Secrets, mounted at runtime
StorageManual volume managementDynamic provisioning via StorageClasses

Kubernetes provides a declarative API — you describe the desired state, and the system continuously reconciles actual state to match it.


Cluster Architecture#

A Kubernetes cluster consists of a control plane (the brain) and worker nodes (the muscle).

graph TB
    subgraph Control Plane
        API[API Server]
        ETCD[etcd]
        SCHED[Scheduler]
        CM[Controller Manager]
        CCM[Cloud Controller Manager]
    end

    subgraph Worker Node 1
        KL1[kubelet]
        KP1[kube-proxy]
        CR1[Container Runtime]
        P1[Pod A]
        P2[Pod B]
    end

    subgraph Worker Node 2
        KL2[kubelet]
        KP2[kube-proxy]
        CR2[Container Runtime]
        P3[Pod C]
        P4[Pod D]
    end

    API --> ETCD
    SCHED --> API
    CM --> API
    CCM --> API
    KL1 --> API
    KL2 --> API

Control Plane Components#

ComponentRole
API Server (kube-apiserver)Front door to the cluster. All communication goes through it (REST API). Validates and processes requests.
etcdDistributed key-value store. Single source of truth for all cluster state.
Scheduler (kube-scheduler)Watches for unscheduled pods, assigns them to nodes based on resource requirements, affinity, taints.
Controller Manager (kube-controller-manager)Runs control loops (Deployment controller, ReplicaSet controller, Node controller, etc.) that drive actual state toward desired state.
Cloud Controller ManagerIntegrates with cloud provider APIs (load balancers, routes, volumes). Optional in bare-metal clusters.

Worker Node Components#

ComponentRole
kubeletAgent on each node. Ensures containers described in PodSpecs are running and healthy.
kube-proxyMaintains network rules on nodes. Implements Service abstraction (iptables/IPVS rules).
Container RuntimeRuns containers. CRI-compatible: containerd, CRI-O. Docker is no longer directly supported.

Pods#

A Pod is the smallest deployable unit in Kubernetes — a group of one or more containers that share network and storage.

Why Pods, Not Containers?#

  • Containers in a pod share localhost (same network namespace)
  • They can share volumes
  • They are co-scheduled on the same node
  • They represent a single unit of deployment

Pod Lifecycle#

stateDiagram-v2
    [*] --> Pending: Pod created
    Pending --> Running: Containers started
    Running --> Succeeded: All containers exit 0
    Running --> Failed: Container exits non-zero
    Running --> Unknown: Node communication lost
    Succeeded --> [*]
    Failed --> [*]
PhaseDescription
PendingAccepted by cluster, but containers not yet running (image pull, scheduling)
RunningAt least one container is running or starting/restarting
SucceededAll containers terminated successfully (exit 0)
FailedAll containers terminated, at least one with failure
UnknownPod state cannot be determined (node lost)

Basic Pod Manifest#

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  labels:
    app: nginx
    tier: frontend
spec:
  containers:
    - name: nginx
      image: nginx:1.27
      ports:
        - containerPort: 80
      resources:
        requests:
          memory: "64Mi"
          cpu: "100m"
        limits:
          memory: "128Mi"
          cpu: "250m"

Multi-Container Patterns#

Pods support multiple containers for cross-cutting concerns:

PatternPurposeExample
SidecarExtend or enhance the main containerLog shipper, service mesh proxy (Envoy)
Init ContainerRun setup tasks before the main container startsDatabase migration, config file generation
AmbassadorProxy connections to external servicesLocal Redis proxy that handles connection pooling

Init Container Example#

apiVersion: v1
kind: Pod
metadata:
  name: app-with-init
spec:
  initContainers:
    - name: wait-for-db
      image: busybox:1.36
      command: ['sh', '-c', 'until nc -z postgres-svc 5432; do sleep 2; done']
  containers:
    - name: app
      image: myapp:1.0
      ports:
        - containerPort: 8080

Sidecar Example#

apiVersion: v1
kind: Pod
metadata:
  name: app-with-sidecar
spec:
  containers:
    - name: app
      image: myapp:1.0
      volumeMounts:
        - name: logs
          mountPath: /var/log/app
    - name: log-shipper
      image: fluent/fluent-bit:3.0
      volumeMounts:
        - name: logs
          mountPath: /var/log/app
          readOnly: true
  volumes:
    - name: logs
      emptyDir: {}

Namespaces#

Namespaces provide logical isolation within a cluster — like folders for Kubernetes resources.

Default NamespacePurpose
defaultWhere resources go if no namespace is specified
kube-systemSystem components (CoreDNS, kube-proxy, metrics-server)
kube-publicPublicly readable data (cluster-info ConfigMap)
kube-node-leaseNode heartbeat leases for health detection
apiVersion: v1
kind: Namespace
metadata:
  name: staging
  labels:
    env: staging
    team: backend

Use namespaces to:

  • Separate environments (dev, staging, production) in a shared cluster
  • Isolate teams or applications
  • Apply resource quotas and network policies per namespace
  • Scope RBAC permissions

Note: Not all resources are namespaced. Nodes, PersistentVolumes, ClusterRoles, and Namespaces themselves are cluster-scoped.


Labels and Selectors#

Labels are key-value pairs attached to objects. Selectors query objects by their labels. This is how Kubernetes components find and group resources.

Common Labelling Convention#

metadata:
  labels:
    app.kubernetes.io/name: myapp
    app.kubernetes.io/version: "1.4.2"
    app.kubernetes.io/component: frontend
    app.kubernetes.io/part-of: online-store
    app.kubernetes.io/managed-by: helm

Selector Types#

Selector TypeSyntaxExample
Equality-based=, ==, !=env=production
Set-basedin, notin, existstier in (frontend, backend)

How Services Use Selectors#

apiVersion: v1
kind: Service
metadata:
  name: frontend-svc
spec:
  selector:
    app: frontend        # Matches pods with label app=frontend
    tier: web
  ports:
    - port: 80
      targetPort: 8080

The Service routes traffic to all pods matching the selector — this is how load balancing works without hardcoding pod IPs.


Key Takeaways#

  1. Kubernetes is declarative — you describe desired state; controllers reconcile continuously.
  2. Control plane manages, worker nodes execute — the API server is the single entry point for all operations.
  3. Pods are the atomic unit — not containers. Pods share network and storage between their containers.
  4. Multi-container patterns (sidecar, init, ambassador) solve cross-cutting concerns without modifying the main application.
  5. Namespaces provide logical isolation; labels and selectors provide the grouping and discovery mechanism that ties everything together.
  6. etcd is critical — all cluster state lives there. Lose etcd without backup, lose the cluster.