deploying-postgres-k8s
Deploys PostgreSQL on Kubernetes using the CloudNativePG operator with automated failover. Use when setting up PostgreSQL for production workloads, high availability, or local K8s development. Covers operator installation, cluster creation, connection secrets, and backup configuration. NOT when using managed Postgres (Neon, RDS, Cloud SQL) or simple Docker containers.
Best use case
deploying-postgres-k8s is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Deploys PostgreSQL on Kubernetes using the CloudNativePG operator with automated failover. Use when setting up PostgreSQL for production workloads, high availability, or local K8s development. Covers operator installation, cluster creation, connection secrets, and backup configuration. NOT when using managed Postgres (Neon, RDS, Cloud SQL) or simple Docker containers.
Teams using deploying-postgres-k8s should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/deploying-postgres-k8s/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How deploying-postgres-k8s Compares
| Feature / Agent | deploying-postgres-k8s | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Deploys PostgreSQL on Kubernetes using the CloudNativePG operator with automated failover. Use when setting up PostgreSQL for production workloads, high availability, or local K8s development. Covers operator installation, cluster creation, connection secrets, and backup configuration. NOT when using managed Postgres (Neon, RDS, Cloud SQL) or simple Docker containers.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# Deploying PostgreSQL on Kubernetes
Deploy production-ready PostgreSQL clusters using CloudNativePG operator (v1.28+) with automated failover.
## Quick Start
```bash
# 1. Install CloudNativePG operator
kubectl apply --server-side -f \
https://raw.githubusercontent.com/cloudnative-pg/cloudnative-pg/release-1.28/releases/cnpg-1.28.0.yaml
# 2. Wait for operator
kubectl rollout status deployment -n cnpg-system cnpg-controller-manager
# 3. Deploy PostgreSQL cluster
kubectl apply -f - <<EOF
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: pg-cluster
spec:
instances: 3
storage:
size: 10Gi
EOF
# 4. Wait for cluster
kubectl wait cluster/pg-cluster --for=condition=Ready --timeout=300s
```
## Operator Installation
### Direct Manifest (Recommended)
```bash
kubectl apply --server-side -f \
https://raw.githubusercontent.com/cloudnative-pg/cloudnative-pg/release-1.28/releases/cnpg-1.28.0.yaml
# Verify
kubectl rollout status deployment -n cnpg-system cnpg-controller-manager
kubectl get pods -n cnpg-system
```
### Helm Installation
```bash
helm repo add cnpg https://cloudnative-pg.github.io/charts
helm repo update
helm upgrade --install cnpg \
--namespace cnpg-system \
--create-namespace \
cnpg/cloudnative-pg
```
### Namespace-Scoped (Enhanced Security)
```bash
helm upgrade --install cnpg \
--namespace cnpg-system \
--create-namespace \
--set config.clusterWide=false \
cnpg/cloudnative-pg
```
## Cluster Configurations
### Development (Single Instance)
```yaml
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: pg-dev
spec:
instances: 1
imageName: ghcr.io/cloudnative-pg/postgresql:17.2
primaryUpdateStrategy: unsupervised
storage:
size: 5Gi
postgresql:
parameters:
max_connections: "100"
shared_buffers: "256MB"
```
### Production (HA with 3 Replicas)
```yaml
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: pg-production
spec:
instances: 3
imageName: ghcr.io/cloudnative-pg/postgresql:17.2
primaryUpdateStrategy: unsupervised
storage:
storageClass: standard
size: 100Gi
resources:
requests:
memory: "2Gi"
cpu: "1"
limits:
memory: "4Gi"
cpu: "2"
postgresql:
parameters:
max_connections: "200"
shared_buffers: "1GB"
effective_cache_size: "3GB"
maintenance_work_mem: "256MB"
checkpoint_completion_target: "0.9"
wal_buffers: "16MB"
default_statistics_target: "100"
random_page_cost: "1.1"
effective_io_concurrency: "200"
affinity:
podAntiAffinityType: required # Spread across nodes
monitoring:
enablePodMonitor: true
```
### With Bootstrap Database
```yaml
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: pg-cluster
spec:
instances: 3
storage:
size: 10Gi
bootstrap:
initdb:
database: learnflow
owner: app_user
secret:
name: app-user-secret
```
Create the secret first:
```bash
kubectl create secret generic app-user-secret \
--from-literal=username=app_user \
--from-literal=password=$(openssl rand -hex 16)
```
## Connection Secrets
CloudNativePG automatically creates connection secrets:
| Secret | Contents |
|--------|----------|
| `pg-cluster-app` | App credentials (recommended) |
| `pg-cluster-superuser` | Superuser credentials |
### Get Connection String
```bash
# Get app credentials
kubectl get secret pg-cluster-app -o jsonpath='{.data.uri}' | base64 -d
# Get superuser credentials (admin tasks only)
kubectl get secret pg-cluster-superuser -o jsonpath='{.data.uri}' | base64 -d
```
### Use in Deployment
```yaml
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: pg-cluster-app
key: uri
```
## Service Endpoints
| Service | Port | Use |
|---------|------|-----|
| `pg-cluster-rw` | 5432 | Read-Write (primary) |
| `pg-cluster-ro` | 5432 | Read-Only (replicas) |
| `pg-cluster-r` | 5432 | Any instance |
### Connect from Another Namespace
```yaml
env:
- name: DATABASE_URL
value: "postgresql://app_user:password@pg-cluster-rw.default.svc.cluster.local:5432/learnflow"
```
## Database Operations
### Connect with psql
```bash
# Using kubectl cnpg plugin (recommended)
kubectl cnpg psql pg-cluster -- -c "SELECT version();"
# Or directly
kubectl exec -it pg-cluster-1 -- psql -U postgres
```
### Create Database and User
```bash
kubectl exec -it pg-cluster-1 -- psql -U postgres <<EOF
CREATE DATABASE myapp;
CREATE USER myapp_user WITH ENCRYPTED PASSWORD 'secure_password';
GRANT ALL PRIVILEGES ON DATABASE myapp TO myapp_user;
\c myapp
GRANT ALL ON SCHEMA public TO myapp_user;
EOF
```
### Run Migrations
```bash
# From local machine
kubectl port-forward svc/pg-cluster-rw 5432:5432 &
DATABASE_URL="postgresql://postgres:password@localhost:5432/learnflow" alembic upgrade head
```
## Backup Configuration
### Backup to S3
```yaml
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: pg-cluster
spec:
instances: 3
storage:
size: 10Gi
backup:
barmanObjectStore:
destinationPath: "s3://my-bucket/pg-backups"
s3Credentials:
accessKeyId:
name: s3-creds
key: ACCESS_KEY_ID
secretAccessKey:
name: s3-creds
key: SECRET_ACCESS_KEY
wal:
compression: gzip
data:
compression: gzip
retentionPolicy: "30d"
```
### Schedule Backups
```yaml
apiVersion: postgresql.cnpg.io/v1
kind: ScheduledBackup
metadata:
name: pg-backup-daily
spec:
schedule: "0 0 * * *" # Daily at midnight
backupOwnerReference: cluster
cluster:
name: pg-cluster
```
## Monitoring
### Check Cluster Status
```bash
kubectl get cluster pg-cluster
kubectl describe cluster pg-cluster
kubectl get pods -l cnpg.io/cluster=pg-cluster
```
### View Logs
```bash
kubectl logs pg-cluster-1 -f
kubectl logs -l cnpg.io/cluster=pg-cluster --all-containers
```
### Prometheus Metrics
With `enablePodMonitor: true`, metrics available at:
- `cnpg_backends_total` - Active connections
- `cnpg_pg_replication_lag_seconds` - Replica lag
- `cnpg_pg_database_size_bytes` - Database size
## Troubleshooting
### Cluster Not Ready
```bash
kubectl describe cluster pg-cluster
kubectl get pods -l cnpg.io/cluster=pg-cluster
kubectl logs pg-cluster-1
```
### Connection Issues
```bash
# Test connectivity
kubectl run pg-client --rm -it --restart=Never \
--image=postgres:17 -- \
psql "postgresql://app_user:password@pg-cluster-rw:5432/learnflow" -c "SELECT 1;"
```
### Common Issues
| Error | Cause | Fix |
|-------|-------|-----|
| PVC pending | No storage class | Add `storageClass` to spec |
| Connection refused | Wrong service name | Use `cluster-rw` for writes |
| Auth failed | Wrong credentials | Check secret `cluster-app` |
| Replica lag high | Heavy writes | Scale up, increase resources |
## Cleanup
```bash
# Delete cluster (keeps PVCs by default)
kubectl delete cluster pg-cluster
# Delete PVCs (data loss!)
kubectl delete pvc -l cnpg.io/cluster=pg-cluster
# Remove operator
kubectl delete -f \
https://raw.githubusercontent.com/cloudnative-pg/cloudnative-pg/release-1.28/releases/cnpg-1.28.0.yaml
```
## Verification
Run: `python scripts/verify.py`
## Related Skills
- `operating-k8s-local` - Local Minikube cluster setup
- `scaffolding-fastapi-dapr` - FastAPI services with SQLModel
- `deploying-kafka-k8s` - Kafka for event-driven architectureRelated Skills
scaffolding-oracle-to-postgres-migration-test-project
Scaffolds an xUnit integration test project for validating Oracle-to-PostgreSQL database migration behavior in .NET solutions. Creates the test project, transaction-rollback base class, and seed data manager. Use when setting up test infrastructure before writing migration integration tests, or when a test project is needed for Oracle-to-PostgreSQL validation.
reviewing-oracle-to-postgres-migration
Identifies Oracle-to-PostgreSQL migration risks by cross-referencing code against known behavioral differences (empty strings, refcursors, type coercion, sorting, timestamps, concurrent transactions, etc.). Use when planning a database migration, reviewing migration artifacts, or validating that integration tests cover Oracle/PostgreSQL differences.
postgresql-code-review
PostgreSQL-specific code review assistant focusing on PostgreSQL best practices, anti-patterns, and unique quality standards. Covers JSONB operations, array usage, custom types, schema design, function optimization, and PostgreSQL-exclusive security features like Row Level Security (RLS).
planning-oracle-to-postgres-migration-integration-testing
Creates an integration testing plan for .NET data access artifacts during Oracle-to-PostgreSQL database migrations. Analyzes a single project to identify repositories, DAOs, and service layers that interact with the database, then produces a structured testing plan. Use when planning integration test coverage for a migrated project, identifying which data access methods need tests, or preparing for Oracle-to-PostgreSQL migration validation.
migrating-oracle-to-postgres-stored-procedures
Migrates Oracle PL/SQL stored procedures to PostgreSQL PL/pgSQL. Translates Oracle-specific syntax, preserves method signatures and type-anchored parameters, leverages orafce where appropriate, and applies COLLATE "C" for Oracle-compatible text sorting. Use when converting Oracle stored procedures or functions to PostgreSQL equivalents during a database migration.
creating-oracle-to-postgres-migration-integration-tests
Creates integration test cases for .NET data access artifacts during Oracle-to-PostgreSQL database migrations. Generates DB-agnostic xUnit tests with deterministic seed data that validate behavior consistency across both database systems. Use when creating integration tests for a migrated project, generating test coverage for data access layers, or writing Oracle-to-PostgreSQL migration validation tests.
creating-oracle-to-postgres-migration-bug-report
Creates structured bug reports for defects found during Oracle-to-PostgreSQL migration. Use when documenting behavioral differences between Oracle and PostgreSQL as actionable bug reports with severity, root cause, and remediation steps.
creating-oracle-to-postgres-master-migration-plan
Discovers all projects in a .NET solution, classifies each for Oracle-to-PostgreSQL migration eligibility, and produces a persistent master migration plan. Use when starting a multi-project Oracle-to-PostgreSQL migration, creating a migration inventory, or assessing which .NET projects contain Oracle dependencies.
electric-postgres-security
Pre-deploy security checklist for Postgres with Electric. Checks REPLICATION role, SELECT grants, CREATE on database, table ownership, REPLICA IDENTITY FULL on all synced tables, publication management (auto vs manual with ELECTRIC_MANUAL_TABLE_PUBLISHING), connection pooler exclusion for DATABASE_URL (use direct connection), and ELECTRIC_POOLED_DATABASE_URL for pooled queries. Load before deploying Electric to production or when diagnosing Postgres permission errors.
deploying-to-production
Automate creating a GitHub repository and deploying a web project to Vercel. Use when the user asks to deploy a website/app to production, publish a project, or set up GitHub + Vercel deployment.
postgresql-optimization
PostgreSQL database optimization workflow for query tuning, indexing strategies, performance analysis, and production database management.
postgres-best-practices
Postgres performance optimization and best practices from Supabase. Use this skill when writing, reviewing, or optimizing Postgres queries, schema designs, or database configurations.