Introduction to Kubernetes

Kubernetes (K8s) is the de facto standard for container orchestration — an open-source platform originally built at Google, now stewarded by the Cloud Native Computing Foundation (CNCF). It automates deploying, scaling, and managing containerised applications across clusters of machines.

Rather than manually placing containers on servers, you declare the desired state of your application. Kubernetes continuously reconciles the actual state of the cluster toward that desired state — restarting failed containers, rescheduling pods away from failed nodes, scaling replicas up or down — all without human intervention.

⬡ Core Design Philosophy

Kubernetes is a declarative, self-healing platform. You describe what you want (desired state). The control loop observes what exists (actual state) and takes action to close the gap. This convergence loop is the foundation of everything Kubernetes does.

🔁
Desired State Management
Declare intent via YAML manifests. Kubernetes continuously reconciles actual state toward it.
💊
Self-Healing
Restarts failed containers, replaces unhealthy pods, reschedules from failed nodes automatically.
⚖️
Horizontal Scaling
Scale out by adding pod replicas. HPA scales automatically on CPU, memory, or custom metrics.
🌐
Service Discovery
Built-in DNS and virtual IPs route traffic to healthy pods. No external load balancer needed for intra-cluster traffic.

High-Level Cluster Architecture

A Kubernetes cluster consists of a Control Plane (the brain — manages desired state, scheduling, and the API) and a Data Plane of Worker Nodes (the muscle — actually runs your workloads). A third concern, the Storage Layer, handles durable persistence for stateful applications.

// Kubernetes Cluster — Full Architecture View
◈ Control Plane (manages cluster state — typically 3 or 5 nodes for HA)
🧠
kube-apiserver
Central API hub. All components talk through here.
🗄️
etcd
Distributed key-value store. Sole source of truth.
📅
kube-scheduler
Assigns unscheduled pods to nodes via filter + score.
🔄
controller-manager
Runs all built-in control loops (Node, Deployment, HPA…)
☁️
cloud-controller
Integrates with AWS/GCP/Azure for LBs and volumes.
kubelet watches API server · schedules workloads
Worker Node 1
api-pod cache-pod
kubelet kube-proxy containerd
Worker Node 2
worker-pod db-pod
kubelet kube-proxy containerd
Storage Node
postgres-0 redis-0
kubelet CSI-node NVMe SSD
ℹ Key Insight: The API Server is the Only Communication Hub

Every component communicates exclusively through the kube-apiserver — never directly with each other. This centralises auth, RBAC, admission control, and audit logging. The API server is stateless; all state is durably persisted in etcd.


Worker Node Architecture

Worker Nodes are the machines in a Kubernetes cluster that actually run containerised workloads. Each node hosts one or more Pods and must run three core components: the kubelet, kube-proxy, and a container runtime.

3.1 kubelet — The Node Agent

The kubelet is the primary agent on every worker node. It watches the API server for Pods assigned to its node and instructs the container runtime to start, stop, and restart containers accordingly. It also reports node health and resource usage back to the API server.

ResponsibilityDetail
Pod LifecycleStarts/stops containers via CRI. Enforces restartPolicy.
Health ProbingExecutes liveness, readiness, and startup probes. Takes corrective action on failure.
Resource ReportingReports node CPU/memory capacity and allocatable resources to the API server.
Volume MountingMounts PVCs, ConfigMaps, Secrets, and ephemeral volumes into pod filesystems.
Image ManagementPulls container images. Enforces imagePullPolicy. Manages local image cache.
Node RegistrationRegisters the node with the API server on startup. Advertises labels and taints.

3.2 kube-proxy — The Service Router

kube-proxy maintains network rules on each node that implement the Kubernetes Service abstraction — routing traffic from a stable virtual IP to backend pod IPs. It operates in one of three modes:

ModeMechanismPerformanceNotes
iptablesKernel netfilter rulesGood — O(n) rule lookupDefault in most clusters
IPVSKernel IP Virtual ServerExcellent — O(1) lookupBest for 1000+ services
eBPF (Cilium)Extended BPF programsBestReplaces kube-proxy entirely

3.3 Container Runtime

The container runtime pulls images and manages container lifecycle at the OS level. The kubelet communicates with it via the Container Runtime Interface (CRI) — a gRPC API. Modern clusters use containerd as the default runtime.

