betelgeusebytes/k8s/postgres/pg.yaml

217 lines
6.0 KiB
YAML

# k8s/postgres/pg-init-sql-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: pg-init-sql
namespace: db
data:
00_extensions.sql: |
\connect gitea
CREATE EXTENSION IF NOT EXISTS postgis;
CREATE EXTENSION IF NOT EXISTS postgis_topology;
CREATE EXTENSION IF NOT EXISTS fuzzystrmatch;
CREATE EXTENSION IF NOT EXISTS pg_trgm;
CREATE EXTENSION IF NOT EXISTS hstore;
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS citext;
CREATE EXTENSION IF NOT EXISTS unaccent;
CREATE EXTENSION IF NOT EXISTS pgcrypto;
DO $$ BEGIN
CREATE EXTENSION IF NOT EXISTS plpython3u;
EXCEPTION WHEN undefined_file THEN
RAISE NOTICE 'plpython3u not available in this image';
END $$;
01_tune.sql: |
ALTER SYSTEM SET shared_buffers = '1GB';
ALTER SYSTEM SET work_mem = '32MB';
ALTER SYSTEM SET maintenance_work_mem = '512MB';
ALTER SYSTEM SET max_connections = 200;
SELECT pg_reload_conf();
---
# k8s/postgres/pg-conf.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: pg-conf
namespace: db
data:
pg_hba.conf: |
# Local connections
local all all trust
host all all 127.0.0.1/32 trust
host all all ::1/128 trust
# TLS-only access from ANY external IP (harden as needed)
hostssl all all 0.0.0.0/0 md5
hostssl all all ::/0 md5
---
# k8s/postgres/pg-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: pg18-secret
namespace: db
type: Opaque
stringData:
POSTGRES_PASSWORD: "pa$$word"
---
# k8s/postgres/pg-certificate.yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: pg-tls
namespace: db
spec:
secretName: pg-tls
dnsNames:
- pg.betelgeusebytes.io
issuerRef:
kind: ClusterIssuer
name: letsencrypt-prod
---
# k8s/postgres/postgres-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: postgres
namespace: db
spec:
selector:
app: postgres
ports:
- name: postgres
port: 5432
targetPort: 5432
---
apiVersion: v1
kind: Service
metadata:
name: postgres-hl
namespace: db
spec:
clusterIP: None
selector:
app: postgres
ports:
- name: postgres
port: 5432
targetPort: 5432
---
# k8s/postgres/postgres.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
namespace: db
spec:
serviceName: postgres-hl
replicas: 1
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
securityContext:
runAsUser: 999
runAsGroup: 999
fsGroup: 999
fsGroupChangePolicy: "Always"
initContainers:
- name: install-certs
image: busybox:1.36
command:
- sh
- -c
- |
cp /in/tls.crt /out/server.crt
cp /in/tls.key /out/server.key
chown 999:999 /out/* || true
chmod 600 /out/server.key
securityContext:
runAsUser: 0
volumeMounts:
- { name: pg-tls, mountPath: /in, readOnly: true }
- { name: pg-certs, mountPath: /out }
containers:
- name: postgres
image: axxs/postgres:18-postgis-vector
imagePullPolicy: IfNotPresent
args:
- -c
- ssl=on
- -c
- ssl_cert_file=/certs/server.crt
- -c
- ssl_key_file=/certs/server.key
- -c
- hba_file=/etc/postgresql-custom/pg_hba.conf
env:
- name: POSTGRES_USER
value: "app"
- name: POSTGRES_DB
value: "gitea"
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: pg18-secret
key: POSTGRES_PASSWORD
- name: TZ
value: "Europe/Paris"
ports:
- name: postgres
containerPort: 5432
volumeMounts:
- { name: data, mountPath: /var/lib/postgresql } # PG18 expects parent, creates /var/lib/postgresql/18/main
- { name: init, mountPath: /docker-entrypoint-initdb.d, readOnly: true }
- { name: pg-certs, mountPath: /certs }
- { name: pg-conf, mountPath: /etc/postgresql-custom }
readinessProbe:
exec: { command: ["sh","-c","pg_isready -U \"$POSTGRES_USER\" -d \"$POSTGRES_DB\" -h 127.0.0.1"] }
initialDelaySeconds: 5
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 6
livenessProbe:
exec: { command: ["sh","-c","pg_isready -U \"$POSTGRES_USER\" -d \"$POSTGRES_DB\" -h 127.0.0.1"] }
initialDelaySeconds: 20
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 6
resources:
requests: { cpu: "250m", memory: "512Mi" }
limits: { cpu: "1", memory: "2Gi" }
volumes:
- name: init
configMap:
name: pg-init-sql
defaultMode: 0444
- name: pg-tls
secret:
secretName: pg-tls
- name: pg-certs
emptyDir: {}
- name: pg-conf
configMap:
name: pg-conf
defaultMode: 0444
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: local-ssd-hetzner
resources:
requests:
storage: 80Gi
# kubectl -n ingress-nginx create configmap tcp-services \
# --from-literal="5432=db/postgres:5432" \
# -o yaml --dry-run=client | kubectl apply -f -
# kubectl -n ingress-nginx patch deploy ingress-nginx-controller \
# --type='json' -p='[
# {"op":"add","path":"/spec/template/spec/containers/0/args/-","value":"--tcp-services-configmap=$(POD_NAMESPACE)/tcp-services"}
# ]'
# # controller must listen on hostPort:5432 (we already patched earlier)