reference · kubernetes 1.3x · kubectl

Architecture, workloads, and the commands you'll actually type

Kubernetes automates deploying, scaling, and healing containerized applications. This guide covers how a cluster is put together, the objects you'll build things out of, the controllers that keep them running, and a kubectl reference for daily work.

01 Cluster architecture

A cluster is a set of machines running containerized workloads, coordinated through a declarative API.

You describe the state you want; a set of controllers continuously works to make the actual state match it. Nodes split into two roles: control plane nodes make global decisions about the cluster and store all its state, while worker nodes run the actual application workloads, inside Pods.

                     ┌───────────────────────────────┐
                     │          Control Plane           │
                     │  kube-apiserver     etcd         │
                     │  kube-scheduler     controller-   │
                     │                     manager       │
                     └────────────────┬──────────────────┘
                                       │ HTTPS (API)
              ┌────────────────────────┼────────────────────────┐
              │                        │                        │
      ┌───────┴────────┐      ┌────────┴───────┐      ┌────────┴───────┐
      │  Worker Node 1  │      │  Worker Node 2  │      │  Worker Node N  │
      │  kubelet         │      │  kubelet         │      │  kubelet         │
      │  kube-proxy      │      │  kube-proxy      │      │  kube-proxy      │
      │  container       │      │  container       │      │  container       │
      │  runtime         │      │  runtime         │      │  runtime         │
      │  [Pod] [Pod]     │      │  [Pod] [Pod]     │      │  [Pod]           │
      └──────────────────┘      └──────────────────┘      └──────────────────┘

Every component talks to the API server; nothing talks to etcd directly except the API server itself. That makes it the single front door for reading or changing cluster state.

02 Control plane components

  • kube-apiserver — the front door. Exposes the Kubernetes REST API, handles authentication/authorization and admission control, validates and persists objects. Everything else is a client of it.
  • etcd — a distributed, consistent key-value store. The single source of truth for all cluster state.
  • kube-scheduler — watches for Pods with no node assigned yet and picks one, based on resource requests, affinity/anti-affinity rules, taints/tolerations, and topology constraints.
  • kube-controller-manager — runs the reconciliation loops (node controller, replication controller, endpoints controller, and more) that continuously watch actual state and drive it toward desired state.
  • cloud-controller-manager — cloud-provider-specific logic (provisioning load balancers, labeling nodes with cloud metadata). Only present on managed clusters (EKS, GKE, AKS).

03 Worker node components

  • kubelet — the agent on every node. Watches the API server for Pods assigned to its node and ensures the containers described in each Pod's spec are actually running and healthy.
  • kube-proxy — maintains the network rules (iptables or IPVS) on each node that implement the Service abstraction, routing traffic sent to a Service's virtual IP to one of its backing Pods.
  • Container runtime — the software that actually pulls images and runs containers (containerd, CRI-O), talked to by the kubelet through the Container Runtime Interface (CRI).

04 Cluster & kubeconfig

A cluster is one or more control plane nodes plus one or more worker nodes, operating as a single unit behind one API server (or a load-balanced set of API server replicas in production). Inside a cluster, namespaces let you logically partition resources (e.g. dev, staging, prod) without running separate clusters.

kubectl doesn't know which cluster to talk to on its own — it reads a kubeconfig file (default ~/.kube/config) holding one or more clusters, users (credentials), and contexts (a cluster + user + default namespace, bundled together and given a name you can switch to).

05 Image

A container image is an immutable, layered filesystem plus metadata (entrypoint/cmd, environment defaults, exposed ports), built once (typically from a Dockerfile) and pushed to a registry (Docker Hub, ECR, GCR, GHCR). Kubernetes pulls images by reference: registry/name:tag, optionally pinned to an exact @sha256:digest for full immutability.

imagePullPolicyBehavior
IfNotPresentPull only if the image isn't already cached on the node (default for explicit tags).
AlwaysAlways check the registry, re-pull if the tag now points to a different digest. Default when the tag is :latest.
NeverOnly use what's already on the node; fail if it's not there.

06 Container

A container is a running instance of an image, isolated from the host and other containers via Linux namespaces (PID, network, mount, ...) and resource-limited via cgroups. In Kubernetes, containers never run standalone — they always run inside a Pod. A Pod can define:

  • init containers — run to completion, in order, before any app container starts (common for setup/migrations).
  • app containers — the long-running main process(es) of the Pod.
  • sidecar containers — auxiliary containers that run alongside the app container for its whole lifetime (log shippers, proxies).

07 Pod

The Pod is the smallest deployable unit in Kubernetes: one or more containers always scheduled together on the same node, sharing a network namespace (same IP address, containers reach each other over localhost) and optionally storage volumes. Pods are ephemeral and not self-healing on their own — if a bare Pod's node fails or the Pod is deleted, nothing recreates it. That's why Pods are almost always created indirectly, through a controller like a Deployment or StatefulSet, rather than by hand.

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  labels:
    app: nginx
spec:
  containers:
    - name: nginx
      image: nginx:1.27
      ports:
        - containerPort: 80

08 ReplicaSet

A ReplicaSet ensures a specified number of identical Pod replicas are running at all times, using a label selector to identify which Pods it's responsible for. If a Pod it manages dies, it creates a replacement; if there are too many matching Pods, it deletes the excess. In practice you rarely create a ReplicaSet directly — a Deployment creates and manages one for you.

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: nginx-rs
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.27

09 Deployment

