Kubernetes operator
Database connections
How the operator finds and authenticates to your database.
Database connection
The operator supports two connection modes: a single connection URL from a Secret, or structured parameters with separate fields for host, port, database, and credentials.
Connection URL (single Secret)
Create a Secret containing your PostgreSQL connection string. Read the value interactively so a password-bearing URL does not enter shell history or the process list:
umask 077
read -rsp 'Database URL: ' DATABASE_URL && printf '\n'
printf '%s' "$DATABASE_URL" > db-url
unset DATABASE_URL
kubectl create secret generic mydb-credentials \
--from-file=DATABASE_URL=db-url
rm db-url
In production, prefer a secret manager or CSI driver over creating the Secret by hand.
Reference it in the policy:
connection:
secretRef:
name: mydb-credentials
secretKey: DATABASE_URL # optional, defaults to DATABASE_URL
When the Secret's resourceVersion changes (e.g. credential rotation), the operator automatically reconnects with updated credentials.
Structured parameters
Use connection.params to build the connection from individual fields. Each field is either a literal value or a reference to a key in a Kubernetes Secret. This integrates natively with PostgreSQL operators that create credential Secrets (Zalando, CloudNativePG, CrunchyData PGO).
Zalando postgres-operator — credentials in a Secret, host/port/database as literals:
connection:
params:
host: my-cluster-postgres # K8s service name (namespace-relative)
port: 5432
dbname: mydb
sslMode: require
usernameSecret:
name: postgres.my-cluster-postgres.credentials.postgresql.acid.zalan.do
key: username
passwordSecret:
name: postgres.my-cluster-postgres.credentials.postgresql.acid.zalan.do
key: password
CloudNativePG / CrunchyData PGO — all fields from the operator-created Secret:
connection:
params:
hostSecret:
name: cluster-example-app
key: host
dbnameSecret:
name: cluster-example-app
key: dbname
usernameSecret:
name: cluster-example-app
key: user
passwordSecret:
name: cluster-example-app
key: password
Each connection field supports a literal value and a *Secret variant:
| Field | Literal | Secret | Required |
|---|---|---|---|
host / hostSecret | Hostname string | SecretKeySelector | Yes (exactly one) |
port / portSecret | Integer (default 5432) | SecretKeySelector | No |
dbname / dbnameSecret | Database name | SecretKeySelector | Yes (exactly one) |
username / usernameSecret | Username string | SecretKeySelector | Yes (exactly one) |
password / passwordSecret | Password string | SecretKeySelector | Yes unless auth is set |
auth | Provider-backed auth config (type, scope, impersonateServiceAccount) | n/a | No |
setRole | Role to SET ROLE to on every operator connection | n/a | No |
sslMode / sslModeSecret | SSL mode string | SecretKeySelector | No |
Valid sslMode values: disable, allow, prefer, require, verify-ca, verify-full.
For required fields, exactly one of the literal or Secret variant must be set. For optional fields, at most one may be set. When a Secret referenced by params changes, the operator detects the resourceVersion change and reconnects automatically.
GKE Workload Identity for Cloud SQL IAM
Use connection.params.auth.type: gcp_workload_identity when the operator pod runs on GKE with Workload Identity and connects to Cloud SQL using IAM database authentication. The operator fetches a short-lived OAuth token from the GKE metadata server and uses it as the PostgreSQL password. password and passwordSecret must be omitted. If sslMode is omitted, the operator uses require.
connection:
params:
host: 10.0.0.5
port: 5432
dbname: discovery
username: pgroles-operator@my-project.iam
auth:
type: gcp_workload_identity
# Optional: impersonate a different GCP service account.
impersonateServiceAccount: target-sa@other-project.iam.gserviceaccount.com
# Optional: defaults to https://www.googleapis.com/auth/sqlservice.login
scope: https://www.googleapis.com/auth/sqlservice.login
The Kubernetes ServiceAccount used by the operator must be annotated for Workload Identity — set operator.serviceAccount.annotations in the chart — and the Google service account must have Cloud SQL IAM database login permissions for the target instance.
An IAM identity usually has too few privileges to manage roles itself. Use connection.params.setRole to authenticate as the low-privilege IAM identity and switch to a privileged parent role on every connection:
connection:
params:
username: pgroles-operator@my-project.iam
setRole: pgroles_admin
auth:
type: gcp_workload_identity
The IAM identity must be a member of the target role. setRole accepts ^[A-Za-z_][A-Za-z0-9_$-]*$ — deliberately excluding @ and ., so an IAM principal name such as sa@project.iam is rejected. Name the PostgreSQL group role to switch into, not the identity you authenticate as. See executor privileges for what that role needs.
Host resolution
The host must be reachable from the operator pod. For an in-cluster database in a different namespace, use the fully qualified service name (e.g. my-postgres.my-namespace.svc). For a database outside the cluster, use the external hostname or IP directly (e.g. db.example.com or 10.0.1.50).