apiVersion: apps/v1 kind: StatefulSet metadata: name: {{ include "instance.fullname" . }}-pg labels: {{- include "instance.labels" . | nindent 4 }} spec: serviceName: {{ include "instance.fullname" . }}-pg replicas: 1 # When the StatefulSet is deleted (e.g. ArgoCD prunes the # Application after an instance is deleted from Tower), drop the # PVCs too. Without this, K8s preserves the PVC for "data safety" # — but in v3's model an instance delete IS a clean wipe, and # leaking the PVC means a same-named recreate mounts the old PG # data dir whose pg_authid carries the previous password. db-init # then fails password auth even though the new K8s Secret has the # correct hash. Setting Delete here prevents that whole class. persistentVolumeClaimRetentionPolicy: whenDeleted: Delete whenScaled: Retain selector: matchLabels: app.kubernetes.io/instance: {{ .Values.instance.code | quote }} odoosky.io/role: postgres template: metadata: labels: {{- include "instance.labels" . | nindent 8 }} odoosky.io/role: postgres spec: {{- with .Values.imageMirror.pullSecret }} # Air-gap support (B.10) — see odoo-deployment.yaml for the # full rationale. Same imageMirror.pullSecret is used for the # postgres image too so customers configure mirror auth once. imagePullSecrets: - name: {{ . }} {{- end }} containers: - name: postgres image: "{{ if .Values.imageMirror.registry }}{{ .Values.imageMirror.registry }}/{{ end }}{{ .Values.postgres.image }}:{{ .Values.postgres.tag }}" imagePullPolicy: IfNotPresent ports: - name: pg containerPort: 5432 envFrom: - secretRef: name: {{ include "instance.fullname" . }}-pg env: # PGDATA in a sub-dir so the mount-point itself isn't the # data dir — postgres refuses to init when `lost+found` # exists at the root of the volume. - name: PGDATA value: /var/lib/postgresql/data/pgdata volumeMounts: - name: pgdata mountPath: /var/lib/postgresql/data resources: {{- include "instance.resources" (dict "Values" .Values "role" "postgres") | nindent 12 }} readinessProbe: exec: command: ["sh", "-c", "pg_isready -U $POSTGRES_USER -d $POSTGRES_DB"] initialDelaySeconds: 10 periodSeconds: 5 livenessProbe: exec: command: ["sh", "-c", "pg_isready -U $POSTGRES_USER -d $POSTGRES_DB"] initialDelaySeconds: 30 periodSeconds: 15 volumeClaimTemplates: - metadata: name: pgdata spec: accessModes: [ReadWriteOnce] {{- if .Values.instance.storageClassName }} storageClassName: {{ .Values.instance.storageClassName | quote }} {{- end }} {{- if and .Values.instance.dataSource .Values.instance.dataSource.database .Values.instance.dataSource.database.snapshotName }} # Seed from VolumeSnapshot — Tower's VolumeClone path # (ADR 0003 phase 3+4). The snapshot is taken from the # source instance's `pgdata--pg-0` PVC. dataSource: apiGroup: snapshot.storage.k8s.io kind: VolumeSnapshot name: {{ .Values.instance.dataSource.database.snapshotName | quote }} {{- end }} resources: requests: storage: {{ include "instance.storage" (dict "Values" .Values "layer" "database") | quote }}