Skip to content

Releases: hops-ops/psql-stack

v0.8.0

14 May 19:12

Choose a tag to compare

What's changed in v0.8.0

  • feat(psqlcluster): add targetNamespace field (by @patrickleet)

    Decouples the PSQLCluster XR's control-plane namespace from the composed
    CNPG Cluster's data-plane namespace. Defaults to the XR's own ns (the
    common case); override when the XR lives in the platform default ns but
    the data plane needs to land elsewhere — e.g. embedded in AuthStack so
    Zitadel pods can env-var-mount the app Secret without cross-namespace
    mirroring.

    Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com

See full diff: v0.7.0...v0.8.0

v0.7.0

08 May 22:46

Choose a tag to compare

What's changed in v0.7.0

  • feat: pivot psql-stack to EKS Auto Mode defaults (#10) (by @patrickleet)

    • feat: optional NodePool for dedicated psql workloads

    Add opt-in Karpenter NodePool composed resource. When
    spec.nodePool.enabled: true, renders a NodePool targeting arm64 spot on
    r7g.large/r7g.xlarge/m7g.large/m7g.xlarge (memory-optimized Graviton),
    tainted with psql=true:NoSchedule and labeled workload-type: psql.

    StackGres (operator/restapi/jobs) and Atlas get nodeSelector + tolerations
    injected into their Helm values when the NodePool is enabled. Usages pin
    both releases to be drained before the NodePool is deleted. Adds
    provider-kubernetes to upbound.yaml for the NodePool Object wrapper.

    Implements [[tasks/psql-stack-vela-simplyblock]]

    Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com

    • feat: StorageClass + ExternalSecrets composed resources
    • storageClass (default on): creates a gp3 StorageClass backed by the
      EKS Auto Mode EBS CSI driver (ebs.csi.eks.amazonaws.com). The legacy
      gp2 in-tree provisioner does not work on EKS Auto Mode.
    • externalSecrets (opt-in): for each entry in externalSecrets.secrets[],
      composes a kubernetes.m.crossplane.io/Object wrapping an ESO
      ExternalSecret that syncs an AWS Secrets Manager value (published via
      hops secrets sync aws) into a Kubernetes Secret on the target cluster.
      Requires a ClusterSecretStore (e.g. from SecretStack); defaults to
      clusterSecretStoreName: hops-aws-secrets-manager.

    Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com

    • fix: default StorageClass name to 'psql' (per-stack naming)

    Mirrors observe stack where StorageClasses are named loki/prometheus/tempo
    per-component. Keeps the name specific to the stack so it doesn't collide
    with cluster-provided defaults.

    Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com

    • feat: externalSecrets.connections[] composes password + config → URL

    Replaces the generic externalSecrets.secrets[] passthrough with a
    Postgres-specific connections[] API. The user publishes just a password
    via hops secrets (single JSON key, default 'password'); the stack
    combines it with non-secret host/port/database/username/sslmode/namespace
    and emits a K8s Secret with a ready-to-use 'url' key plus discrete fields.

    Downstream consumers reference whichever key they need:
    AtlasSchema.devURLFrom → url
    SGCluster credentials.users.superuser.password → password
    applications → url (or discrete fields)

    Breaking change to the (locally-only) externalSecrets API; redeploy with
    the new shape.

    Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com

    • refactor: drop externalSecrets from PSQLStack

    Without managing the SGCluster, every field in externalSecrets.connections[]
    (host/port/database/namespace) is passthrough — no abstraction. Users write
    ExternalSecret CRs directly (or as a Crossplane Object wrapper in local/)
    against the ClusterSecretStore provisioned by SecretStack.

    PSQLStack now = platform only: StackGres + Atlas operators + NodePool +
    StorageClass. If we later add an instances[] that composes SGClusters,
    ESO wiring can come back for free since the stack will then know
    host/port/database/namespace without the user restating them.

    Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com

    • feat: swap StackGres operator for CloudNativePG (phase 1 of CNPG pivot)

    Rewrites PSQLStack schema to remove stackgresOperator, add cnpg and
    scaleToZeroPlugin blocks. Default namespace: cnpg-system. CNPG 1.29
    (chart 0.27.1) replaces StackGres 1.18 as the operator. Atlas operator
    renumbered 210 → 220 to make room for the scale-to-zero plugin
    install (added in a later phase).

    Storage (psql StorageClass on EBS gp3) and NodePool blocks preserved
    unchanged — phases 2 and 3 will rewrite them for the three-profile
    (mayastor / lvm / ebs) storage model and the branches/primary NodePool
    split with hugepages + nvme-tcp pre-configured.

    Implements [[tasks/psql-stack-cnpg]]

    Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com

    • feat: three-profile storage layer — mayastor + lvm + ebs (phase 2)

    Replaces the single storageClass block with a storage block exposing three
    independent profiles:

    • storage.mayastor (replicated NVMe-oF via OpenEBS Mayastor) — enterprise
      default for primary serving clusters; CoW + HA across N replicas. Default
      enabled=false until phase 3 lands the NodePool with hugepages + nvme-tcp.
    • storage.lvm (single-node CoW via OpenEBS LVM LocalPV) — branches and dev
      clusters. Default enabled=false until phase 3 lands NodePool LVM volume
      groups.
    • storage.ebs (EBS gp3 via EKS Auto Mode CSI) — durable fallback, no CoW;
      always-on default.

    Render templates:

    • 120-storageclass.yaml.gotmpl deleted (was the single 'psql' SC)
    • 160-openebs-lvm.yaml.gotmpl: Helm release for OpenEBS LVM LocalPV
    • 165-openebs-mayastor.yaml.gotmpl: Helm release for OpenEBS Mayastor
    • 170-storageclass-mayastor.yaml.gotmpl: psql-mayastor SC + VolumeSnapshotClass
    • 175-storageclass-lvm.yaml.gotmpl: psql-lvm SC + VolumeSnapshotClass
    • 180-storageclass-ebs.yaml.gotmpl: psql-ebs SC (renamed from 'psql')

    state-init defaults the three profile blocks; state-status observes the new
    resource keys. Mayastor + LVM Helm releases + their StorageClasses are gated
    on storage.{mayastor,lvm}.enabled — only EBS materializes by default until
    phase 3 unblocks the others.

    standard.yaml example patched to drop the removed storageClass and
    stackgresOperator fields (full example rewrite is phase 5).

    Implements [[tasks/psql-stack-cnpg]]

    Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com

    • feat: split NodePool into branches + primary sub-pools (phase 3)

    Replaces the single Karpenter NodePool with two sub-pools targeting NVMe
    arm64 instance-store nodes (i4g.2xlarge / i4g.4xlarge / im4gn.2xlarge):

    • nodePool.branches: spot — for ephemeral PSQLBranch workloads. Spot is
      acceptable since branches are reproducible.
    • nodePool.primary: on-demand — for PSQLCluster primaries and operators
      (CNPG, Atlas, scale-to-zero). Spot preemption would lose a Mayastor
      replica, so on-demand is the right default for serving workloads.

    Each sub-pool has its own labels (sub-pool=branches | sub-pool=primary)
    and matching taints so workloads can target one specifically. Operators
    ride the primary sub-pool via nodeSelector + tolerations injected from
    state-init.

    Render templates:

    • 150-nodepool.yaml.gotmpl deleted
    • 140-nodepool-branches.yaml.gotmpl: spot sub-pool
    • 145-nodepool-primary.yaml.gotmpl: on-demand sub-pool + Usage protection
      for CNPG/Atlas Releases against premature NodePool deletion.

    state-init defaults the new sub-pool blocks; state-status observes both.
    nodePool.enabled stays default-false — existing claims unchanged.

    Out of scope for this commit: node-side prep for Mayastor + LVM
    (hugepages, nvme-tcp module, LVM volume group on instance-store NVMe).
    That's phase 3b (a separate concern that needs careful image / runtime
    choices) — without it, mayastor.enabled and lvm.enabled won't bind PVCs.

    Implements [[tasks/psql-stack-cnpg]]

    Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com

    • feat: install cnpg-i-scale-to-zero plugin (phase 4)

    Inlines the upstream cnpg-i-scale-to-zero v0.1.7 release manifest as 9
    Crossplane Kubernetes Objects:

    • ServiceAccount cnpg-scale-to-zero-plugin
    • ClusterRole cnpg-scale-to-zero-sidecar-role + ClusterRoleBinding
    • Secret scale-to-zero-config (sidecar image reference, paired to plugin
      version via stringData — k8s base64-encodes on apply)
    • Self-signed cert-manager Issuer + 2 Certificates (server + client) for
      the gRPC TLS material the CNPG operator uses to reach the plugin
    • Service scale-to-zero (cnpg.io/pluginPort=9090, cnpg.io/pluginName
      annotations)
    • Deployment scale-to-zero (the plugin gRPC server)

    Plugin and sidecar images both pin to spec.scaleToZeroPlugin.version
    (default v0.1.7). Secret is renamed scale-to-zero-config (was
    scale-to-zero-config-c2c2544fbk in upstream — drops the kustomize
    hash suffix since we emit the resources as separate Objects).

    All resources are gated on spec.scaleToZeroPlugin.enabled (default true
    — the plugin is zero-cost when no PSQLCluster opts in).

    Source URL is annotated for renovate tracking:
    source: https://github.com/xataio/cnpg-i-scale-to-zero/releases/download/$VER/manifest.yaml
    renovate: datasource=github-releases depName=xataio/cnpg-i-scale-to-zero

    Prereq: cert-manager must be installed (provided by the dns-stack in
    hops-ops). Without it, the Issuer + Certificate resources won't reconcile
    and the plugin Deployment won't have its TLS volumes available.

    When PSQLClusters opt into scale-to-zero, they add:
    metadata.annotations:
    xata.io/scale-to-zero-enabled: "true"
    xata.io/scale-to-zero-inactivity-minutes: "10"
    spec.plugins:
    - name: cnpg-i-scale-to-zero.xata.io

    Implements [[tasks/psql-stack-cnpg]]

    Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com

    • docs/test: refresh README, examples, and render tests for CNPG pivot (phase 5)
    • README rewritten: CNPG architecture, three-stage journey (EBS-only →
      +LVM CoW → +Mayastor HA), full Spec Reference table, prereq notes
      (cert-manager via cert-manager-stack; node prep deferred to phase 3b)
    • examples refreshed:
      • minimal: just clusterName, EBS-only baseline
      • standard: full production posture (NodePool sub-pools, Mayastor +
        LVM + EBS, S2Z plugin, Atlas)
      • local: dev cluster with LVM CoW only (no Mayastor since replication
        needs >1 node, no NodePool, default Helm provider config)
    • tests/test-render/main.k: rewritten a...
