217 lines
6.0 KiB
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) |