A Deployment is the standard way to run stateless applications. You describe the desired Pod template and replica count declaratively; the Deployment controller creates and owns a ReplicaSet, which in turn owns the Pods. Change the Pod template (e.g. a new image tag) and the Deployment performs a controlled rolling update — spinning up new Pods and retiring old ones gradually, governed by maxSurge/maxUnavailable — and you can roll it back with a single command if it goes wrong.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.27
          ports:
            - containerPort: 80

10 StatefulSet

A StatefulSet is for workloads that need stable, unique identity and stable storage per replica — databases, Kafka, ZooKeeper, anything where "replica 0" and "replica 1" aren't interchangeable. It differs from a Deployment in three ways:

  • Pods get stable, predictable names<name>-0, <name>-1, ... — instead of a random hash suffix.
  • Pods are created and scaled in order by default (0, 1, 2, ... up; reverse order down), rather than all at once.
  • Each replica gets its own PersistentVolumeClaim via volumeClaimTemplates, which survives Pod rescheduling — Pod -0 always reattaches to the same volume it had before.

A StatefulSet also needs a headless Service (clusterIP: None) so each Pod gets a stable DNS name: <pod-name>.<service-name>.<namespace>.svc.cluster.local.

apiVersion: v1
kind: Service
metadata:
  name: postgres-headless
spec:
  clusterIP: None
  selector:
    app: postgres
  ports:
    - port: 5432
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: postgres
spec:
  serviceName: postgres-headless
  replicas: 3
  selector:
    matchLabels:
      app: postgres
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
        - name: postgres
          image: postgres:16
          volumeMounts:
            - name: data
              mountPath: /var/lib/postgresql/data
  volumeClaimTemplates:
    - metadata:
        name: data
      spec:
        accessModes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 10Gi

11 Liveness & readiness probes

ProbeQuestion it answersOn failure
livenessProbe Is this container still alive/healthy? kubelet kills and restarts the container (per its restartPolicy) — recovers a deadlocked or stuck process.
readinessProbe Is this container ready to receive traffic right now? The Pod is pulled out of every Service's endpoint list — no restart, traffic just stops being routed to it until it passes again.
Related A third probe, startupProbe, delays liveness/readiness checks until a slow-starting container has finished booting, so a long startup isn't mistaken for a liveness failure and repeatedly restarted.

All three support the same check mechanisms — httpGet, tcpSocket, or exec — and the same tuning fields: initialDelaySeconds, periodSeconds, timeoutSeconds, successThreshold, failureThreshold.

containers:
  - name: web
    image: myapp:1.4
    livenessProbe:
      httpGet:
        path: /healthz
        port: 8080
      initialDelaySeconds: 10
      periodSeconds: 10
      failureThreshold: 3
    readinessProbe:
      httpGet:
        path: /ready
        port: 8080
      initialDelaySeconds: 5
      periodSeconds: 5
      failureThreshold: 2

12 kubectl cheat sheet

cluster & context

kubectl cluster-infoShow the API server and core service endpoints.
kubectl get nodes -o wideList nodes with IP/OS/kubelet version.
kubectl config get-contextsList available cluster/user/namespace contexts.
kubectl config use-context <name>Switch the active context.
kubectl config set-context --current --namespace=<ns>Set the default namespace for the current context.

namespaces

kubectl get nsList namespaces.
kubectl create ns <name>Create a namespace.

pods

kubectl get pods -o wide -n <ns>List Pods with node/IP.
kubectl describe pod <name>Full status, events, and probe/restart history — the first place to look when a Pod misbehaves.
kubectl logs <pod> [-c <container>] [-f]Stream container logs; -f follows.
kubectl logs <pod> --previousLogs from the previous (crashed) instance of the container.
kubectl exec -it <pod> -- shOpen a shell inside a running container.
kubectl port-forward pod/<name> 8080:80Forward a local port to a port inside the Pod.
kubectl delete pod <name>Delete a Pod (its controller will usually recreate it).

deployments

kubectl create deployment <name> --image=<img>Quickly create a Deployment imperatively.
kubectl get deploymentsList Deployments and their ready/up-to-date/available counts.
kubectl scale deployment <name> --replicas=5Change the replica count.
kubectl set image deployment/<name> <container>=<image>:<tag>Trigger a rolling update to a new image.
kubectl rollout status deployment/<name>Watch a rollout until it completes.
kubectl rollout history deployment/<name>List past revisions.
kubectl rollout undo deployment/<name> [--to-revision=N]Roll back to the previous (or a specific) revision.

replicasets & statefulsets

kubectl get rsList ReplicaSets (usually one per Deployment revision).
kubectl get stsList StatefulSets.
kubectl scale statefulset <name> --replicas=3Scale a StatefulSet (respects ordered creation/deletion).
kubectl rollout status statefulset/<name>Watch a StatefulSet rollout.

services

kubectl get svcList Services and their cluster IPs/ports.
kubectl expose deployment <name> --port=80 --target-port=8080Create a Service in front of a Deployment.

manifests & labels

kubectl apply -f file.yamlCreate or update resources declaratively from a manifest.
kubectl apply -f dir/Apply every manifest in a directory.
kubectl delete -f file.yamlDelete everything defined in a manifest.
kubectl diff -f file.yamlPreview what apply would change.
kubectl get pods -l app=webFilter by label selector.
kubectl label pod <name> env=prodAdd/update a label on a live object.

debugging & config objects

kubectl get events --sort-by=.lastTimestampCluster-wide events, newest last — useful for scheduling/pull failures.
kubectl top pods / kubectl top nodesLive CPU/memory usage (requires metrics-server).
kubectl create configmap <name> --from-literal=key=valueCreate a ConfigMap for non-secret config.
kubectl create secret generic <name> --from-literal=key=valueCreate a Secret for sensitive config.