Isolating the Database

Isolating BookNest's Database with a NetworkPolicy

PostgreSQL 1,289 has two kinds of legitimate client: the API and the schema Jobs (PostgreSQL StatefulSet and Migration Job), whose Pods carry an automatic batch.kubernetes.io/job-name label. One policy admits both and refuses the rest:

k8s/network-policies.yaml: only the API and Jobs may reach PostgreSQLYAML
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata: { name: postgres, labels: { app: booknest } }
spec:
  podSelector: { matchLabels: { tier: db } }
  policyTypes: [Ingress]
  ingress:
  - from:
    - podSelector: { matchLabels: { tier: api } }
    - podSelector:
        matchExpressions: [{ key: batch.kubernetes.io/job-name, operator: Exists }]
    ports: [{ port: 5432 }]
The database policy tested from a plain Pod and from a JobShell
kubectl apply -f k8s/network-policies.yaml
kubectl run dbcheck --image=localhost:33500/postgres:18 --restart=Never -- \
  pg_isready -h postgres -t 3 >/dev/null 2>&1
kubectl create job dbcheck --image=localhost:33500/postgres:18 -- pg_isready -h postgres -t 3 \
  2>/dev/null
kubectl wait --for=condition=Complete job/dbcheck >/dev/null
kubectl wait --for=jsonpath='{.status.phase}'=Failed pod/dbcheck >/dev/null
kubectl logs pod/dbcheck; kubectl logs job/dbcheck
kubectl delete pod/dbcheck job/dbcheck >/dev/null
git add k8s/network-policies.yaml
git commit -qm "Let only the API and Jobs reach PostgreSQL"
Output
networkpolicy.networking.k8s.io/postgres created
job.batch/dbcheck created
postgres:5432 - no response
postgres:5432 - accepting connections

The plain Pod got no response, the Job was accepted, and the API Pods stayed ready. The two podSelector entries under from are alternatives (API or Job), unlike the combined entry in Policy Rules. Any Job may connect, a deliberate trade, since only administrators and the pipeline (Pipeline RBAC) create Jobs here.