Title: Add Pod Security Standards (PSA) Fields Support in postgresql CR spec for v2.0.1+
Repository: https://github.com/zalando/postgres-operator
Version: postgres-operator v2.0.1 (and v2.0.0)
Date: 2026-08-03
Problem Statement
postgres-operator v2.0.1 does not support Pod Security Standards (PSA) Restricted profile fields in the postgresql Custom Resource Definition (CRD). This prevents compliance with Kubernetes PSA enforcement policies like Kyverno's psa-validation-by-pod/restricted.
The operator moved PSA configuration from OperatorConfiguration (v1.x) to individual postgresql CR specs (v2.x), but the CRD schema was not updated to include the necessary fields for PSA compliance.
Missing Fields in postgresql CR Schema
The following PSA-related fields are defined in the Spilo container specification but are missing from the postgresql CRD schema:
1. Spilo Container PSA Fields
spiloRunAsNonRoot:
type: boolean
description: "Enforce non-root execution for spilo container (PSA Restricted requirement)"
spiloAllowPrivilegeEscalation:
type: boolean
description: "Prevent privilege escalation in spilo container (PSA Restricted requirement)"
droppedPodCapabilities:
type: array
items:
type: string
description: "Linux capabilities to drop from spilo container (PSA Restricted: ALL)"
spiloSeccompProfile:
type: object
properties:
type:
type: string
localhostProfile:
type: string
description: "Seccomp profile for spilo container (PSA Restricted: RuntimeDefault)"
2. Sidecar Container PSA Fields (in sidecars[].securityContext)
sidecars:
- name: exporter
securityContext:
allowPrivilegeEscalation:
type: boolean
capabilities:
type: object
properties:
add:
type: array
items: string
drop:
type: array
items: string
readOnlyRootFilesystem:
type: boolean
runAsNonRoot:
type: boolean
runAsUser:
type: integer
format: int64
seccompProfile:
type: object
properties:
type:
type: string
localhostProfile:
type: string
Root Cause
In v2.0.1, the operator development team:
- ✅ Moved PSA configuration from
OperatorConfiguration to individual postgresql CR specs
- ✅ Updated the Go type definitions in
postgresql_types.go
- ❌ Did NOT update the CRD YAML schema to reflect these new fields
When CRD schemas lack field definitions, Kubernetes API server silently prunes unknown fields during validation, breaking GitOps workflows and causing infinite sync loops.
Reference: Kubernetes 1.25+ applies strict CRD schema validation. See CRD Validation Rules.
Impact
Without PSA Field Support:
-
Kyverno Policy Violations: Pods fail PSA Restricted validation
policy psa-validation-by-pod/restricted fail:
- allowPrivilegeEscalation != false
- runAsNonRoot != true
- capabilities not dropped
- seccompProfile not set
-
ArgoCD Infinite OutOfSync: PSA fields in postgresql CR are rejected by API server validation
error: error validating data: ValidationError(PostgreSQL.spec):
unknown field "spiloRunAsNonRoot" in io.acid.zalan.do.v1.PostgreSQL.spec
-
Manual CRD Patches Required: Teams must manually patch the CRD to add field definitions
kubectl patch crd postgresqls.acid.zalan.do --type merge \
-p '{"spec":{"versions":[{"schema":{"openAPIV3Schema":{"properties":{"spec":{"properties":{"spiloRunAsNonRoot":{"type":"boolean"}}}}}}}]}}'
Proof of Missing Fields
Current CRD status (v2.0.1):
spiloRunAsUser ✅ Defined
spiloRunAsGroup ✅ Defined
spiloRunAsNonRoot ❌ Missing
spiloAllowPrivilegeEscalation ❌ Missing
droppedPodCapabilities ❌ Missing
spiloSeccompProfile ❌ Missing
sidecars[].securityContext ❌ Missing (only name, image, env defined)
Kubernetes API Server Behavior:
$ kubectl apply -f postgresql-with-psa.yaml
error: error validating "postgresql.yaml": error validating data:
ValidationError(PostgreSQL.spec.spiloRunAsNonRoot): unknown field "spiloRunAsNonRoot"...
Use Case: Kubernetes PSA Enforcement
With Kubernetes Pod Security Standards and tools like Kyverno, clusters enforce security policies:
# Kyverno Policy (Restricted Profile)
validationFailureAction: enforce
rules:
- name: require-non-root
validation:
message: "Running as root is not allowed"
pattern:
spec:
=(containers):
- securityContext:
runAsNonRoot: true
=(initContainers):
- securityContext:
runAsNonRoot: true
Without PSA field support in the postgresql CR, pods cannot be deployed to clusters with enforced PSA policies.
Expected Behavior
Users should be able to define PSA compliance in postgresql CR:
apiVersion: acid.zalan.do/v1
kind: postgresql
metadata:
name: my-db
namespace: default
spec:
numberOfInstances: 3
# PSA Restricted Compliance
spiloRunAsNonRoot: true
spiloAllowPrivilegeEscalation: false
droppedPodCapabilities:
- ALL
spiloSeccompProfile:
type: RuntimeDefault
sidecars:
- name: exporter
image: prometheuscommunity/postgres-exporter:latest
securityContext:
runAsNonRoot: true
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
seccompProfile:
type: RuntimeDefault
This should validate without manual CRD patches.
Actual Behavior
Currently, applying the same postgresql CR results in:
- ✅ Operator accepts the CR (Go types support it)
- ❌ Kubernetes API rejects validation (CRD schema missing)
- ❌ Fields are silently pruned from spec
- ❌ Pod security is NOT applied
- ❌ Kyverno policy violations occur
Workaround (Temporary)
Teams must manually patch the CRD to add PSA field definitions:
# Temporary Patch - Not Recommended for Production
kubectl apply --server-side --force-conflicts -f postgresqls-extended-crd.yaml
This workaround:
- ❌ Breaks GitOps automation
- ❌ Requires manual intervention on every cluster
- ❌ Gets overwritten on operator upgrades
- ❌ Is not documented in operator release notes
Proposed Solution
Update the postgres-operator v2.0.1+ CRD YAML generation to include PSA fields in the postgresql CR schema:
Location: pkg/apis/acid.zalan.do/v1/postgresql_types.go
Add struct tags for CRD schema generation:
type PostgresSpec struct {
// ... existing fields ...
// PSA Restricted Compliance
SpiloRunAsNonRoot *bool `json:"spiloRunAsNonRoot,omitempty"`
SpiloAllowPrivilegeEscalation *bool `json:"spiloAllowPrivilegeEscalation,omitempty"`
DroppedPodCapabilities []string `json:"droppedPodCapabilities,omitempty"`
SpiloSeccompProfile *SeccompProfile `json:"spiloSeccompProfile,omitempty"`
}
type SeccompProfile struct {
Type string `json:"type,omitempty"`
LocalhostProfile *string `json:"localhostProfile,omitempty"`
}
Rebuild CRD:
make generate-crd
# This regenerates crds/postgresqls.yaml with the new fields
Related Issues & PRs
Affected Versions
- postgres-operator v2.0.0: ❌ Missing
- postgres-operator v2.0.1: ❌ Missing
- postgres-operator v1.14.0: ✅ PSA in OperatorConfiguration (deprecated approach)
Testing Recommendations
-
Unit Test: Verify CRD schema includes all PSA fields
kubectl apply -f test-postgresql-with-psa.yaml --dry-run=server
# Should validate without errors
-
E2E Test: Verify pods render with PSA security context
kubectl get pod <pod> -o jsonpath='{.spec.containers[0].securityContext}'
# Should show: {"runAsNonRoot":true,"allowPrivilegeEscalation":false,...}
-
Kyverno Integration Test: Verify compliance with PSA Restricted policy
# Deploy with Kyverno enforce mode
# Postgres pods should pass validation
References
Priority
High — Blocks deployment to production Kubernetes clusters with PSA enforcement enabled.
Suggested Labels
type/feature-request
area/crd
area/security
component/v2.0
priority/high
Title: Add Pod Security Standards (PSA) Fields Support in postgresql CR spec for v2.0.1+
Repository: https://github.com/zalando/postgres-operator
Version: postgres-operator v2.0.1 (and v2.0.0)
Date: 2026-08-03
Problem Statement
postgres-operator v2.0.1 does not support Pod Security Standards (PSA) Restricted profile fields in the
postgresqlCustom Resource Definition (CRD). This prevents compliance with Kubernetes PSA enforcement policies like Kyverno'spsa-validation-by-pod/restricted.The operator moved PSA configuration from
OperatorConfiguration(v1.x) to individualpostgresqlCR specs (v2.x), but the CRD schema was not updated to include the necessary fields for PSA compliance.Missing Fields in postgresql CR Schema
The following PSA-related fields are defined in the Spilo container specification but are missing from the postgresql CRD schema:
1. Spilo Container PSA Fields
2. Sidecar Container PSA Fields (in
sidecars[].securityContext)Root Cause
In v2.0.1, the operator development team:
OperatorConfigurationto individualpostgresqlCR specspostgresql_types.goWhen CRD schemas lack field definitions, Kubernetes API server silently prunes unknown fields during validation, breaking GitOps workflows and causing infinite sync loops.
Reference: Kubernetes 1.25+ applies strict CRD schema validation. See CRD Validation Rules.
Impact
Without PSA Field Support:
Kyverno Policy Violations: Pods fail PSA Restricted validation
ArgoCD Infinite OutOfSync: PSA fields in postgresql CR are rejected by API server validation
Manual CRD Patches Required: Teams must manually patch the CRD to add field definitions
kubectl patch crd postgresqls.acid.zalan.do --type merge \ -p '{"spec":{"versions":[{"schema":{"openAPIV3Schema":{"properties":{"spec":{"properties":{"spiloRunAsNonRoot":{"type":"boolean"}}}}}}}]}}'Proof of Missing Fields
Current CRD status (v2.0.1):
spiloRunAsUser✅ DefinedspiloRunAsGroup✅ DefinedspiloRunAsNonRoot❌ MissingspiloAllowPrivilegeEscalation❌ MissingdroppedPodCapabilities❌ MissingspiloSeccompProfile❌ Missingsidecars[].securityContext❌ Missing (only name, image, env defined)Kubernetes API Server Behavior:
Use Case: Kubernetes PSA Enforcement
With Kubernetes Pod Security Standards and tools like Kyverno, clusters enforce security policies:
Without PSA field support in the postgresql CR, pods cannot be deployed to clusters with enforced PSA policies.
Expected Behavior
Users should be able to define PSA compliance in postgresql CR:
This should validate without manual CRD patches.
Actual Behavior
Currently, applying the same postgresql CR results in:
Workaround (Temporary)
Teams must manually patch the CRD to add PSA field definitions:
This workaround:
Proposed Solution
Update the postgres-operator v2.0.1+ CRD YAML generation to include PSA fields in the
postgresqlCR schema:Location:
pkg/apis/acid.zalan.do/v1/postgresql_types.goAdd struct tags for CRD schema generation:
Rebuild CRD:
make generate-crd # This regenerates crds/postgresqls.yaml with the new fieldsRelated Issues & PRs
Affected Versions
Testing Recommendations
Unit Test: Verify CRD schema includes all PSA fields
kubectl apply -f test-postgresql-with-psa.yaml --dry-run=server # Should validate without errorsE2E Test: Verify pods render with PSA security context
Kyverno Integration Test: Verify compliance with PSA Restricted policy
References
Priority
High — Blocks deployment to production Kubernetes clusters with PSA enforcement enabled.
Suggested Labels
type/feature-requestarea/crdarea/securitycomponent/v2.0priority/high