Cloud Tech by Victor
DevOpsAdvanced

Kubernetes Fundamentals

How Pods, Deployments, and Services fit together, what the control loop actually does, and why Kubernetes networking confuses people coming straight from Docker Compose.

Updated 2026-07-226 min read

Overview

Kubernetes takes the same container primitives Docker introduced and adds a control plane that keeps a declared number of them running, healthy, and reachable across a fleet of machines, automatically. Where Docker Compose runs a fixed set of containers on one host, Kubernetes schedules Pods across many nodes, restarts them when they fail, moves them when a node dies, and continuously reconciles the cluster's actual state toward whatever you declared in a manifest. That extra layer is also where most of the initial confusion comes from, Pods, Deployments, and Services look similar to Compose services but solve genuinely different problems, and none of them behave like a single long-lived container.

Quick Reference

ObjectPurposeLifetime
PodSmallest deployable unit, one or more co-located containersEphemeral, disposable
DeploymentManages a set of identical Pods, handles rollouts/rollbacksLong-lived, declarative
ServiceStable virtual IP + DNS name routing to matching PodsLong-lived
ConfigMap / SecretExternalized configuration and sensitive valuesLong-lived
NamespaceLogical partition of a cluster (isolation, not virtualization)Long-lived

The commands below are grouped by what you're trying to do, not an exhaustive reference (see the official kubectl reference for every flag), but the set that covers nearly all day-to-day cluster work.

CommandDescriptionCopy
kubectl get podsList Pods in the current namespace.
kubectl get pods -o wideList Pods with their node and IP address.
kubectl describe pod <name>Show events, status, and container details for one Pod.
kubectl logs <pod> -fStream a Pod's logs (add -f to follow).
kubectl exec -it <pod> -- shOpen an interactive shell inside a running Pod.
kubectl delete pod <name>Delete a Pod directly; a Deployment will recreate it immediately if one manages it.

Syntax

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api
spec:
  replicas: 3
  selector:
    matchLabels: { app: api }
  template:
    metadata:
      labels: { app: api }
    spec:
      containers:
        - name: api
          image: my-registry/api:1.4.0
          ports:
            - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: api
spec:
  selector: { app: api }
  ports:
    - port: 80
      targetPort: 8080

Examples

bash
kubectl apply -f deployment.yaml
kubectl get pods -l app=api
kubectl rollout status deployment/api
kubectl rollout undo deployment/api
javascript
// Inside any Pod in the cluster, the Service's DNS name resolves
// automatically - no hardcoded Pod IPs, no service registry to run.
const response = await fetch('http://api.default.svc.cluster.local/health')
CommandDescriptionCopy
kubectl get podsList Pods in the current namespace.
kubectl describe pod <name>Show events, status, and container details for one Pod.
kubectl logs <pod> -fStream a Pod's logs (add -f to follow).
kubectl rollout status deployment/<name>Watch a Deployment rollout until it finishes.
kubectl rollout undo deployment/<name>Roll a Deployment back to its previous revision.
kubectl scale deployment/<name> --replicas=5

Change the desired replica count directly, without editing the manifest. The Deployment controller reconciles the running Pod count to match.

kubectl scale deployment/api --replicas=5

Visual Diagram

Common Mistakes

  • Editing a Pod directly (kubectl edit pod) instead of the Deployment that manages it; the change is lost the moment that Pod is replaced.
  • Skipping resource requests/limits on containers, which lets one Pod starve others on the same node or get evicted unpredictably under pressure.
  • Assuming a Service load-balances intelligently by response time or load; the default is simple round-robin/random across Pods matching the label selector, nothing more.
  • Forgetting readiness probes, so a Deployment routes traffic to a Pod that's technically running but not yet able to serve requests (still warming up, DB connection not established).

Performance

  • The control loop's reconciliation frequency and cluster size both affect how quickly Kubernetes reacts to failures, very large clusters need a properly sized and tuned control plane (etcd especially) to keep reconciliation fast.
  • Resource requests directly drive the scheduler's bin-packing decisions; under-requesting causes overcommitted nodes and noisy-neighbor problems, over-requesting wastes capacity.
  • Rolling updates (the Deployment default) trade deployment speed for zero downtime, maxUnavailable/maxSurge tune how aggressively old Pods are replaced.

Best Practices

  • Always set resource requests and limits on every container; it's what makes scheduling and autoscaling behave predictably.
  • Define both readiness and liveness probes; readiness controls traffic routing, liveness controls automatic restarts, and conflating them causes cascading restarts under load.
  • Manage manifests through Deployments (or a higher-level tool like Helm/Kustomize), never edit live Pods or ReplicaSets directly.
  • Use namespaces to separate environments or teams within a cluster, but don't treat them as a security boundary on their own, pair them with network policies and RBAC.

Interview questions

What is the difference between a Pod, a Deployment, and a Service?

A Pod is the smallest deployable unit, one or more containers that share network and storage, scheduled together onto a node. Pods are ephemeral and disposable; Kubernetes recreates them freely and their IPs change every time. A Deployment manages a set of identical Pods (a ReplicaSet under the hood), handling rolling updates, rollbacks, and keeping the desired replica count running even as individual Pods die. A Service gives that changing set of Pods a stable network identity, a fixed virtual IP and DNS name, so other things in the cluster don't need to track individual Pod IPs, which change constantly.

What does the Kubernetes control loop actually do?

Every Kubernetes controller (Deployment, ReplicaSet, etc.) runs a reconciliation loop: it continuously compares the desired state (what you declared in a manifest, stored in etcd) against the observed actual state of the cluster, and takes action to close any gap. If you declared 3 replicas and only 2 Pods are running, the ReplicaSet controller creates one more. This is the same declarative, converge-toward-desired-state model as Terraform, but running continuously and automatically rather than on-demand.

Why can't you rely on a Pod's IP address for service discovery?

Pods are ephemeral by design, Kubernetes kills and recreates them constantly (failed health checks, node drains, rolling deployments, autoscaling), and every new Pod gets a brand-new IP address. Hardcoding or caching a Pod IP breaks the moment that Pod is replaced. A Service solves this by providing a stable virtual IP and DNS name that always routes to whichever Pods currently match its label selector, regardless of how many times the underlying Pods have been replaced.

References

ShareXLinkedInReddit
Was this page helpful?
Suggest an improvement