Postgres operator creates and manages PostgreSQL clusters running in Kubernetes
Go to file
IO ANALYTICA 29168ca0bc
Fix operatorconfigurations CRD: NamespacedName must render as type string (#3145)
Upgrading to v2.0.0 fails at the CRD apply step. The apiserver rejects the
OperatorConfiguration CRD:

  CustomResourceDefinition "operatorconfigurations.acid.zalan.do" is invalid:
  ...oauth_token_secret_name.default: Invalid value: "string": in body must
  be of type object

Root cause: these CRDs are generated by controller-gen from the Go types.
spec.NamespacedName is a struct {Namespace, Name}, so controller-gen emits an
object schema for every NamespacedName field. But NamespacedName has custom
MarshalJSON/UnmarshalJSON that (de)serialize it as a plain JSON string
("namespace/name"). The generated object schema therefore never matched how
the operator actually reads and writes these fields (it did in 1.15.x, where
they were type: string).

For oauth_token_secret_name this is a hard failure: it also carries
`// +kubebuilder:default=postgres-operator`, and a scalar string default on an
object-typed property is rejected by the apiserver, blocking the whole
1.15.x -> 2.0.0 upgrade before the operator Deployment is touched.

Fix at the source by annotating the NamespacedName type with
`// +kubebuilder:validation:Type=string` and regenerating the CRDs. This makes
controller-gen emit `type: string` for all NamespacedName fields
(oauth_token_secret_name, infrastructure_roles_secret_name,
pod_environment_configmap, and the nested infrastructure role secretname),
matching their runtime serialization and restoring 1.15.x behaviour. A
field-level Type override cannot be used here: it conflicts with the
struct-derived schema ("object vs string in allOf") and fails generation.

Regenerated manifests/operatorconfiguration.crd.yaml and its two synced
copies (pkg/apis/... embed source and charts/.../crds). Verified with a
server-side dry-run apply: the unpatched CRD is rejected, the regenerated CRD
is accepted.

Fixes #3143
2026-07-28 16:02:59 +02:00
.github bump to v2.0 (#3134) 2026-07-27 23:50:17 +02:00
charts Fix operatorconfigurations CRD: NamespacedName must render as type string (#3145) 2026-07-28 16:02:59 +02:00
cmd Add abitility to set QPS and Burst limits for api client (#2667) 2024-12-23 08:53:27 +01:00
docker update docker build commands in Makefiles to use buildx (#3137) 2026-07-23 16:24:23 +02:00
docs bump to v2.0 (#3134) 2026-07-27 23:50:17 +02:00
e2e bump to v2.0 (#3134) 2026-07-27 23:50:17 +02:00
hack adjust makefile and scripts to also run on macos (#3130) 2026-07-15 11:24:20 +02:00
logical-backup Remove references to registry.opensource.zalan.do (#3092) 2026-05-08 09:16:10 +02:00
manifests Fix operatorconfigurations CRD: NamespacedName must render as type string (#3145) 2026-07-28 16:02:59 +02:00
mocks Support EBS gp2 to gp3 migration on sync for below 1tb volumes (#1242) 2020-12-11 15:52:32 +01:00
pkg Fix operatorconfigurations CRD: NamespacedName must render as type string (#3145) 2026-07-28 16:02:59 +02:00
pooler build multi-arch pooler image (#3077) 2026-04-28 13:34:36 +02:00
ui bump to v2.0 (#3134) 2026-07-27 23:50:17 +02:00
.flake8 Implement runner for e2e tests (#548) 2019-06-05 17:07:27 +02:00
.gitignore drop kubectl-pg plugin (#3107) 2026-06-12 10:42:37 +02:00
.golangci.yml add .golangci.yml (#422) 2018-11-27 12:00:15 +01:00
.zappr.yaml Min 2 zalando approvers. (#1338) 2021-01-29 11:12:08 +01:00
CODEOWNERS add Mikkel (#3002) 2025-12-03 11:00:59 +01:00
CONTRIBUTING.md Update docs for v1.2 (#609) 2019-07-11 17:19:27 +02:00
LICENSE auto-generate configuration CRD (#3102) 2026-06-22 10:44:46 +02:00
MAINTAINERS add Mikkel (#3002) 2025-12-03 11:00:59 +01:00
Makefile update docker build commands in Makefiles to use buildx (#3137) 2026-07-23 16:24:23 +02:00
README.md bump to v2.0 (#3134) 2026-07-27 23:50:17 +02:00
SECURITY.md docs(general): Adding Security.md (#88) 2017-09-04 14:33:30 +02:00
build-ci.sh Modernize code generation (#3003) 2026-01-09 14:22:10 +01:00
delivery.yaml Remove references to registry.opensource.zalan.do (#3092) 2026-05-08 09:16:10 +02:00
go.mod Bump golang.org/x/crypto from 0.51.0 to 0.52.0 (#3127) 2026-07-21 09:38:14 +02:00
go.sum Bump golang.org/x/crypto from 0.51.0 to 0.52.0 (#3127) 2026-07-21 09:38:14 +02:00
mkdocs.yml bump to v2.0 (#3134) 2026-07-27 23:50:17 +02:00
run_operator_locally.sh Modernize code generation (#3003) 2026-01-09 14:22:10 +01:00

README.md

Postgres Operator

Tests E2E Tests Coverage Status

The Postgres Operator delivers an easy to run highly-available PostgreSQL clusters on Kubernetes (K8s) powered by Patroni. It is configured only through Postgres manifests (CRDs) to ease integration into automated CI/CD pipelines with no access to Kubernetes API directly, promoting infrastructure as code vs manual operations.

Operator features

  • Rolling updates on Postgres cluster changes, incl. quick minor version updates
  • Live volume resize without pod restarts (AWS EBS, PVC)
  • Database connection pooling with PGBouncer
  • Support fast in place major version upgrade. Supports global upgrade of all clusters.
  • Pod protection during bootstrap phase and configurable maintenance windows
  • Restore and cloning Postgres clusters on AWS, GCS and Azure
  • Additionally logical backups to S3 or GCS bucket can be configured
  • Standby cluster from S3 or GCS WAL archive or remote host
  • Configurable for non-cloud environments
  • Basic credential and user management on K8s, eases application deployments
  • Support for custom TLS certificates
  • UI to create and edit Postgres cluster manifests
  • Compatible with OpenShift
  • Multi-arch support

PostgreSQL features

The Postgres Operator has been developed at Zalando and is being used in production for over five years.

Supported Postgres & K8s versions

Release Postgres versions K8s versions Golang
v2.0.0 14 → 18 1.27+ 1.26.4
v1.15.1 13 → 17 1.27+ 1.25.3
v1.14.0 13 → 17 1.27+ 1.23.4
v1.13.0 12 → 16 1.27+ 1.22.5
v1.12.0 11 → 16 1.27+ 1.22.3
v1.11.0 11 → 16 1.27+ 1.21.7

Getting started

For a quick first impression follow the instructions of this tutorial.

Migrating from v1 to v2 operator

If you have been using Postgres Operator since v1.x (thank you), make sure you have read the migration docs before deploying a v2 operator.

Documentation

There is a browser-friendly version of this documentation at postgres-operator.readthedocs.io