Kubernetes primer¶
This chapter is the vocabulary you need for the rest of the guide. If you already know what a CRD and an operator are, skim it and move on. Nothing here is specific to Postgres yet.
The one idea: desired state and reconciliation¶
Kubernetes is a system where you declare what you want, and a set of controllers continuously work to make reality match. You do not run commands like "start this container on that machine". You write a document that says "I want 3 copies of this running", and a controller keeps checking and fixing until that is true — and keeps it true afterwards.
flowchart LR
you["You: desired state<br/>(YAML manifest)"] --> api["API server<br/>(stores the wish)"]
api --> ctrl["Controller<br/>(reconcile loop)"]
ctrl -->|observe| world["Actual cluster state"]
ctrl -->|act to close the gap| world
world -->|status| api
This loop — observe, compare, act, repeat — is called reconciliation. It is the heartbeat of everything in Kubernetes, including the database operator we will use.
The objects you will meet¶
You describe everything as objects, usually in YAML. Each object has an
apiVersion, a kind, metadata (name, namespace, labels), and a spec (the
desired state). Controllers write back a status.
| Object | What it is, in plain terms |
|---|---|
| Pod | The smallest unit: one or more containers that run together. You rarely create these directly. |
| Deployment | "Keep N identical, stateless pods running." Handles rollouts and restarts. |
| StatefulSet | Like a Deployment but for stateful pods that need stable identity and their own storage. (CloudNativePG deliberately does not use these — see Why CloudNativePG.) |
| Service | A stable network name and virtual IP that load-balances to a changing set of pods. The key to not caring which pod is the primary. |
| Namespace | A folder for grouping and isolating objects (e.g. production, cnpg-system). |
| Secret | Base64-wrapped sensitive data (passwords, keys). Not encrypted by default — treat with care. |
| ConfigMap | Non-sensitive configuration as key/value pairs. |
Storage objects (important for databases)¶
flowchart LR
sc["StorageClass<br/>(how to make volumes:<br/>'longhorn-postgres')"] -->|template| pvc
pvc["PersistentVolumeClaim<br/>(a pod's request:<br/>'I need 20Gi')"] -->|bound to| pv["PersistentVolume<br/>(the actual disk)"]
pod["Pod"] -->|mounts| pvc
- A PersistentVolume (PV) is a real piece of storage.
- A PersistentVolumeClaim (PVC) is a pod's request for storage of a certain size and class.
- A StorageClass is a recipe that says how to provision a PV when a claim
appears (which driver, how many replicas, can it grow, etc.). We will define a
StorageClass called
longhorn-postgresand each database instance will get its own PVC from it.
Why this matters for Postgres
A database's data lives on a PVC. When a pod is rescheduled to another node, Kubernetes must re-attach (or rebuild) that PVC. How your storage handles that is the difference between a 10-second failover and a painful outage — which is exactly why storage choices get a whole chapter.
Operators and Custom Resources (CRDs)¶
Plain Kubernetes knows about Pods and Services, but it knows nothing about "a PostgreSQL cluster with a primary, two replicas, and point-in-time backups".
A Custom Resource Definition (CRD) teaches the API server a new kind of
object. After installing CloudNativePG, the API understands a kind: Cluster
in the postgresql.cnpg.io API group — a first-class object you can
kubectl get cluster, just like a Pod.
An operator is a controller written for a specific application. It watches those custom resources and runs the same reconcile loop, but with deep domain knowledge: it knows how to do a Postgres failover, run a base backup, rotate certificates, and so on.
flowchart TB
user["You apply a Cluster manifest"] --> api["API server (knows 'Cluster'<br/>thanks to the CRD)"]
api --> operator["CloudNativePG operator"]
operator -->|creates & manages| pods["Pods, PVCs, Services,<br/>Secrets, ConfigMaps"]
operator -->|"Postgres-aware actions:<br/>failover, backup, switchover"| pods
The mental model to keep
Plain Kubernetes gives you Lego bricks. An operator is an expert that assembles and maintains a specific machine out of those bricks for you.
NetworkPolicy (used later for security)¶
By default, any pod can talk to any other pod. A NetworkPolicy is a firewall rule expressed in Kubernetes: "only pods with label X may connect to these pods on port 5432". Whether it is enforced depends on your network plugin (CNI) — we cover that in Security.
kubectl, the remote control¶
Almost everything is done with kubectl, which talks to the API server using a
kubeconfig file (credentials + cluster address). A few commands you will use
constantly:
kubectl get pods -n production # list pods in a namespace
kubectl describe cluster pg -n production # detailed status & events
kubectl apply -f file.yaml # create/update from a manifest
kubectl logs <pod> -n production # read a pod's logs
kubectl get events -n production --sort-by=.lastTimestamp
apply is declarative: run it twice and nothing bad happens — Kubernetes just
reconciles to the state in the file.
Where to go deeper¶
Next: PostgreSQL high availability — the database side of the vocabulary.