shell
# Check container runtime on a node $ kubectl get node worker-1 -o jsonpath='{.status.nodeInfo.containerRuntimeVersion}' containerd://1.7.14 # kubelet CRI socket path $ crictl --runtime-endpoint unix:///run/containerd/containerd.sock ps CONTAINER IMAGE CREATED STATE NAME a3f1e2b4d5 nginx 2 min ago Running nginx

Containers in Kubernetes

Containers are lightweight, isolated execution environments that package an application with all its runtime dependencies. In Kubernetes, containers always run inside a Pod — they cannot be scheduled independently. They are the atomic unit of execution.

🐧 Linux Primitives Behind Containers

Namespaces provide isolation (PID, Network, Mount, UTS, IPC, User). cgroups enforce resource limits for CPU and memory. OverlayFS stacks read-only image layers with a thin writable layer on top. seccomp/AppArmor restrict system calls to reduce the attack surface.

4.1 Health Probes

Kubernetes uses three types of probes to monitor and manage container health. These are critical for ensuring only healthy containers receive traffic and unhealthy ones are automatically remediated.

❤️
Liveness
Is the container alive? Detects deadlocks and broken states that don't cause a process exit.
→ Container is killed and restarted
Readiness
Is the container ready to serve traffic? Gates inclusion in Service load balancer endpoints.
→ Removed from Service endpoints
🚀
Startup
Has the app finished initialising? Disables liveness/readiness until this passes.
→ Container killed if never passes

4.2 Container Security Context

Always configure a security context to follow the principle of least privilege in production:

yaml
securityContext: runAsNonRoot: true runAsUser: 1000 readOnlyRootFilesystem: true allowPrivilegeEscalation: false capabilities: drop: ["ALL"] seccompProfile: type: RuntimeDefault

4.3 Init Containers

Init containers run sequentially to completion before main application containers start. Each must succeed before the next begins. They share the pod's volumes but have their own images.

✅ Common Init Container Patterns

Waiting for a database to be ready before the app starts · Running DB schema migrations · Cloning git repos or fetching config into shared volumes · Fetching TLS certificates · Pre-populating a shared cache.


Pods — The Fundamental Unit

A Pod is the smallest deployable unit in Kubernetes. It encapsulates one or more containers, shared storage volumes, a unique cluster IP address, and configuration governing how containers run. Containers in a pod share the same network namespace — they communicate via localhost and share port space.

// Pod Internal Anatomy
Pod (Shared Namespace)
🌐 Shared Network (eth0)
Single IP · Shared Ports
💾 Shared Volumes
emptyDir · PVC Mounts
⚙️
Init Container
Runs first. Waits for DB, runs migrations.
📦
Main Container
Application workload. Starts after init completes.
🔭
Sidecar
Log shipper / Envoy proxy / Secret injector.

5.1 Pod Lifecycle Phases

PENDING
Waiting for scheduling or image pull
RUNNING
At least one container is running
SUCCEEDED
All containers exited 0
FAILED
At least one container exited non-zero
UNKNOWN
Node communication lost

5.2 Quality of Service (QoS) Classes

Kubernetes assigns a QoS class to every pod based on how its containers' resource requests and limits are configured. This directly determines eviction priority under node memory pressure.

GUARANTEED
requests == limits for ALL containers in the pod. CPU + memory both set.
↑ Highest Priority — Last Evicted
BURSTABLE
At least one container has a CPU or memory request or limit set. Not Guaranteed.
→ Medium Priority
BESTEFFORT
No resource requests or limits set on any container.
↓ Lowest Priority — First Evicted

5.3 Scheduling Controls

Kubernetes provides a rich set of mechanisms to control where pods are placed. These range from simple label matching to complex topology-aware spreading.

MechanismPurposeHard / Soft
nodeSelectorMatch pods to nodes by label key-value pairsHard (required)
nodeAffinityRich expression-based node selectionBoth
podAffinityCo-locate pods with other pods by labelBoth
podAntiAffinitySpread pods away from other podsBoth
Taints + TolerationsRepel pods from nodes unless pod has a matching tolerationHard
topologySpreadConstraintsEvenly distribute pods across zones/nodesBoth
PriorityClassPreempt lower-priority pods when resources are scarceHard

5.4 Pod Controllers

In production you never create pods directly. Higher-level controllers manage pod sets and handle resilience.

ControllerUse CaseKey Feature
DeploymentStateless appsRolling updates, rollbacks, replica management
StatefulSetDatabases, cachesStable identity, ordered start/stop, per-pod PVC
DaemonSetNode-level agentsOne pod per node — CNI, log agents, CSI drivers
JobOne-off batch tasksRun to completion with retry logic
CronJobScheduled batch tasksCron schedule syntax
ReplicaSetReplica guaranteeEnsures N replicas are always running

