examples/demo: fix two real bugs this exact demo just hit live
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.
This commit is contained in:
@@ -10,7 +10,7 @@
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Secret
|
kind: Secret
|
||||||
metadata:
|
metadata:
|
||||||
name: terdut-demo-postgres
|
name: terdut-operator-demo-postgres
|
||||||
type: Opaque
|
type: Opaque
|
||||||
stringData:
|
stringData:
|
||||||
password: demo-not-a-real-password
|
password: demo-not-a-real-password
|
||||||
@@ -18,9 +18,9 @@ stringData:
|
|||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: terdut-demo-postgres
|
name: terdut-operator-demo-postgres
|
||||||
labels:
|
labels:
|
||||||
app: terdut-demo-postgres
|
app: terdut-operator-demo-postgres
|
||||||
spec:
|
spec:
|
||||||
replicas: 1
|
replicas: 1
|
||||||
# Recreate, not RollingUpdate: emptyDir means a new pod starts with an
|
# Recreate, not RollingUpdate: emptyDir means a new pod starts with an
|
||||||
@@ -30,27 +30,32 @@ spec:
|
|||||||
type: Recreate
|
type: Recreate
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
app: terdut-demo-postgres
|
app: terdut-operator-demo-postgres
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
app: terdut-demo-postgres
|
app: terdut-operator-demo-postgres
|
||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: postgres
|
- name: postgres
|
||||||
image: postgres:17-alpine
|
image: postgres:17-alpine
|
||||||
# Partial, deliberately: the official image's entrypoint needs to
|
# Partial, deliberately: the official image's entrypoint needs to
|
||||||
# start as root to chown the data directory before it drops
|
# start as root to chown/chmod the data directory before it drops
|
||||||
# privileges itself (gosu, to the postgres user) -- forcing
|
# privileges itself (gosu, to the postgres user) -- forcing
|
||||||
# runAsNonRoot here would just refuse to start the container. A
|
# runAsNonRoot would just refuse to start the container, and
|
||||||
# "restricted" PodSecurity namespace warns on that gap rather
|
# dropping all capabilities (an earlier version of this file did)
|
||||||
# than blocking (confirmed server-side against this operator's
|
# takes CAP_CHOWN/CAP_FOWNER away from that same root user, which
|
||||||
# own dev cluster), which is an acceptable tradeoff for Postgres
|
# is a different way of breaking the identical startup step:
|
||||||
# that exists only to be thrown away with the rest of this demo.
|
# 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:
|
securityContext:
|
||||||
allowPrivilegeEscalation: false
|
allowPrivilegeEscalation: false
|
||||||
capabilities:
|
|
||||||
drop: ["ALL"]
|
|
||||||
seccompProfile:
|
seccompProfile:
|
||||||
type: RuntimeDefault
|
type: RuntimeDefault
|
||||||
ports:
|
ports:
|
||||||
@@ -64,7 +69,7 @@ spec:
|
|||||||
- name: POSTGRES_PASSWORD
|
- name: POSTGRES_PASSWORD
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: terdut-demo-postgres
|
name: terdut-operator-demo-postgres
|
||||||
key: password
|
key: password
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: data
|
- name: data
|
||||||
@@ -81,10 +86,10 @@ spec:
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
name: terdut-demo-postgres
|
name: terdut-operator-demo-postgres
|
||||||
spec:
|
spec:
|
||||||
selector:
|
selector:
|
||||||
app: terdut-demo-postgres
|
app: terdut-operator-demo-postgres
|
||||||
ports:
|
ports:
|
||||||
- name: postgres
|
- name: postgres
|
||||||
port: 5432
|
port: 5432
|
||||||
|
|||||||
@@ -10,19 +10,19 @@
|
|||||||
apiVersion: terdut.ryuvia.com/v1alpha1
|
apiVersion: terdut.ryuvia.com/v1alpha1
|
||||||
kind: TerdutServer
|
kind: TerdutServer
|
||||||
metadata:
|
metadata:
|
||||||
name: terdut-demo
|
name: terdut-operator-demo
|
||||||
spec:
|
spec:
|
||||||
image:
|
image:
|
||||||
repository: git.ryuvia.com/niklas/terdut-server
|
repository: git.ryuvia.com/niklas/terdut-server
|
||||||
tag: v0.33.2
|
tag: v0.33.2
|
||||||
replicas: 1
|
replicas: 1
|
||||||
networking:
|
networking:
|
||||||
hostname: terdut-demo.example
|
hostname: terdut-operator-demo.example
|
||||||
servicePort: 8080
|
servicePort: 8080
|
||||||
database:
|
database:
|
||||||
dsn: "postgres://terdut@terdut-demo-postgres:5432/terdut?sslmode=disable"
|
dsn: "postgres://terdut@terdut-operator-demo-postgres:5432/terdut?sslmode=disable"
|
||||||
passwordSecretRef:
|
passwordSecretRef:
|
||||||
name: terdut-demo-postgres
|
name: terdut-operator-demo-postgres
|
||||||
key: password
|
key: password
|
||||||
sweeper:
|
sweeper:
|
||||||
staleAfter: 6h
|
staleAfter: 6h
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ kind: TerdutTeam
|
|||||||
metadata:
|
metadata:
|
||||||
name: terdutteam-platform
|
name: terdutteam-platform
|
||||||
spec:
|
spec:
|
||||||
# serverRef.namespace omitted: both this and terdut-demo (01-server.yaml)
|
# serverRef.namespace omitted: both this and terdut-operator-demo (01-server.yaml)
|
||||||
# live in whatever namespace you apply this directory into, which is the
|
# live in whatever namespace you apply this directory into, which is the
|
||||||
# common case and needs no allowedTeams consent on the TerdutServer side
|
# common case and needs no allowedTeams consent on the TerdutServer side
|
||||||
# (DESIGN.md §4.1, §4.6).
|
# (DESIGN.md §4.1, §4.6).
|
||||||
serverRef:
|
serverRef:
|
||||||
name: terdut-demo
|
name: terdut-operator-demo
|
||||||
displayName: Platform
|
displayName: Platform
|
||||||
# No oidc block: this demo is password-login only (01-server.yaml).
|
# No oidc block: this demo is password-login only (01-server.yaml).
|
||||||
|
|||||||
@@ -4,5 +4,5 @@ metadata:
|
|||||||
name: terdutteam-payments
|
name: terdutteam-payments
|
||||||
spec:
|
spec:
|
||||||
serverRef:
|
serverRef:
|
||||||
name: terdut-demo
|
name: terdut-operator-demo
|
||||||
displayName: Payments
|
displayName: Payments
|
||||||
|
|||||||
+15
-4
@@ -18,6 +18,17 @@ directory. Throw the whole namespace away when you're done.
|
|||||||
throwaway resources in. A `kind` cluster is the easy choice.
|
throwaway resources in. A `kind` cluster is the easy choice.
|
||||||
- `kubectl`, `jq`, `curl` on your path.
|
- `kubectl`, `jq`, `curl` on your path.
|
||||||
|
|
||||||
|
**Apply this into a namespace of its own.** Every object name in this
|
||||||
|
directory is prefixed `terdut-operator-demo` specifically so applying it
|
||||||
|
by mistake into some other namespace that already has unrelated objects
|
||||||
|
doesn't collide with them -- but that only helps if this directory's own
|
||||||
|
objects don't collide with *each other* across two applies. Applying it
|
||||||
|
twice into two different namespaces is fine; applying it a second time
|
||||||
|
into a namespace that already has something else named `terdut-demo` (a
|
||||||
|
real install from following `terdut-operator`'s own repo along, say) is
|
||||||
|
exactly the mistake this prefix exists to avoid, and it only works if you
|
||||||
|
don't override these names yourself.
|
||||||
|
|
||||||
## Apply it
|
## Apply it
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
@@ -40,10 +51,10 @@ kubectl get terdutservers,terdutteams,terdutescalationrules,terdutdeadmanswitche
|
|||||||
|
|
||||||
The operator's own Deployment template now carries a `wait-for-postgres`
|
The operator's own Deployment template now carries a `wait-for-postgres`
|
||||||
init container (same fix as `charts/terdut-server`'s chart as of v0.33.2),
|
init container (same fix as `charts/terdut-server`'s chart as of v0.33.2),
|
||||||
so `terdut-demo`'s pod should come up clean even against this brand-new
|
so `terdut-operator-demo`'s pod should come up clean even against this brand-new
|
||||||
Postgres doing its very first boot — no `CrashLoopBackOff` expected here.
|
Postgres doing its very first boot — no `CrashLoopBackOff` expected here.
|
||||||
|
|
||||||
Once `terdut-demo`'s own `Ready` condition is `True`, everything downstream
|
Once `terdut-operator-demo`'s own `Ready` condition is `True`, everything downstream
|
||||||
of it should settle within a reconcile interval or two.
|
of it should settle within a reconcile interval or two.
|
||||||
|
|
||||||
## See the web UI
|
## See the web UI
|
||||||
@@ -53,7 +64,7 @@ The operator doesn't create any external exposure yet
|
|||||||
— `spec.networking.hostname` is accepted but nothing acts on it), so:
|
— `spec.networking.hostname` is accepted but nothing acts on it), so:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
kubectl -n terdut-operator-demo port-forward svc/terdut-demo 8080:8080
|
kubectl -n terdut-operator-demo port-forward svc/terdut-operator-demo 8080:8080
|
||||||
```
|
```
|
||||||
|
|
||||||
and open http://localhost:8080.
|
and open http://localhost:8080.
|
||||||
@@ -72,7 +83,7 @@ kubectl get deploy -A -l control-plane=controller-manager
|
|||||||
|
|
||||||
# The Secret holding the operator's own admin token for this TerdutServer
|
# The Secret holding the operator's own admin token for this TerdutServer
|
||||||
# (cross-namespace from terdut-operator-demo, per DESIGN.md §7):
|
# (cross-namespace from terdut-operator-demo, per DESIGN.md §7):
|
||||||
secretname=$(kubectl -n terdut-operator-demo get terdutserver terdut-demo \
|
secretname=$(kubectl -n terdut-operator-demo get terdutserver terdut-operator-demo \
|
||||||
-o jsonpath='{.status.credentialsSecretRef.name}')
|
-o jsonpath='{.status.credentialsSecretRef.name}')
|
||||||
token=$(kubectl -n <operator-namespace-from-above> get secret "$secretname" \
|
token=$(kubectl -n <operator-namespace-from-above> get secret "$secretname" \
|
||||||
-o jsonpath='{.data.token}' | base64 -d)
|
-o jsonpath='{.data.token}' | base64 -d)
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
#
|
#
|
||||||
# Prerequisites: kubectl context pointed at the demo namespace, jq, curl,
|
# Prerequisites: kubectl context pointed at the demo namespace, jq, curl,
|
||||||
# and (in another terminal) a running:
|
# and (in another terminal) a running:
|
||||||
# kubectl port-forward svc/terdut-demo 8080:8080
|
# kubectl port-forward svc/terdut-operator-demo 8080:8080
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
NAMESPACE="${NAMESPACE:-}"
|
NAMESPACE="${NAMESPACE:-}"
|
||||||
|
|||||||
Reference in New Issue
Block a user