cluster-cnpg-integrated

Manifests #

01-cnpg.yaml #

# CloudNativePG (CNPG) Postgres used as the Temporal datastore.
#
# Prerequisite: the CNPG operator must be installed in the cluster, e.g.:
#   kubectl apply --server-side -f \
#     https://raw.githubusercontent.com/cloudnative-pg/cloudnative-pg/release-1.24/releases/cnpg-1.24.0.yaml
#
# Two things Temporal needs that aren't obvious:
#
#   1. Two databases. The operator only runs schema setup (setup-schema); it
#      does NOT create databases. initdb creates "temporal"; the postInitSQL
#      below creates the separate "temporal_visibility" database.
#
#   2. Enough connections. Each Temporal service pod opens a connection pool to
#      BOTH stores, which blows past Postgres's default max_connections of 100
#      and surfaces as "remaining connection slots are reserved for ... SUPERUSER"
#      (SQLSTATE 53300). Raise it to 200.
#
# CNPG generates a Secret "temporal-pg-app" (keys: username, password) for the
# "temporal" app user, referenced by the TemporalCluster. Do NOT redeclare the
# "temporal" role under spec.managed.roles without a passwordSecret — CNPG would
# reset it to PASSWORD NULL / NOLOGIN and break password authentication.
apiVersion: v1
kind: Namespace
metadata:
  name: temporal
---
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: temporal-pg
  namespace: temporal
spec:
  instances: 1
  storage:
    size: 5Gi
  postgresql:
    parameters:
      max_connections: "200"
  bootstrap:
    initdb:
      database: temporal
      owner: temporal
      postInitSQL:
        - CREATE DATABASE temporal_visibility OWNER temporal;

02-temporalcluster.yaml #

# A TemporalCluster backed by the CNPG Postgres from 01-cnpg.yaml.
#
# The operator reconciler pings the datastore from its OWN pod (in the
# temporal-system namespace), so the persistence host must be a
# namespace-qualified FQDN. A bare "temporal-pg-rw" would resolve in the
# operator's namespace and fail with PersistenceUnreachable.
apiVersion: temporal.bmor10.com/v1alpha1
kind: TemporalCluster
metadata:
  name: temporal
  namespace: temporal
spec:
  version: "1.31.1"
  numHistoryShards: 512
  persistence:
    defaultStore:
      sql:
        pluginName: postgres12
        host: temporal-pg-rw.temporal.svc.cluster.local
        port: 5432
        database: temporal
        user: temporal
        passwordSecretRef:
          name: temporal-pg-app
          key: password
    visibilityStore:
      sql:
        pluginName: postgres12
        host: temporal-pg-rw.temporal.svc.cluster.local
        port: 5432
        database: temporal_visibility
        user: temporal
        passwordSecretRef:
          name: temporal-pg-app
          key: password
  # Web UI. Reach it with `kubectl -n temporal port-forward svc/temporal-ui
  # 8080:8080`, or uncomment the ingress block to expose it.
  ui:
    enabled: true
    # ingress:
    #   enabled: true
    #   ingressClassName: nginx
    #   host: temporal.example.com
    #   tlsSecretName: temporal-example-com-tls
    #   annotations:
    #     cert-manager.io/cluster-issuer: letsencrypt-prod
---
# Declarative namespace registered on the cluster once it is Ready.
apiVersion: temporal.bmor10.com/v1alpha1
kind: TemporalNamespace
metadata:
  name: default
  namespace: temporal
spec:
  clusterRef:
    name: temporal
  retentionPeriod: "72h"
  description: "Default namespace"
  allowDeletion: true