Skip to main content

Create a PostgreSQL service

As a Project administrator or developer, create a PostgreSQL service from a published plan with a Kubernetes manifest. Use the parameter reference to configure its database, replicas, backups, and connection pool. The console's creation sheet submits the same manifest; see Use the console.

Before you begin​

  • The admin or developer role in the Project. See Managed services.
  • The class, plan and connectivity class names. This page uses postgresql, postgresql-production and tenant-native; plan names differ between installations. See Classes and plans.
  • A plan whose allowedPlacementModes includes ProviderShared and whose allowedConnectivityClasses includes tenant-native.
  • The values of your plan's bounds (instances, storage, compute), which you get from your provider or from the sliders of the console's Size step.
  • Enough Project quota for the instances, storage and backups you request.

Throughout this page, replace my-project with your Project's backing namespace.

kubectl auth can-i create managedservices.services.kube-dc.com -n my-project

Create the service​

Save this manifest as orders-db.yaml:

apiVersion: services.kube-dc.com/v1alpha1
kind: ManagedService
metadata:
name: orders-db
namespace: my-project
spec:
classRef:
name: postgresql
planRef:
name: postgresql-production
# Set placement explicitly; the API default is TenantCluster, which the
# published plans do not allow.
placement:
mode: ProviderShared
connectivity:
classRef:
name: tenant-native
# Sizing. Each value must be within the plan's bounds; omit a field to take
# the plan default. These change later only through operations.
topology:
instances: 3
compute:
cpu: "1"
memory: 2Gi
storage:
size: 20Gi
# Engine parameters of the postgresql class.
parameters:
database: orders
owner: orders
readonlyRole: true
# Backups need backup.enabled: true on the plan.
backup:
enabled: true
postgresql:
parameters:
work_mem: 8MB
deletionPolicy: Retain
deletionProtection: true

Check the manifest with a server-side dry run, then apply it:

kubectl apply --dry-run=server -f orders-db.yaml
kubectl apply -f orders-db.yaml
kubectl get managedservice orders-db -n my-project -w

The dry run checks the API schema and admission policies only. The class schema, plan bounds and capacity are checked after the object is created, and the result appears in status. Wait until PHASE is Ready and READY is True, then confirm the result is current as described in Read the status.

Record the service UID. Bindings, operations and credential policies need it:

kubectl get managedservice orders-db -n my-project -o jsonpath='{.metadata.uid}{"\n"}'

Service fields​

FieldRequiredDescription
spec.classRef.nameYesThe class, postgresql. Cannot change
spec.planRef.nameYesThe plan, for example postgresql-production. Cannot change
spec.placement.modeYesSet ProviderShared, which runs the service inside your Project. Your plan's allowedPlacementModes must include it. If you omit the field, the API default TenantCluster is used and the published plans refuse it. Cannot change
spec.connectivity.classRef.nameYesThe connectivity class, tenant-native. Your plan's allowedConnectivityClasses must include it. Cannot change
spec.engineVersionNoThe PostgreSQL major version, for example "17". It must equal the plan's engineVersion, so the simplest choice is to omit it. Changes only through a MinorUpgrade or MajorUpgrade operation
spec.topology.instancesNoOne primary plus replicas, within the plan's topology bounds. Default: the plan's topology.defaultInstances. Changes only through a Scale operation
spec.compute.cpu, spec.compute.memoryNoRequests and limits per instance, as quantity strings (500m, 1Gi). Only within the plan's capacity.computeBounds; a plan without bounds accepts only its defaults. Change through a Resize operation
spec.storage.sizeNoThe data volume per instance, at most the plan's capacity.maxStorage. Default: the plan's capacity.storage. Grows through an ExpandStorage operation; never shrinks
spec.storage.classNoThe plan default or one of its capacity.allowedStorageClasses. Cannot change; existing volumes never move to another class
spec.parametersNoEngine parameters of the class. See Parameter reference
spec.maintenance.applyImmediatelyNoApply declarative changes now instead of waiting for the plan's maintenance window. It never bypasses approval
spec.retryNoRequest one new attempt for a failed declarative change, naming its attempt ID from status
spec.deletionPolicyNoWhat deleting the ManagedService does to the engine and its data. Default Retain. Must be one of the plan's allowedDeletionPolicies
spec.deletionProtectionNoWhile true, deleting the ManagedService is refused. Set it to false in a separate update before you delete
spec.restoreFromPlatform-generatedThe platform sets this field for a catalog-backed RestoreToNew operation. See Backups and restore

