Background
Sections
IntroductionRequirements & Problem AnalysisConstraints & AssumptionsEstimation TechniquesFunctional vs Non-Functional RequirementsMoSCoW PrioritizationSystem Design FundamentalsArchitecture DiagramClass DiagramComponent DiagramData Flow Diagram (DFD)ER Diagram (Entity-Relationship Diagram)High Level Design (HLD)Low Level Design (LLD)Sequence DiagramState DiagramUse Case DiagramData StorageDocument StoresFile StorageGraph DatabasesIn-Memory DatabasesKey-Value StoresNewSQLNoSQL DatabasesObject StorageSQL Databases (RDBMS)Time-Series DatabasesWide-Column StoresDatabase ConceptsACID PropertiesCAP TheoremConsistency ModelsIndexingNormalization & DenormalizationReplicationSharding & PartitioningTransactions & Isolation LevelsScalabilityAuto-Scaling & ElasticityConsensus & Leader ElectionLoad BalancingReplication & Read ReplicasSharding & PartitioningVertical vs Horizontal ScalingAvailability & ReliabilityBackup & Data DurabilityCircuit BreakerData ConsistencyDisaster RecoveryFault Tolerance & FailoverGraceful DegradationHigh AvailabilityNetworkingCDNDNSFirewalls & VPNHTTP & HTTPSLoad Balancer & Reverse ProxyTCP/IP & UDPWebSocketsCachingCache InvalidationCache Read/Write PatternsCaching LayersEviction PoliciesRedis vs MemcachedMessaging & CommunicationDead-Letter QueueIdempotencyKafka vs RabbitMQ vs SQSMessage QueuesPub/SubCompute & ServicesAPI GatewayContainers & OrchestrationMonolith vs MicroservicesServerlessService DiscoveryService MeshWeb Server & App ServerAPI DesignAPI Versioning & IdempotencyAuthentication & AuthorizationGraphQLgRPCPaginationRate Limiting & ThrottlingRESTSecurityAuthentication & AuthorizationData PrivacyEncryptionInput Validation & InjectionOAuth2 & JWTSecrets ManagementXSS & CSRFStorage & File SystemsBackup & RetentionBlock vs File vs Object StorageData Lakes & WarehousesDistributed File SystemsEphemeral StorageObservability & MonitoringDistributed TracingHealth ChecksLoggingMetricsSLI, SLO, SLADesign PatternsBulkhead PatternCircuit Breaker PatternCreational PatternsRate Limiter PatternRetry PatternStructural & Behavioral Patterns

Containers & Orchestration

8 min read

In a Nutshell

A container packages your application together with everything it needs to run — code, runtime, libraries, dependencies — into a single, portable, isolated unit that runs identically on any machine. This solves the age-old "works on my machine" problem: the container is the environment. Orchestration is what you need once you have many containers across many machines — a system (overwhelmingly Kubernetes) that schedules containers onto servers, restarts failed ones, scales them up and down, handles networking between them, and rolls out updates without downtime. Together, containers and orchestration are the foundation of modern cloud-native deployment.

2D minimalistic diagram split in two: left shows a single container as a box neatly packaging app code + runtime + libraries + dependencies, portable across different host machines; right shows an orchestrator (Kubernetes) scheduling many such containers across a cluster of worker nodes, restarting a failed one and scaling another, illustrating automated management

How It Actually Works

Containers vs Virtual Machines

Containers are often confused with VMs — the difference is what they virtualize:

Virtual Machine Container
Virtualizes Hardware (full OS per VM) OS (shares the host kernel)
Size GBs (includes an OS) MBs (just the app + deps)
Startup Minutes (boot an OS) Seconds/less (start a process)
Isolation Strong (separate kernels) Process-level (shared kernel)
Density Few per host Many per host
Overhead High Low
VM:         [App][Bins][Guest OS] ×N  →  Hypervisor  →  Host OS  →  Hardware
Container:  [App][Bins] ×N  →  Container runtime  →  Host OS (shared)  →  Hardware
            (no guest OS per app → lighter, faster, denser)

Containers share the host kernel, making them dramatically lighter and faster than VMs — you can pack many on one machine.

The Image → Container Lifecycle

  • Image — an immutable, versioned template (built from a Dockerfile) containing your app and its dependencies.
  • Container — a running instance of an image.
  • Registry — where images are stored and pulled from (Docker Hub, ECR, GCR).
Dockerfile → docker build → Image → push to Registry
                                       │
             Any machine → docker pull → run → Container (identical everywhere)

Immutability is the superpower: the exact image you tested is the exact image that runs in production — no environment drift.

Why You Need Orchestration

Running one container is easy. Running hundreds across a fleet, keeping them healthy, scaled, and connected, is not. Orchestration automates:

Job What the Orchestrator Does
Scheduling Place containers on nodes with capacity
Self-healing Restart crashed containers; replace dead nodes
Scaling Add/remove replicas based on load (autoscaling)
Service discovery & networking Let containers find and talk to each other
Load balancing Distribute traffic across replicas
Rolling updates/rollbacks Deploy new versions with zero downtime; revert on failure
Config & secrets Inject configuration and credentials
Storage Attach persistent volumes to stateful containers

