Quick Start¶
This tutorial walks you through creating a PostgreSQL database with a user in 5 minutes.
Prerequisites¶
- DB Provision Operator installed in your cluster
- A PostgreSQL server accessible from your cluster
No PostgreSQL server?
You can deploy a test PostgreSQL server:
Step 1: Create Admin Credentials¶
First, create a Secret with the credentials to connect to your PostgreSQL server:
apiVersion: v1
kind: Secret
metadata:
name: postgres-admin-credentials
namespace: default
type: Opaque
stringData:
username: postgres
password: your-admin-password
Apply:
kubectl apply -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
name: postgres-admin-credentials
namespace: default
type: Opaque
stringData:
username: postgres
password: postgres
EOF
Step 2: Create a DatabaseInstance¶
A DatabaseInstance represents the connection to your database server:
apiVersion: dbops.dbprovision.io/v1alpha1
kind: DatabaseInstance
metadata:
name: postgres-primary
namespace: default
spec:
engine: postgres
connection:
host: postgresql.default.svc.cluster.local # Adjust to your server
port: 5432
database: postgres
secretRef:
name: postgres-admin-credentials
healthCheck:
enabled: true
intervalSeconds: 30
Apply and verify:
Wait for the instance to become Ready:
NAME ENGINE PHASE HOST PORT AGE
postgres-primary postgres Ready postgresql.default.svc.cluster.local 5432 30s
Step 3: Create a User¶
Create a user first — the operator auto-generates a password and stores it in a Kubernetes Secret:
apiVersion: dbops.dbprovision.io/v1alpha1
kind: DatabaseUser
metadata:
name: myapp-user
namespace: default
spec:
instanceRef:
name: postgres-primary
username: myapp_user
passwordSecret:
generate: true
length: 24
secretName: myapp-user-credentials
Apply:
kubectl apply -f user.yaml
# Check the generated credentials
kubectl get secret myapp-user-credentials -o jsonpath='{.data.password}' | base64 -d
Step 4: Create a Database with an Owner¶
Now create a database and assign the user as its owner. The owner field references the username of a DatabaseUser (or any existing role):
apiVersion: dbops.dbprovision.io/v1alpha1
kind: Database
metadata:
name: myapp-database
namespace: default
spec:
instanceRef:
name: postgres-primary
name: myapp
owner: myapp_user
deletionPolicy: Retain
Apply:
Why create the user first?
The owner field references a database role that must already exist. By creating the DatabaseUser before the Database, the role is ready when the database is created.
Step 5: Customize Credentials with Secret Templates (Optional)¶
The DatabaseUser's secret provides raw credentials by default. Use secretTemplate to format them as a connection string your application can consume directly:
# Patch the user to add a DATABASE_URL key
spec:
passwordSecret:
secretTemplate:
data:
DATABASE_URL: "postgresql://{{ urlEncode .Username }}:{{ urlEncode .Password }}@{{ .Host }}:{{ .Port }}/myapp?sslmode=prefer"
See the DatabaseUser docs for the full list of template variables and functions.
Step 6: Grant Permissions¶
Grant the user access to the database:
apiVersion: dbops.dbprovision.io/v1alpha1
kind: DatabaseGrant
metadata:
name: myapp-user-grants
namespace: default
spec:
userRef:
name: myapp-user
databaseRef:
name: myapp-database
postgres:
grants:
- database: myapp
schema: public
tables: ["*"]
privileges: [SELECT, INSERT, UPDATE, DELETE]
Apply:
Verify Everything¶
Check all resources:
Expected output:
NAME ENGINE PHASE AGE
databaseinstance.dbops.dbprovision.io/postgres-primary postgres Ready 5m
NAME ENGINE PHASE DATABASE AGE
database.dbops.dbprovision.io/myapp-database postgres Ready myapp 4m
NAME ENGINE PHASE USERNAME AGE
databaseuser.dbops.dbprovision.io/myapp-user postgres Ready myapp_user 3m
NAME PHASE AGE
databasegrant.dbops.dbprovision.io/myapp-user-grants Ready 2m
Connect to the Database¶
Use the generated credentials to connect:
# Get credentials
export PGHOST=postgresql.default.svc.cluster.local
export PGPORT=5432
export PGDATABASE=myapp
export PGUSER=myapp_user
export PGPASSWORD=$(kubectl get secret myapp-user-credentials -o jsonpath='{.data.password}' | base64 -d)
# Connect (from a pod with psql)
kubectl run -it --rm psql --image=postgres:16 --restart=Never -- psql
Credentials lifecycle
The DatabaseUser's Secret is owned by the operator. If the Secret is deleted, the operator automatically generates a new password and recreates it. See Password Rotation for scheduled rotation.
Clean Up¶
To remove all resources:
kubectl delete databasegrant myapp-user-grants
kubectl delete databaseuser myapp-user
kubectl delete database myapp-database
kubectl delete databaseinstance postgres-primary
kubectl delete secret postgres-admin-credentials myapp-user-credentials
Next Steps¶
- User Guide - Deep dive into each CRD
- Examples - More complex scenarios
- Engine Guides - PostgreSQL, MySQL, MariaDB specifics