apiVersion: v1 kind: ConfigMap metadata: name: postgres-config namespace: gravl-staging data: POSTGRES_DB: gravl POSTGRES_USER: gravl_user --- apiVersion: v1 kind: Secret metadata: name: postgres-secret namespace: gravl-staging type: Opaque stringData: POSTGRES_PASSWORD: "gravl_staging_password_12345" --- apiVersion: apps/v1 kind: StatefulSet metadata: name: postgres namespace: gravl-staging spec: serviceName: postgres replicas: 1 selector: matchLabels: app: postgres template: metadata: labels: app: postgres spec: containers: - name: postgres image: postgres:16-alpine ports: - name: postgres containerPort: 5432 envFrom: - configMapRef: name: postgres-config - secretRef: name: postgres-secret volumeMounts: - name: postgres-storage mountPath: /var/lib/postgresql/data subPath: postgres - name: init-script mountPath: /docker-entrypoint-initdb.d livenessProbe: exec: command: - /bin/sh - -c - pg_isready -U gravl_user initialDelaySeconds: 30 periodSeconds: 10 readinessProbe: exec: command: - /bin/sh - -c - pg_isready -U gravl_user initialDelaySeconds: 5 periodSeconds: 10 resources: requests: memory: "256Mi" cpu: "100m" limits: memory: "512Mi" cpu: "500m" volumes: - name: init-script configMap: name: postgres-init defaultMode: 0755 volumeClaimTemplates: - metadata: name: postgres-storage spec: accessModes: [ "ReadWriteOnce" ] resources: requests: storage: 5Gi --- apiVersion: v1 kind: ConfigMap metadata: name: postgres-init namespace: gravl-staging data: init.sql: | CREATE TABLE IF NOT EXISTS users ( id SERIAL PRIMARY KEY, username VARCHAR(100) UNIQUE NOT NULL, email VARCHAR(100) UNIQUE NOT NULL, password_hash VARCHAR(255) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE IF NOT EXISTS workouts ( id SERIAL PRIMARY KEY, user_id INTEGER REFERENCES users(id) ON DELETE CASCADE, name VARCHAR(255) NOT NULL, description TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE IF NOT EXISTS exercises ( id SERIAL PRIMARY KEY, workout_id INTEGER REFERENCES workouts(id) ON DELETE CASCADE, name VARCHAR(255) NOT NULL, sets INTEGER, reps INTEGER, weight DECIMAL(10, 2), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE IF NOT EXISTS workout_logs ( id SERIAL PRIMARY KEY, user_id INTEGER REFERENCES users(id) ON DELETE CASCADE, workout_id INTEGER REFERENCES workouts(id), logged_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, duration_minutes INTEGER, notes TEXT ); --- apiVersion: v1 kind: Service metadata: name: postgres namespace: gravl-staging spec: clusterIP: None selector: app: postgres ports: - name: postgres port: 5432 targetPort: 5432