The sizing fields used to live under spec.parameters. Manifests that still carry parameters.cpu, parameters.memory, parameters.instances, parameters.storage or parameters.version are refused at admission with a message naming the field to use instead.

The deletion policies behave as follows:

deletionPolicyEffect of deleting the ManagedService
RetainManagement stops. The engine, its volumes and its data stay in the Project and can keep using capacity and quota
SnapshotAndDeleteThe platform takes a final backup and then removes the engine and its volumes. This needs working backups. If the engine no longer exists, so that no final backup can be taken, the data volumes are retained instead of deleted
DeleteThe engine and its volumes are removed and the data is lost. The service must also carry the annotation services.kube-dc.com/confirm-delete set to the service name, or deletion waits with reason DeletionConfirmationNeeded

For a service in the Project's own namespace, none of these settings apply when the whole Project is deleted. See Delete a service or a Project and Status and deletion.

Parameter reference​

These are the engine parameters of the postgresql class, under spec.parameters. Unknown parameters are refused. The last column gives each parameter's mutation class; see Change a service after creation.

ParameterType and formatDefaultChanges after creation
databaseString matching ^[a-z_][a-z0-9_]*$, up to 63 charactersappCreateOnly
ownerString matching ^[a-z_][a-z0-9_]*$, up to 63 charactersappCreateOnly
readonlyRoleBooleantrueCreateOnly
postgresql.parametersMap of allow-listed settings; values are stringsManaged defaultsOnlineDesired, or the UpdateParameters operation
backup.enabledBooleantrueOnlineDesired
backup.scheduleFive-field cron expression in UTCThe plan's backup.scheduleOnlineDesired
backup.retentionDaysIntegerThe plan's backup.retentionDaysOnlineDesired
backup.storeObject: endpoint, bucket, secretName, secretUIDNoneCreateOnly
pooler.enabledBooleanfalseOnlineDesired
pooler.instancesInteger, 1 to 31OnlineDesired
pooler.modesession or transactiontransactionOnlineDesired
pooler.readOnlyBoolean: also pool the replicas as the pooled-read-only endpointfalseOnlineDesired
breakGlass.enableSuperuserAccessBooleanfalseOnlineDesired
expose.typeinternal, loadbalancer or gatewayinternalOnlineDesired

Details:

  • database and owner: the application database created at bootstrap and the login that owns it. The owner's credential is the owner binding role.
  • readonlyRole: creates a readonly login with the pg_read_all_data privilege, delivered through the readonly binding role.
  • postgresql.parameters: settings that reload online are work_mem, maintenance_work_mem, effective_cache_size, log_min_duration_statement, timezone, statement_timeout, idle_in_transaction_session_timeout and archive_timeout. Settings that cause a rolling restart of the instances are shared_buffers, max_connections, max_worker_processes, max_wal_senders, max_replication_slots, huge_pages, max_prepared_transactions and max_locks_per_transaction. Give every value as a string with exact units. timezone accepts IANA names and UTC.
  • backup.*: backups require the plan's backup.enabled: true. The schedule and retention must be within the plan's backup bounds. Omit a field to inherit the plan value. Lowering retentionDays can permanently remove old recovery points.
  • backup.store: a backup destination of your own. It requires the plan's backup.allowedCustomEndpoints and an existing Opaque Secret in the Project with AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY. Keep that Secret for as long as you may need to recover. The destination cannot change later.
  • pooler.*: runs PgBouncer in front of the primary and publishes a pooled endpoint. Each pooler replica adds 100m CPU and 128Mi memory to the capacity the service uses. transaction mode multiplexes more clients. Use session mode for anything that relies on session state, such as prepared statements, advisory locks, LISTEN/NOTIFY or temporary tables. Turning the pooler off is refused while a binding uses the pooled endpoint.
  • breakGlass.enableSuperuserAccess: emergency postgres superuser access. It requires the plan's credentials.allowBreakGlass and is off by default.
  • expose.type: keep the default internal unless you need access from outside the Project. gateway requires the plan field exposure.gateway; see External access. loadbalancer requires the plan's exposure.allowPublicLoadBalancer and a public IPv4 address from your organization's quota.

