We closed the previous lesson with the map of the cluster's pieces: apiserver, etcd, scheduler, controllers, kubelet. Those are the pieces that run Kubernetes. Now comes the other vocabulary, the one you will be writing every day: pods, Deployments, Services, ConfigMaps, PVCs, namespaces. It is a large vocabulary and the temptation is to learn it like a dictionary, term by term, which is a bad idea: Kubernetes concepts are not independent, they form families with clear hierarchical relationships. This lesson gives you that complete mental map, so that when a PersistentVolumeClaim turns up in module 5 you already know where it fits and who it talks to. We are not going to work through the practical use of each object —each one has its own lesson— but to place them on the map.

Contents

  1. The foundation: resource, object and API
  2. Cluster and node
  3. The pod: the smallest unit
  4. The workload family
  5. The networking family
  6. The configuration family
  7. The storage family
  8. Organisation: namespaces, labels, selectors and annotations
  9. Controllers, operators and CRDs
  10. Master table of concepts

  1. The foundation: resource, object and API

Before the concrete names, three terms that get confused constantly:

Term Definition Example
Resource A type of entity the API knows how to handle, with its endpoint pods, deployments, services
Object A concrete instance of a resource, stored in etcd The pod called bookings-api-7d9f in rutas-norte-dev
Manifest The YAML file describing the object you want k8s/base/bookings-api.yaml

And the rule that governs the whole system, which we already saw in the architecture:

  • spec: what you want. You write it.
  • status: what is really there. The cluster writes it.

Everything that exists in Kubernetes —an application, a virtual IP, a password, a disk, a permission— is an object with spec and status stored in the same API. That uniformity is what makes a single command, kubectl get, work for everything. The detailed anatomy of an object is covered in Objects, YAML Manifests and the Declarative Model.

  1. Cluster and node

  • Cluster: the whole set. A control plane plus a group of nodes that present themselves as a single system. When you say "I deploy to the cluster", you are saying "I hand my intention to the API and let the system decide where".
  • Node: a machine —physical or virtual— that runs workloads. It is also an API object: kubectl get nodes proves it. It has capacity (CPU, memory, maximum pods), labels (zone, disk type) and conditions (Ready, MemoryPressure).

Rutas Norte will use a single-node practice cluster (minikube) throughout the course, and we will talk about multi-node clusters when we get to scheduling (module 6) and high availability (module 9).

  1. The pod: the smallest unit

This is the foundational concept, and the one that surprises people most when they come from Docker.

Kubernetes does not run containers: it runs pods. A pod is a group of one or more containers that share networking and storage and are always scheduled together on the same node.

What the containers in a pod share:

  • A single IP. They see each other over localhost and cannot use the same port.
  • The volumes declared in the pod.
  • The lifecycle: they are born together, they die together, they move together.

In the vast majority of cases —and in almost all of Rutas Norte's— a pod contains a single container. Multi-container pods are reserved for specific patterns (sidecar, init container, adapter) covered in module 6.

Two properties of the pod to internalise from day one:

  1. It is ephemeral. A pod is not "repaired" and it does not move: if its node goes down, that pod is written off and a brand-new one is created, with a different name and a different IP. Never depend on a pod's name or IP.
  2. It is rarely created by hand. A loose pod has nobody to bring it back. Except for one-off tests, it is always created through a workload controller. In the lesson The Course Project you will create a loose one precisely to experience that fragility first-hand.

A minimal snippet, just to see the shape:

apiVersion: v1
kind: Pod
metadata:
  name: bookings-api
spec:
  containers:
    - name: api
      image: registry.rutasnorte.example/bookings-api:2.4.0

  1. The workload family

All these objects have the same purpose: creating and maintaining pods. They differ in how and when.

4.1. The essential hierarchy

flowchart TD
    D["Deployment<br/>manages versions"] --> RS["ReplicaSet<br/>guarantees N replicas"]
    RS --> P1["Pod"]
    RS --> P2["Pod"]
    RS --> P3["Pod"]
    P1 --> C1["container"]
    P2 --> C2["container"]
    P3 --> C3["container"]

