Kubernetes Vocabulary

41 core Kubernetes terms in plain English — what each one means, a YAML manifest or kubectl example, and the gotcha worth knowing before production.

Last reviewed:

Sections

Workloads

Pod

The smallest deployable unit in Kubernetes — one or more containers that share a network namespace and storage. You rarely create Pods directly; a controller makes them for you.

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

💡 Containers in the same Pod reach each other on localhost and share volumes.

Deployment

The standard way to run stateless apps. It manages a ReplicaSet and gives you rolling updates, rollbacks, and a declared replica count.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 3
  selector:
    matchLabels: { app: web }
  template:
    metadata:
      labels: { app: web }
    spec:
      containers:
        - name: web
          image: nginx:1.27

💡 Change the image and Kubernetes rolls Pods one batch at a time with zero downtime.

ReplicaSet

Keeps a fixed number of identical Pods running. Deployments create and manage ReplicaSets for you — you almost never touch one directly.

kubectl get rs
# web-7d9f8c   3   3   3   2m

💡 Each rollout of a Deployment creates a new ReplicaSet; old ones are kept for rollback.

StatefulSet

Like a Deployment but for stateful apps that need stable network identities and stable per-Pod storage — databases, queues, clustered services.

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: db
spec:
  serviceName: db
  replicas: 3
  selector:
    matchLabels: { app: db }
  template:
    metadata:
      labels: { app: db }
    spec:
      containers:
        - name: db
          image: postgres:16

💡 Pods get ordinal names (db-0, db-1, db-2) and keep them across reschedules.

DaemonSet

Runs exactly one copy of a Pod on every node (or a subset). Used for node-level agents — log collectors, metrics exporters, CNI plugins.

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: log-agent
spec:
  selector:
    matchLabels: { app: log-agent }
  template:
    metadata:
      labels: { app: log-agent }
    spec:
      containers:
        - name: agent
          image: fluent-bit:3.1

💡 Add a node and a DaemonSet Pod appears on it automatically.

Job

Runs a Pod to completion — a batch task that should run once, succeed, and stop. Kubernetes retries it until the configured number of completions succeed.

apiVersion: batch/v1
kind: Job
metadata:
  name: migrate
spec:
  backoffLimit: 4
  template:
    spec:
      restartPolicy: Never
      containers:
        - name: migrate
          image: myapp:1.0
          command: ["./migrate.sh"]

💡 Use for migrations, one-off imports, and processing tasks.

CronJob

Creates Jobs on a cron schedule. The Kubernetes equivalent of crontab — for backups, reports, and periodic cleanup.

apiVersion: batch/v1
kind: CronJob
metadata:
  name: nightly-backup
spec:
  schedule: "0 2 * * *"
  jobTemplate:
    spec:
      template:
        spec:
          restartPolicy: OnFailure
          containers:
            - name: backup
              image: backup-tool:2.0

💡 Schedule uses standard cron syntax in the cluster timezone (UTC by default).

Networking

Service

A stable network endpoint in front of a set of Pods. Pods come and go, but the Service gives them one steady virtual IP and DNS name.

apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  selector: { app: web }
  ports:
    - port: 80
      targetPort: 8080

💡 The selector matches Pod labels; traffic is load-balanced across matching Pods.

ClusterIP

The default Service type. Gives the Service an internal-only virtual IP reachable from inside the cluster — not from the outside world.

spec:
  type: ClusterIP   # default, can be omitted
  ports:
    - port: 80

💡 Reach it by DNS name: <service>.<namespace>.svc.cluster.local.

NodePort

A Service that opens the same high port (30000–32767) on every node. External traffic hitting any node IP on that port reaches the Service.

spec:
  type: NodePort
  ports:
    - port: 80
      targetPort: 8080
      nodePort: 30080

💡 Crude but dependency-free. Usually fronted by an external load balancer in production.

LoadBalancer

A Service that asks the cloud provider to provision an external load balancer with a public IP pointing at the Service.

spec:
  type: LoadBalancer
  ports:
    - port: 443
      targetPort: 8443

💡 Only works where the cloud controller supports it (AWS, GCP, Azure, etc.).

Ingress

HTTP/HTTPS routing rules — host- and path-based — that send external traffic to Services. Needs an Ingress controller (nginx, Traefik) to do the actual work.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web
spec:
  rules:
    - host: example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: web
                port: { number: 80 }

💡 One external IP can serve many domains and paths through a single Ingress controller.

NetworkPolicy

