d9315322fc
1. Renamed every object this demo creates (TerdutServer, Postgres
Secret/Deployment/Service) from terdut-demo[-postgres] to
terdut-operator-demo[-postgres]. The user applied this kit into the
already-live "terdut-demo" namespace -- the real operator exercise
from earlier in this repo's own history -- and this demo's own
TerdutServer/Postgres objects shared that exact name. The TerdutServer
apply was rejected outright (DatabaseSpec's own CEL rule: adding dsn
while the live object already had postgresClusterRef violates "exactly
one of" and the API server refused it), and the real Postgres Service
was never touched (confirmed live: still Zalando's own spilo selector,
endpoint still the real StatefulSet pod) -- but the Postgres Secret and
Deployment, having no such protection, were created as brand new,
extra, crash-looping objects sitting right next to the real ones.
Prefixing every name this demo creates means a repeat of this exact
mistake no longer collides with anything, documented directly in
README.md now.
2. The actual crash itself, independent of (1): capabilities.drop: ["ALL"]
(added responding to a PodSecurity "restricted" warning) took
CAP_CHOWN/CAP_FOWNER away from the root user postgres:17-alpine's own
entrypoint needs to chown/chmod the data directory before it drops
privileges itself -- confirmed in a real crashed pod's logs: `chmod:
/var/run/postgresql: Operation not permitted`. kubectl apply
--dry-run=server, which is as far as this got verified before, only
checks admission policy; it was never actually booted. Removed the
capability drop and verified for real this time: applied just
00-postgres.yaml alone into a disposable namespace, waited for the pod
to go Ready, read its logs ("database system is ready to accept
connections"), then deleted that namespace.
97 lines
3.3 KiB
YAML
97 lines
3.3 KiB
YAML
# Demo-only Postgres: a bare Deployment+Service+Secret, not the Zalando
|
|
# postgres-operator path (DatabaseSpec.postgresClusterRef, DESIGN.md §8).
|
|
# Bring-your-own DSN is the simpler of the two paths to stand up from
|
|
# nothing (ROADMAP.md Stage 1's own note), which is all this needs to be.
|
|
#
|
|
# emptyDir, one replica, a password sitting in a plaintext Secret below --
|
|
# none of that is how you'd run Postgres for real. It exists only so
|
|
# 01-server.yaml has something to talk to. Throw the whole demo namespace
|
|
# away when you're done; nothing here is meant to survive that.
|
|
apiVersion: v1
|
|
kind: Secret
|
|
metadata:
|
|
name: terdut-operator-demo-postgres
|
|
type: Opaque
|
|
stringData:
|
|
password: demo-not-a-real-password
|
|
---
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: terdut-operator-demo-postgres
|
|
labels:
|
|
app: terdut-operator-demo-postgres
|
|
spec:
|
|
replicas: 1
|
|
# Recreate, not RollingUpdate: emptyDir means a new pod starts with an
|
|
# empty database anyway, and two Postgres pods would never agree on one
|
|
# emptyDir each.
|
|
strategy:
|
|
type: Recreate
|
|
selector:
|
|
matchLabels:
|
|
app: terdut-operator-demo-postgres
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: terdut-operator-demo-postgres
|
|
spec:
|
|
containers:
|
|
- name: postgres
|
|
image: postgres:17-alpine
|
|
# Partial, deliberately: the official image's entrypoint needs to
|
|
# start as root to chown/chmod the data directory before it drops
|
|
# privileges itself (gosu, to the postgres user) -- forcing
|
|
# runAsNonRoot would just refuse to start the container, and
|
|
# dropping all capabilities (an earlier version of this file did)
|
|
# takes CAP_CHOWN/CAP_FOWNER away from that same root user, which
|
|
# is a different way of breaking the identical startup step:
|
|
# confirmed the hard way, as `chmod: /var/run/postgresql:
|
|
# Operation not permitted` in a real pod's logs, not caught by
|
|
# `kubectl apply --dry-run=server` -- that only checks admission
|
|
# policy, never whether the container actually boots. A
|
|
# "restricted" PodSecurity namespace warns on the remaining gap
|
|
# (no runAsNonRoot) rather than blocking, which is an acceptable
|
|
# tradeoff for Postgres that exists only to be thrown away with
|
|
# the rest of this demo.
|
|
securityContext:
|
|
allowPrivilegeEscalation: false
|
|
seccompProfile:
|
|
type: RuntimeDefault
|
|
ports:
|
|
- name: postgres
|
|
containerPort: 5432
|
|
env:
|
|
- name: POSTGRES_USER
|
|
value: terdut
|
|
- name: POSTGRES_DB
|
|
value: terdut
|
|
- name: POSTGRES_PASSWORD
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: terdut-operator-demo-postgres
|
|
key: password
|
|
volumeMounts:
|
|
- name: data
|
|
mountPath: /var/lib/postgresql/data
|
|
subPath: pgdata
|
|
readinessProbe:
|
|
exec:
|
|
command: ["pg_isready", "-U", "terdut"]
|
|
initialDelaySeconds: 5
|
|
volumes:
|
|
- name: data
|
|
emptyDir: {}
|
|
---
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: terdut-operator-demo-postgres
|
|
spec:
|
|
selector:
|
|
app: terdut-operator-demo-postgres
|
|
ports:
|
|
- name: postgres
|
|
port: 5432
|
|
targetPort: postgres
|