Read more

v0.6.0

28 Apr 00:49

Choose a tag to compare

What's changed in v0.6.0

  • feat(deps): update crossplane-contrib/function-auto-ready docker tag to v0.6.4 (#9) (by @renovate[bot])

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

See full diff: v0.5.0...v0.6.0

v0.5.0

24 Mar 05:20

Choose a tag to compare

What's changed in v0.5.0

  • feat(deps): update crossplane-contrib/function-auto-ready docker tag to v0.6.3 (#8) (by @renovate[bot])

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

See full diff: v0.4.0...v0.5.0

v0.4.0

17 Mar 17:13

Choose a tag to compare

What's changed in v0.4.0

  • chore(deps): update unbounded-tech/workflows-crossplane action to v2.18.0 (#5) (by @renovate[bot])

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

  • chore(deps): update unbounded-tech/workflows-crossplane action to v2.20.0 (#6) (by @renovate[bot])

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

  • feat(deps): update crossplane-contrib/function-auto-ready docker tag to v0.6.2 (#7) (by @renovate[bot])

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

See full diff: v0.3.0...v0.4.0

v0.3.0

09 Mar 19:13

Choose a tag to compare

What's changed in v0.3.0

  • chore(deps): update unbounded-tech/workflows-crossplane action to v2.16.0 (#2) (by @renovate[bot])

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

  • chore(deps): update unbounded-tech/workflows-crossplane action to v2.17.0 (#4) (by @renovate[bot])

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

  • feat: psql -> psql-stack, kind: PSQLStack, api: hops.ops.com.ai (by @patrickleet)

  • fix: test updates (by @patrickleet)

  • fix: test updates (by @patrickleet)

See full diff: v0.2.0...v0.3.0

v0.2.0

02 Mar 07:10

Choose a tag to compare

What's changed in v0.2.0

  • chore: readme (by @patrickleet)

  • feat(deps): update crossplane-contrib/function-auto-ready docker tag to v0.6.1 (#1) (by @renovate[bot])

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

See full diff: v0.1.0...v0.2.0

v0.1.0

25 Feb 20:20

Choose a tag to compare

What's changed in v0.1.0