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
| Object | Purpose | Lifetime |
|---|---|---|
| Pod | Smallest deployable unit, one or more co-located containers | Ephemeral, disposable |
| Deployment | Manages a set of identical Pods, handles rollouts/rollbacks | Long-lived, declarative |
| Service | Stable virtual IP + DNS name routing to matching Pods | Long-lived |
| ConfigMap / Secret | Externalized configuration and sensitive values | Long-lived |
| Namespace | Logical 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.
| Command | Description | Copy |
|---|---|---|
kubectl get pods | List Pods in the current namespace. | |
kubectl get pods -o wide | List Pods with their node and IP address. | |
kubectl describe pod <name> | Show events, status, and container details for one Pod. | |
kubectl logs <pod> -f | Stream a Pod's logs (add -f to follow). | |
kubectl exec -it <pod> -- sh | Open 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. |
| Command | Description | Copy |
|---|---|---|
kubectl apply -f deployment.yaml | Create or update resources declared in a manifest file. | |
kubectl get deployments | List Deployments and their ready/up-to-date/available replica counts. | |
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. | |
kubectl delete -f deployment.yaml | Delete every resource declared in a manifest file. |
| Command | Description | Copy |
|---|---|---|
kubectl get svc | List Services and their cluster IPs and ports. | |
kubectl describe svc <name> | Show a Service's selector, endpoints, and port mappings. | |
kubectl port-forward svc/<name> 8080:80 | Forward a local port to a Service, for local debugging without exposing it publicly. | |
kubectl expose deployment <name> --port=80 | Create a Service that targets an existing Deployment's Pods. |
| Command | Description | Copy |
|---|---|---|
kubectl get configmaps | List ConfigMaps in the current namespace. | |
kubectl create configmap <name> --from-file=<path> | Create a ConfigMap from a file or directory. | |
kubectl get secrets | List Secrets in the current namespace (values are not shown in plaintext). | |
kubectl create secret generic <name> --from-file=key=<path> | Create a Secret from a file's contents, avoiding passing credential values as shell arguments where they'd land in shell history and process listings. |
| Command | Description | Copy |
|---|---|---|
kubectl get events --sort-by=.lastTimestamp | List cluster events, most recent last - often the fastest way to spot a scheduling or image-pull failure. | |
kubectl get pods -A | List Pods across every namespace. | |
kubectl top pods | Show live CPU/memory usage per Pod (requires metrics-server). | |
kubectl get nodes | List cluster nodes and their status. |
Syntax
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: 8080Examples
kubectl apply -f deployment.yaml
kubectl get pods -l app=api
kubectl rollout status deployment/api
kubectl rollout undo deployment/api// 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')| Command | Description | Copy |
|---|---|---|
kubectl get pods | List Pods in the current namespace. | |
kubectl describe pod <name> | Show events, status, and container details for one Pod. | |
kubectl logs <pod> -f | Stream 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=5Change 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/limitson containers, which lets one Pod starve others on the same node or get evicted unpredictably under pressure. - Assuming a
Serviceload-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
requestsdirectly 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/maxSurgetune how aggressively old Pods are replaced.
Best Practices
- Always set resource
requestsandlimitson 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.