Change a service after creation​

OnlineDesired parameters​

Edit the manifest and apply the complete ManagedService again, keeping every other field unchanged, or change the value in the console's Settings tab and use Review & apply:

kubectl apply -f orders-db.yaml

Settings that need a restart roll through the instances one at a time. Applications should reconnect and retry. Declarative changes wait for the plan's maintenance window unless the plan applies them immediately or you set spec.maintenance.applyImmediately: true.

For PostgreSQL settings, a completed UpdateParameters operation takes precedence over the manifest. After such an operation, editing or removing that key in spec.parameters.postgresql.parameters does not change its effective value; use another UpdateParameters operation. Its resetParameters list resets the named settings to their managed defaults. A setting cannot be set and reset in the same operation.

Sizing, version and CreateOnly parameters​

An edit to one of these fields on the ManagedService is refused when you apply it:

parameters instances are CreateOnly, OperationOnly or ReplaceOrMigrate for class postgresql and cannot be edited on the ManagedService; OperationOnly values change through a ServiceOperation

If an edit gets past admission, the service reports Reconciled=False with reason ParameterMutationRejected, and the last accepted configuration stays in force. Revert the edit.

Change them with a ServiceOperation, or with the matching action in the console:

FieldOperation typeOperation parametersPlan requirement
spec.topology.instancesScaleinstancesWithin topology bounds
spec.compute.cpu, spec.compute.memoryResizecpu, memory (either one may be omitted to keep its current value)capacity.computeBounds and capacity.allocationProtocol: v1
spec.storage.sizeExpandStoragesize, larger than the current sizeAt most capacity.maxStorage, and the service's status.engineDetails.storageExpansion must be "true". Refused on storage that cannot expand
spec.engineVersionMinorUpgrade, MajorUpgradeimageName from the plan's allowedImagesSee Upgrades
spec.parameters.postgresql.parametersUpdateParametersparameters, resetParametersNone beyond the allow-list

Every operation type must also be in the plan's operations.allowed. This example scales orders-db to five instances:

apiVersion: services.kube-dc.com/v1alpha1
kind: ServiceOperation
metadata:
name: orders-db-scale-5
namespace: my-project
spec:
serviceRef:
name: orders-db
# The service's metadata.uid.
serviceUID: REPLACE_WITH_SERVICE_UID
type: Scale
idempotencyKey: orders-db-scale-5
parameters:
instances: 5
execution:
window: Immediate
kubectl apply -f orders-db-scale-5.yaml
kubectl get serviceoperation orders-db-scale-5 -n my-project -w

An operation moves through Pending, Preflight, AwaitingApproval, Accepted and Running to one of Succeeded, Failed, Rejected or Cancelled. Only Succeeded means the change was made. Read status.reason, status.message and status.result for details.

  • The operation spec is immutable. To retry a submission whose result you did not see, apply the same manifest again with the same name and idempotencyKey. For a new, deliberate change, use a new name and a new key.
  • execution.window: NextPlanWindow waits for the plan's maintenance window. Immediate does not skip approval.
  • To withdraw an operation that has not started running, set the annotation services.kube-dc.com/cancel: "true" on it.
  • An operation record can be deleted only after it reaches a final phase. Deleting a record does not stop work that has already started.

After an operation succeeds, the new value appears in status.effectiveConfiguration and status.resolvedSpec, not in the manifest you applied. Do not copy it back: the manifest keeps stating what you created, and the operations record what changed.

Read the status​

Confirm that the service reports Ready=True for its current generation before connecting applications. See Check service status for phases, conditions, effective configuration, and observation freshness. After a change, use Is the result current? to verify that it was applied.

Common refusals​

See Common refusals for admission errors, plan restrictions, capacity failures, and operation conflicts. After the service is ready, connect your application.