A firewall for Pods. Declares which Pods may talk to which, by label and port. Without one, all Pods can reach all others.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: db-allow-api
spec:
  podSelector:
    matchLabels: { app: db }
  ingress:
    - from:
        - podSelector:
            matchLabels: { app: api }

💡 Only enforced if the CNI plugin supports it (Calico, Cilium); flannel does not.

Configuration

ConfigMap

Stores non-secret configuration as key/value pairs. Mount it as files or inject it as environment variables — keeps config out of the image.

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  LOG_LEVEL: "info"
  feature.flags: "beta=on"

💡 Updating a mounted ConfigMap eventually updates the files; env vars need a Pod restart.

Secret

Like a ConfigMap but for sensitive data — passwords, tokens, TLS keys. Stored base64-encoded and handled with extra care by the API.

apiVersion: v1
kind: Secret
metadata:
  name: db-creds
type: Opaque
stringData:
  password: s3cr3t

💡 Base64 is encoding, not encryption — enable encryption-at-rest and RBAC to protect Secrets.

Namespace

A virtual cluster inside a cluster. Groups resources, scopes names, and is the boundary for quotas and RBAC.

kubectl create namespace staging
kubectl get pods -n staging

💡 Default objects live in the "default" namespace; system components live in "kube-system".

Storage

PersistentVolume (PV)

A piece of cluster storage provisioned by an admin or a StorageClass. It exists independently of any Pod that uses it.

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-data
spec:
  capacity: { storage: 10Gi }
  accessModes: ["ReadWriteOnce"]
  hostPath: { path: /mnt/data }

💡 A PV is the actual storage; a PVC is the request to use it.

PersistentVolumeClaim (PVC)

A Pod's request for storage — "I need 10Gi, ReadWriteOnce". Kubernetes binds it to a matching PV or provisions one dynamically.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: data
spec:
  accessModes: ["ReadWriteOnce"]
  resources:
    requests: { storage: 10Gi }

💡 Pods mount the PVC, not the PV directly — this decouples apps from storage details.

StorageClass

A template for dynamically provisioning PVs. Defines the provisioner (e.g. an EBS or GCE PD driver) and parameters like disk type.

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast-ssd
provisioner: ebs.csi.aws.com
parameters:
  type: gp3

💡 A PVC referencing a StorageClass triggers on-demand disk creation — no manual PV needed.

Volume

A directory accessible to containers in a Pod. Many types exist — configMap, secret, emptyDir, persistentVolumeClaim, hostPath.

spec:
  volumes:
    - name: cache
      emptyDir: {}
  containers:
    - name: app
      volumeMounts:
        - name: cache
          mountPath: /cache

💡 A Volume's lifetime is tied to the Pod (except PVC-backed volumes, which persist).

emptyDir

A scratch volume created empty when a Pod starts and deleted when the Pod is removed. Good for caches and sharing files between containers in one Pod.

volumes:
  - name: tmp
    emptyDir:
      sizeLimit: 500Mi

💡 Set medium: Memory to back it with RAM (tmpfs) for speed.

kubectl verbs

get

List resources. The first command you reach for. Add -o wide, -o yaml, or -o json for more detail.

kubectl get pods -n prod -o wide
kubectl get deploy,svc,ingress

💡 Add --watch (-w) to stream changes live.

describe

Show a detailed, human-readable dump of one resource — including recent Events, which is where you find why a Pod won't start.

kubectl describe pod web-7d9f8c-abc12

💡 The Events section at the bottom is the single most useful debugging output.

apply

Create or update resources from a manifest, declaratively. Kubernetes diffs your file against the live state and reconciles.

kubectl apply -f deployment.yaml
kubectl apply -k ./overlays/prod

💡 Prefer apply over create — it is idempotent and tracks the last-applied config.

delete

Remove resources by name, label, or file. Deleting a Deployment also removes its Pods.

kubectl delete pod web-7d9f8c-abc12
kubectl delete -f deployment.yaml

💡 Add --grace-period=0 --force to kill a stuck Pod immediately (use sparingly).

exec

Run a command inside a running container — usually an interactive shell for debugging.

kubectl exec -it web-7d9f8c-abc12 -- sh

💡 The -- separates kubectl flags from the command you want to run in the container.

logs

Print a container's stdout/stderr. Add -f to follow, --previous to see the crashed container's logs.

kubectl logs -f web-7d9f8c-abc12
kubectl logs web-7d9f8c-abc12 --previous

💡 For multi-container Pods, pick one with -c <container>.

port-forward

Tunnel a local port to a Pod or Service port. Lets you hit an internal service from your laptop without exposing it.