Storage Nodes & Persistent Volumes

Stateful workloads — databases, message brokers, object stores — require durable storage that outlives any individual pod. Kubernetes abstracts storage through a layered model that decouples provisioning from consumption.

6.1 What is a Storage Node?

A Storage Node is a worker node dedicated to or optimised for stateful workloads. It's configured with high-performance storage hardware (NVMe SSDs, high-IOPS disks) and is labelled and tainted so that only storage-intensive pods (PostgreSQL, Cassandra, Elasticsearch) are scheduled onto it.

shell
# Label and taint a storage node $ kubectl label node storage-node-1 node-role=storage $ kubectl taint node storage-node-1 dedicated=storage:NoSchedule # Pod toleration to schedule onto storage nodes tolerations: - key: "dedicated" operator: "Equal" value: "storage" effect: "NoSchedule"

6.2 The Storage Abstraction Model

Kubernetes provides four storage objects that form a clean separation between infrastructure and developer concerns:

// Kubernetes Storage Abstraction Layers
⚙️
StorageClass
Admin defines provisioner + parameters
💿
PersistentVolume
Actual storage resource in the cluster
📋
PersistentVolumeClaim
Developer's request for storage
📦
Volume Mount
PVC mounted into pod container
Access ModeShortDescriptionTypical Use
ReadWriteOnceRWORead-write by a single nodeDatabases (MySQL, Postgres)
ReadOnlyManyROXRead-only by many nodesShared config / static assets
ReadWriteManyRWXRead-write by many nodesNFS shared content stores
ReadWriteOncePodRWOPRead-write by a single pod onlyStrict single-writer workloads
⚠ Reclaim Policy — Production Critical

Always use Retain for production databases. With Delete, releasing a PVC permanently deletes the underlying storage — including all your data. Retain preserves the PV and data for manual recovery.

6.3 Container Storage Interface (CSI)

CSI is the standardised plugin API between Kubernetes and storage vendors. CSI drivers ship independently from Kubernetes, allowing any storage system to integrate without modifying core Kubernetes code.

yaml
# StorageClass using AWS EBS CSI driver apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: fast-nvme provisioner: ebs.csi.aws.com parameters: type: gp3 iops: "6000" throughput: "250" reclaimPolicy: Retain volumeBindingMode: WaitForFirstConsumer --- # PVC claiming from that StorageClass apiVersion: v1 kind: PersistentVolumeClaim metadata: name: postgres-data spec: storageClassName: fast-nvme accessModes: [ReadWriteOnce] resources: requests: storage: 100Gi

Architecture Summary

The complete reference of all major Kubernetes components, their location, and function:

ComponentLocationPrimary Function
kube-apiserverControl PlaneCentral API hub. All communication passes through. Enforces auth and admission.
etcdControl PlaneDistributed key-value store. Single source of cluster truth.
kube-schedulerControl PlaneAssigns unscheduled pods to nodes via filter + score phases.
kube-controller-managerControl PlaneRuns all built-in control loops — Node, Deployment, HPA, etc.
cloud-controller-managerControl PlaneCloud API integration for load balancers, node lifecycle, volumes.
kubeletWorker NodeNode agent. Manages pod/container lifecycle. Reports node status.
kube-proxyWorker NodeService routing. Maintains iptables/IPVS rules for virtual IPs.
Container RuntimeWorker NodePulls images and runs containers (containerd, CRI-O).
CNI PluginWorker NodePod networking. Assigns IPs. Enforces NetworkPolicies.
PodWorker NodeSmallest deployable unit. Wraps 1+ containers, network, storage.
PersistentVolumeCluster-scopedRepresents a piece of durable storage in the cluster.
PersistentVolumeClaimNamespace-scopedDeveloper's request for persistent storage. Bound to a PV.
StorageClassCluster-scopedDefines provisioner + parameters for dynamic PV creation.
CSI DriverCluster + Each NodePlugin interface between Kubernetes and external storage systems.
Storage NodeDedicated Worker NodeHigh-IOPS node tainted for stateful workloads only.
CoreDNSkube-systemCluster DNS. Resolves service and pod names to IPs.
⬡ Copyright

© Tech with Vishal Abhinav · Platform Ops Engineer · All rights reserved. This article is published as part of the Platform Ops Newsletter.