Read it like this, from the bottom up:

  • The container runs your process.
  • The pod wraps one or more containers and is the unit that gets scheduled onto a node.
  • The ReplicaSet makes sure there are exactly N identical pods; if one is missing, it creates it.
  • The Deployment manages ReplicaSets so it can change version gradually: it creates a new ReplicaSet with the new image and shrinks the old one.

That is why you write Deployments, hardly ever ReplicaSets or Pods. The ReplicaSet does exist, and you will see it with kubectl get rs, but it is an intermediary the Deployment manages for you.

4.2. The six workloads

Object What it is for Distinguishing trait In Rutas Norte
Deployment Stateless applications, with interchangeable replicas Progressive update and rollback web-store, bookings-api, notifications-worker
ReplicaSet Keeping N identical copies Managed by the Deployment; not written by hand Created automatically by the above
StatefulSet Stateful applications with a stable identity Fixed names (-0, -1), a disk of its own per replica, ordered start-up bookings-postgres
DaemonSet One copy on every node Adjusts itself when nodes are added or removed Log and metrics agents (module 7)
Job A task that runs to completion It finishes; it can retry and parallelise Database schema migrations
CronJob A Job launched on a schedule cron syntax occupancy-reports, overnight

The key question when choosing is always the same: are my replicas interchangeable? If any of them can serve any request and they store nothing on disk, it is a Deployment. If each replica has its own identity and data, it is a StatefulSet.

  1. The networking family

Pods are ephemeral and their IPs change. The networking family exists to add stability and reachability on top of that chaos.

  • Service: a stable virtual IP and DNS name that spread traffic across a set of pods, chosen by labels. It is the piece that makes it possible for web-store to call bookings-api by name without knowing any IP. Main types: ClusterIP (internal, the usual one), NodePort and LoadBalancer (external exposure), and ExternalName.
  • Ingress: HTTP/HTTPS rules that route by domain and path to different Services, with TLS termination. It is what will let us publish www.rutasnorte.example and api.rutasnorte.example on a single public IP. An Ingress does nothing on its own: it needs an Ingress Controller installed in the cluster (NGINX, Traefik…).
  • NetworkPolicy: a firewall at pod level. By default, in Kubernetes every pod can talk to every other pod. A NetworkPolicy restricts that: for example, so that only bookings-api may connect to bookings-postgres. Since that database stores personal data, it is not optional for Rutas Norte.
  • EndpointSlice: the automatically maintained list of the healthy pod IPs sitting behind a Service. You do not write it by hand, but it is the first thing to look at when a Service "goes nowhere".
flowchart LR
    U["User<br/>www.rutasnorte.example"] --> ING["Ingress"]
    ING --> SVC1["Service<br/>web-store"]
    ING --> SVC2["Service<br/>bookings-api"]
    SVC1 --> PA["Pod web-store"]
    SVC1 --> PB["Pod web-store"]
    SVC2 --> PC["Pod bookings-api"]
    SVC2 --> PD["Pod bookings-api"]
    PC --> SVC3["Service<br/>bookings-postgres"]
    PD --> SVC3
    SVC3 --> PG["Pod bookings-postgres"]

  1. The configuration family

The golden rule: the image contains the code; never the configuration or the credentials. The very same bookings-api:2.4.0 image must be able to run in rutas-norte-dev and in rutas-norte-pro without being rebuilt.

Object Content How it reaches the container Warning
ConfigMap Non-sensitive configuration: URLs, cache sizes, .conf files Environment variables or a mounted file It encrypts nothing; do not put passwords in it
Secret Sensitive data: passwords, tokens, TLS certificates Same as the ConfigMap It is base64-encoded, which is not encryption; it needs RBAC and encryption at rest
ServiceAccount The identity of a pod towards the Kubernetes API Token mounted automatically Different from a person's identity

One detail that prevents a lot of misunderstandings: base64 is encoding, not protection. Anyone with read permission on Secrets can decode them in a second. Real protection comes from RBAC (module 8) and from etcd's encryption at rest.