kubectl port-forward svc/web 8080:80

💡 Great for debugging databases and dashboards that have no public endpoint.

scale

Change the replica count of a Deployment, ReplicaSet, or StatefulSet imperatively.

kubectl scale deployment web --replicas=5

💡 Manual scaling is overridden by an HPA if one targets the same workload.

rollout

Manage and inspect rolling updates — check status, pause, resume, undo to a previous revision, or restart Pods.

kubectl rollout status deployment/web
kubectl rollout undo deployment/web
kubectl rollout restart deployment/web

💡 rollout restart cycles Pods without changing the spec — handy to reload config or Secrets.

edit

Open a live resource in your editor and apply changes on save. Quick fixes, but changes are not tracked in your manifests.

kubectl edit deployment web

💡 Convenient for hotfixes; for anything lasting, edit the YAML and apply it.

Resources & scheduling

requests

The amount of CPU/memory a container is guaranteed. The scheduler uses requests to decide which node a Pod fits on.

resources:
  requests:
    cpu: "250m"
    memory: "256Mi"

💡 250m means 0.25 of a CPU core; memory is in bytes with Ki/Mi/Gi suffixes.

limits

The hard cap on CPU/memory a container may use. Exceeding the memory limit gets the container OOM-killed; CPU is throttled, not killed.

resources:
  limits:
    cpu: "500m"
    memory: "512Mi"

💡 A frequent cause of mysterious restarts is hitting the memory limit (OOMKilled).

QoS classes

Quality of Service tiers Kubernetes assigns from your requests/limits: Guaranteed (limits == requests on all containers), Burstable (some requests set), BestEffort (none set).

# Guaranteed:
resources:
  requests: { cpu: "500m", memory: "512Mi" }
  limits:   { cpu: "500m", memory: "512Mi" }

💡 Under node pressure, BestEffort Pods are evicted first, Guaranteed last.

HPA (HorizontalPodAutoscaler)

Automatically scales the replica count of a workload up or down based on metrics like CPU utilisation or custom metrics.

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: web
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: web
  minReplicas: 2
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target: { type: Utilization, averageUtilization: 70 }

💡 Requires the metrics-server and CPU/memory requests set on the Pods.

node

A worker machine (VM or physical) that runs Pods. Each node runs the kubelet and a container runtime.

kubectl get nodes -o wide
kubectl describe node ip-10-0-1-23

💡 Control-plane nodes run the API server, scheduler, and etcd; worker nodes run your Pods.

label

A key/value tag attached to objects. The glue of Kubernetes — Services, selectors, and tooling all match on labels.

metadata:
  labels:
    app: web
    tier: frontend
    env: prod

💡 kubectl get pods -l app=web,env=prod filters by label.

selector

A query over labels. Services, Deployments, and NetworkPolicies use selectors to find the Pods they apply to.

selector:
  matchLabels:
    app: web

💡 A Service's selector must match its Pods' labels or it routes to nothing.

annotation

A key/value note attached to an object for tools and humans — not used for selection. Holds metadata like ingress config or change cause.

metadata:
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    kubernetes.io/change-cause: "bump to v1.27"

💡 Unlike labels, annotations are not indexed and can hold large or structured values.

taint

A mark on a node that repels Pods. Only Pods with a matching toleration may schedule there. Used to reserve nodes (e.g. GPU nodes).

kubectl taint nodes gpu-1 \
  dedicated=gpu:NoSchedule

💡 Effects: NoSchedule (block new), PreferNoSchedule (avoid), NoExecute (also evict existing).

toleration

A Pod's permission to schedule onto a node with a matching taint. Tolerations do not force placement — they only allow it.

spec:
  tolerations:
    - key: "dedicated"
      operator: "Equal"
      value: "gpu"
      effect: "NoSchedule"

💡 Pair with nodeSelector or affinity to actually pull the Pod onto the tainted node.

English phrases engineers use

  • "The Pod is stuck in CrashLoopBackOffkubectl logs --previous shows it's OOMKilled, so bump the memory limit."
  • "kubectl describe the Pod and read the Events — it's failing to pull the image."
  • "The Service selector doesn't match the new Pod labels, so traffic is going nowhere."
  • "Let's roll out the new image and watch kubectl rollout status; if it stalls we'll undo."
  • "Put the DB on a StatefulSet with a PVC so each replica keeps its own volume."
  • "Add an HPA targeting 70% CPU and set requests, or it has nothing to scale on."
  • "Taint the GPU nodes and give the ML Pods a matching toleration."