PostgreSQL on k3s

Overview

Runs PostgreSQL as a cluster-internal stateful service managed by Argo CD. On a single VPS, one database instance is honest about the failure domain; replicas on the same node do not provide host-level availability.

Deployment Choice

  • CloudNativePG operator: recommended when backup/restore, declarative clusters, and future replication matter.
  • Bitnami PostgreSQL chart: smaller learning curve for a disposable or low-risk environment.
  • Managed PostgreSQL: recommended when data durability matters more than self-hosting cost.

For the GitOps template, use CloudNativePG and keep the database custom resource separate from the operator Application so CRDs sync first.

Minimum Configuration

apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: app-db
  namespace: data
spec:
  instances: 1
  storage:
    size: 20Gi
  resources:
    requests:
      cpu: 200m
      memory: 512Mi
    limits:
      memory: 2Gi

Applications connect to app-db-rw.data.svc.cluster.local:5432. Read credentials from the generated Secret; never expose PostgreSQL with a public LoadBalancer or Ingress.

Backup and Verification

Configure continuous WAL/object-store backup to S3-compatible storage outside the VPS, and regularly test restoration into a new cluster.

kubectl get cluster,pod,pvc -n data
kubectl cnpg status app-db -n data
kubectl exec -n data app-db-1 -- pg_isready

A successful backup job is not enough: recovery time and data correctness are verified only by a restore drill.