Related to this family are resource limits (CPU and memory requests and limits), the per-namespace ResourceQuota and the LimitRange, all covered in module 3, which determine the pod's quality of service (QoS) class.

  1. The storage family

A container's filesystem is ephemeral: on restart, it is lost. For bookings-postgres that is unacceptable, hence this family.

Object What it is Analogy
Volume A directory mounted in the pod, defined inside the pod itself A shared directory; many types die with the pod (emptyDir)
PersistentVolume (PV) A piece of real cluster storage, with a life independent of the pod The physical disk available
PersistentVolumeClaim (PVC) A user's request: "I want 20 GiB in read-write mode" The voucher you exchange for a disk
StorageClass The "type" of storage and how it is provisioned automatically The catalogue: ssd-fast, hdd-cheap

The normal flow, which you will see in module 5, is: you declare a PVC in your manifest → the StorageClass dynamically provisions a real PV → the PVC is bound to it → the pod mounts that PVC as a volume. As a developer, you almost always write only the PVC.

The PV/PVC split reflects a division of responsibilities: the cluster administrator manages supply (PVs and StorageClasses), the developer expresses demand (PVCs), and neither needs to know the other's details.

  1. Organisation: namespaces, labels, selectors and annotations

With 40 objects, the cluster becomes unmanageable without organisation. Kubernetes offers two complementary axes.

8.1. Namespace: the hard division

A namespace is a logical partition of the cluster. Rutas Norte will use three: rutas-norte-dev, rutas-norte-pre and rutas-norte-pro.

What a namespace gives you:

  • Name uniqueness: there can be a bookings-api Service in each one with no conflict.
  • RBAC scope: "this team can deploy to dev but only read in pro".
  • Quota scope: CPU and memory limits per environment.
  • DNS: a service resolves as bookings-api.rutas-norte-dev.svc.cluster.local.

What it does not give you: network isolation (that is what NetworkPolicy is for) or node isolation. On top of that, some objects are cluster-scoped and live in no namespace: Node, PersistentVolume, StorageClass, ClusterRole, and Namespace itself.

8.2. Labels and selectors: the soft division

A label is a key-value pair attached to an object. A selector is a query over labels. This pair is the coupling mechanism of the whole of Kubernetes: a Service does not know its pods by name, it finds them by label. A ReplicaSet does the same with its replicas.

Conventions Rutas Norte will use on every object:

metadata:
  labels:
    app: bookings-api                       # the component
    app.kubernetes.io/part-of: rutas-norte  # the platform
    environment: dev                        # the environment

And the matching selector in a Service:

spec:
  selector:
    app: bookings-api
    environment: dev

Annotations are also key-value pairs, but with the opposite purpose: you cannot select on them. They are there to attach metadata consumed by tools: an Ingress Controller's configuration, the Git commit that triggered the deployment, a certificate identifier. Rule of thumb: if you are going to filter by it, label; if it is information for a tool or for a human, annotation.

  1. Controllers, operators and CRDs

These three close the map and are the door to the advanced part of the course.

  • Controller: a process that runs the previous lesson's reconciliation loop over one type of object. The ReplicaSet controller watches ReplicaSets and creates pods. It is the universal Kubernetes pattern.
  • CRD (Custom Resource Definition): an object that defines a new type of object. When you apply a CRD, your cluster's API starts to understand, for example, kind: Certificate or kind: PostgresCluster, with its own kubectl get certificates.
  • Operator: the combination of a CRD with a controller of its own that knows how to reconcile it. It is "an expert administrator's knowledge turned into software": a PostgreSQL operator can create replicas, take backups and run a failover with no human intervention.
flowchart LR
    CRD["CRD<br/>defines the PostgresCluster type"] --> API["Kubernetes API"]
    CR["PostgresCluster object<br/>'bookings', 3 replicas"] --> API
    API --> CTRL["Operator controller"]
    CTRL --> SS["StatefulSet"]
    CTRL --> SVC["Services"]
    CTRL --> SEC["Secrets"]
    CTRL --> PVC["PVCs"]

When in module 6 you weigh up whether bookings-postgres should be managed with a StatefulSet of your own or with an operator, this will be the key distinction.

  1. Master table of concepts

