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:

FieldLiteralSecretRequired
host / hostSecretHostname stringSecretKeySelectorYes (exactly one)
port / portSecretInteger (default 5432)SecretKeySelectorNo
dbname / dbnameSecretDatabase nameSecretKeySelectorYes (exactly one)
username / usernameSecretUsername stringSecretKeySelectorYes (exactly one)
password / passwordSecretPassword stringSecretKeySelectorYes unless auth is set
authProvider-backed auth config (type, scope, impersonateServiceAccount)n/aNo
setRoleRole to SET ROLE to on every operator connectionn/aNo
sslMode / sslModeSecretSSL mode stringSecretKeySelectorNo

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).