Kubernetes: The Core Concepts

Kubernetes (K8s) is the de facto standard. Its key objects:

Object What It Is
Pod The smallest unit — one or more tightly-coupled containers sharing network/storage
Deployment Declares the desired state (e.g., "run 5 replicas of this image")
Service A stable network endpoint + load balancing across a set of pods
Node A worker machine running pods
Ingress HTTP routing from outside the cluster to services
ConfigMap / Secret Configuration and sensitive data

The heart of K8s is declarative desired state + reconciliation:

You declare: "I want 5 replicas of app v2 running."
K8s control loop continuously reconciles:
  actual = 3 replicas → K8s starts 2 more
  a pod crashes → actual = 4 → K8s starts 1 more
  a node dies → K8s reschedules its pods elsewhere
→ The system constantly drives ACTUAL state toward DESIRED state.

You describe what you want, not how to achieve it; the orchestrator makes it so and keeps it that way.

2D minimalistic diagram of the Kubernetes reconciliation loop: a "desired state" box (5 replicas) on one side, an "actual state" box on the other, and a control-loop arrow continuously comparing them; when a pod crashes (red X) the loop detects the gap and schedules a replacement pod to restore the desired count, illustrating self-healing

Seeing It in Action

Scenario: Deploying a web service on Kubernetes.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 5                         # desired state: 5 pods
  selector: { matchLabels: { app: web } }
  template:
    metadata: { labels: { app: web } }
    spec:
      containers:
      - name: web
        image: myapp/web:v2.3.1       # immutable, versioned image
        ports: [{ containerPort: 8080 }]
        resources:
          requests: { cpu: "250m", memory: "256Mi" }   # scheduler uses these
          limits:   { cpu: "500m", memory: "512Mi" }
        readinessProbe:               # only send traffic when ready
          httpGet: { path: /healthz, port: 8080 }
        livenessProbe:                # restart if unhealthy
          httpGet: { path: /healthz, port: 8080 }
---
apiVersion: v1
kind: Service                          # stable endpoint + load balancing
metadata: { name: web }
spec:
  selector: { app: web }
  ports: [{ port: 80, targetPort: 8080 }]
kubectl apply -f web.yaml     # declare desired state
kubectl set image deploy/web web=myapp/web:v2.3.2   # rolling update, zero downtime
kubectl rollout undo deploy/web                     # instant rollback if it breaks

What Kubernetes handles automatically here: it schedules the 5 pods onto nodes with capacity (using the resource requests), sends traffic only to pods passing their readiness probe, restarts any pod failing its liveness probe, and reschedules pods if a node dies — always driving toward "5 healthy replicas." The Service gives a stable endpoint and load-balances across the pods even as they come and go. A new version rolls out pod-by-pod (old ones drained as new ones become ready) so users see no downtime, and a bad deploy is one command to roll back. You declared what you want; K8s continuously makes reality match — that's the essence of orchestration.

Interview Questions

  1. Q: What's the difference between a container and a virtual machine? Hint: A VM virtualizes hardware and runs a full guest OS per instance (GBs, minutes to boot, strong isolation). A container virtualizes the OS — it shares the host kernel and packages just the app + dependencies (MBs, starts in seconds, process-level isolation, high density). Containers are far lighter and faster, so you can pack many per host; VMs give stronger isolation.

  2. Q: What problem do containers solve, and why is image immutability important? Hint: Containers package the app with its exact runtime, libraries, and dependencies into a portable unit that runs identically everywhere — solving "works on my machine" / environment drift. Immutability means the exact versioned image you built and tested is what runs in production, byte-for-byte, eliminating configuration drift between environments and making deployments reproducible and rollbacks reliable.

  3. Q: Why do you need orchestration once you have many containers? Hint: Running many containers across a fleet requires automating scheduling (placement), self-healing (restart crashed containers, reschedule off dead nodes), scaling, service discovery and networking, load balancing, rolling updates/rollbacks, and config/secret injection. Doing this manually at scale is infeasible; orchestrators (Kubernetes) handle it declaratively and continuously.

  4. Q: Explain Kubernetes' declarative model and reconciliation. Hint: You declare desired state (e.g., "5 replicas of image v2") rather than imperative steps. A control loop continuously compares actual vs desired state and takes action to close the gap — starting pods if too few, replacing crashed pods, rescheduling off failed nodes. This self-healing "drive actual toward desired" behavior is the core of Kubernetes; you specify what, not how.

  5. Q: What are readiness and liveness probes, and why do both matter? Hint: A liveness probe checks if a container is still healthy — failing it triggers a restart (recovers hung processes). A readiness probe checks if a container can serve traffic right now — failing it removes the pod from the load-balancing pool without killing it (useful during startup, warmup, or temporary overload). Together they ensure traffic goes only to healthy, ready pods and unhealthy ones are recovered.

References

Dive Deeper