Keep this table: it is the conceptual index of the whole course.

Concept What it is in one sentence Where we will see it in Rutas Norte Module
Cluster Control plane + nodes as a single system The practice cluster and the future production one 1, 10
Node A machine that runs pods minikube's single node; multi-node with kind 1, 6
Pod The smallest unit: containers sharing networking and disk The first deployment of web-store 1, 2
ReplicaSet Guarantees N identical pods Created by the Deployments 2
Deployment Manages ReplicaSets to deploy and update without downtime web-store, bookings-api, notifications-worker 2
StatefulSet Replicas with their own identity and disk bookings-postgres 6
DaemonSet One pod per node Log and metrics agent 6, 7
Job A task that runs to completion Bookings schema migration 6
CronJob A Job scheduled by time occupancy-reports, every night 6
Service A stable IP and name + balancing towards pods bookings-api, bookings-postgres, redis-cache 2, 4
Ingress HTTP routing by domain and path, with TLS www.rutasnorte.example, api.rutasnorte.example 4
NetworkPolicy A firewall between pods Only the API reaches the database 4, 8
ConfigMap Externalised non-sensitive configuration The API's parameters and the store's nginx.conf 3
Secret Sensitive data managed separately bookings-postgres password, SMTP credentials 3, 8
ServiceAccount The pod's identity towards the API A minimal account for each component 3, 8
Volume A directory mounted in the pod Temporary cache, files shared between containers 5
PersistentVolume Real storage with a life of its own The database's disk 5
PersistentVolumeClaim A storage request The 20 GiB bookings-postgres asks for 5
StorageClass Catalogue and dynamic provisioning of disks minikube's default class and cloud classes 5
Namespace A logical partition of the cluster rutas-norte-dev, -pre, -pro 2
Label / selector Queryable metadata / a query over it app, environment, app.kubernetes.io/part-of 2
Annotation Non-queryable metadata, for tools Ingress configuration, deployed commit 2, 4
Resource / object A type of entity / a concrete instance Everything you write under k8s/ 1
Controller A process that reconciles one type of object The ones creating your pods without you seeing them 1, 6
CRD Defines a new type of object in the API The one cert-manager installs 4, 6
Operator CRD + controller with expert logic A managed alternative for PostgreSQL 6
HPA Adjusts the number of replicas automatically Bank-holiday and holiday peaks 9
Probe A container's health check The API's liveness and readiness 7
RBAC Who may do what on which resources Permissions for the team and for the pods 8

Common Mistakes and Tips

  • Confusing pod and container. A pod can have several containers, but it is scheduled, moved and scaled as a unit. "Scaling" means creating more pods, not more containers inside the pod.
  • Creating loose pods in production. Nobody brings them back. Always through a Deployment, StatefulSet, DaemonSet or Job.
  • Storing a password in a ConfigMap. It is the most frequent security mistake in real clusters. The ConfigMap/Secret distinction exists precisely so that different RBAC can be applied to each.
  • Assuming a Secret is encrypted. base64 is encoding. Without encryption at rest and RBAC, a Secret is plain text with one extra step.
  • Believing a namespace isolates the network. It does not: a pod in rutas-norte-dev can reach one in rutas-norte-pro unless a NetworkPolicy exists.
  • Changing labels casually. Labels are the coupling mechanism: if you modify a pod's label, its Service stops seeing it and its ReplicaSet creates a new one to replace it. This is done deliberately in some debugging techniques, but never by accident.
  • Tip: when an object you do not know turns up, ask yourself three questions — which family does it belong to (workload, networking, configuration, storage)?, which other object creates it or consumes it?, is it namespace-scoped or cluster-scoped? With those three answers you can already place it. And kubectl explain <resource> answers them without leaving the terminal.

Exercises

Exercise 1: Choosing the right object

For each Rutas Norte need, state which object (or combination of objects) you would use and why:

  1. Run 4 interchangeable copies of bookings-api and be able to move from version 2.4.0 to 2.5.0 without service downtime.
  2. Make bookings-postgres keep its data even if its pod is recreated, and always have the same name.
  3. Generate an occupancy report every night at 02:30.
  4. Let web-store reach bookings-api by a fixed name even though the replicas change IP.
  5. Keep the database password outside the image.
  6. Prevent notifications-worker from connecting directly to the database.

Exercise 2: The chain of responsibility

Explain in your own words, in 6 lines at most, what happens from the moment you write replicas: 3 in a Deployment until there are three containers running, naming all the objects and components involved. Then answer: if you delete one of those three pods by hand, who exactly recreates it?

Exercise 3: Label or annotation

Classify each piece of metadata as a label or an annotation and justify it in one line:

  1. app: bookings-api
  2. environment: pro
  3. rutasnorte.example/commit: 9f3a1c2
  4. nginx.ingress.kubernetes.io/proxy-body-size: 8m
  5. app.kubernetes.io/part-of: rutas-norte
  6. rutasnorte.example/owner: [email protected]

Solutions

Solution 1

  1. Deployment. It is a stateless application with interchangeable replicas; the Deployment manages ReplicaSets and enables progressive updates and rollback.
  2. StatefulSet + PersistentVolumeClaim (with its StorageClass behind it). The StatefulSet gives a stable identity (bookings-postgres-0) and a PVC of its own per replica that survives the pod being recreated.
  3. CronJob, which in turn creates a Job and that a Pod on each scheduled run.
  4. A Service of type ClusterIP. It provides a stable DNS name and virtual IP and spreads traffic across the healthy pods selected by label.
  5. A Secret, mounted as an environment variable or a file, with restrictive RBAC. Never a ConfigMap.
  6. A NetworkPolicy allowing ingress traffic to bookings-postgres only from pods carrying the label app: bookings-api.

Solution 2

You write the Deployment and apply it; the apiserver stores it in etcd. The Deployment controller creates a ReplicaSet with replicas: 3. The ReplicaSet controller observes that there are 0 pods and creates 3 Pod objects. The kube-scheduler assigns a node to each. Each node's kubelet asks the runtime, over CRI, to pull the image and start the container. The full chain: Deployment → ReplicaSet → Pod → container.

If you delete a pod by hand, it is recreated by the ReplicaSet controller (not the Deployment): it detects that there are 2 pods where its spec asks for 3 and creates a new one, with a different name and IP.

Solution 3

  1. Label. It identifies the component and is the key Services and ReplicaSets select by.
  2. Label. It is used for filtering and for per-environment selectors.
  3. Annotation. It is traceability; you are never going to select objects by commit and the value changes on every deployment.
  4. Annotation. It is configuration consumed by the Ingress Controller, not a selection criterion.
  5. Label. A recommended standard label that lets you query the whole platform at once (-l app.kubernetes.io/part-of=rutas-norte).
  6. Annotation. Contact information for humans; filtering by it makes no sense and its free format does not fit a label's value restrictions.

Conclusion

You now have the complete map of the vocabulary: Kubernetes objects group into families with clear roles —workloads that create pods, networking that gives them stability and access, configuration that parameterises them, storage that gives them persistence— organised by namespaces and coupled to each other through labels and selectors, with controllers reconciling everything and CRDs and operators making it possible to extend the system. The Deployment → ReplicaSet → Pod → container hierarchy is the backbone worth keeping in mind at all times, and the master table serves as your index for the rest of the course.

So far, everything has been theory. It is time to have a cluster of your own in which to try out everything we learn: in the next lesson, Setting Up a Kubernetes Cluster, we will build the practice environment we will use across the twelve modules, step by step.

Kubernetes Course

Module 1: Introduction to Kubernetes

Module 2: Core Kubernetes Components

Module 3: Configuration and Secret Management

Module 4: Networking in Kubernetes

Module 5: Storage in Kubernetes

Module 6: Advanced Kubernetes Concepts

Module 7: Monitoring and Logging

Module 8: Kubernetes Security

Module 9: Scaling and Performance

Module 10: Kubernetes Ecosystem and Tooling

Module 11: Case Studies and Real-World Applications

Module 12: Preparing for Kubernetes Certification

© Copyright 2026. All rights reserved