Kubernetes CRD Pruning Management
Kubernetes CRD Pruning Management ensures efficient resource cleanup by automatically removing unused Custom Resource Definitions in Kubernetes clusters.
Kubernetes CRD Pruning Management is the practice of understanding, configuring, and debugging the API server's automatic removal of fields submitted on a custom resource that are not declared in its OpenAPI schema, a behavior enabled by structural schemas that silently discards unrecognized data rather than rejecting it, with targeted escape hatches available where genuinely unstructured data is a deliberate design choice.
Why Pruning Exists
Structural Schemas Enable Automatic Field Management
Once a CRD's schema satisfies the structural schema requirement — every field has a known type, and the schema does not permit arbitrary properties at any level via unconstrained additionalProperties — the API server gains the ability to reason about exactly which fields a stored object is allowed to contain, which is the same capability that lets it merge fields correctly during server-side apply, generate accurate kubectl explain output, and prune anything outside that known shape.
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
replicas:
type: integer
Default Pruning Behavior
Submitting an object with a field not declared in the schema does not produce an error under default pruning behavior; the API server simply omits that field from the stored object, as if it had never been sent.
kubectl apply -f - <<'EOF'
apiVersion: databases.example.com/v1
kind: PostgresCluster
metadata:
name: orders-db
spec:
replicas: 3
undocumentedField: "this will be silently dropped"
EOF
kubectl get postgrescluster orders-db -o jsonpath='{.spec}'
# {"replicas":3}
The Danger of Silent Pruning
Typos That Fail Without an Error
Because pruning is silent rather than rejecting, a field name typo (replias instead of replicas) results in the intended value being dropped entirely and the field falling back to its schema default or zero value, with no error surfaced to the client, a class of bug that is notoriously difficult to diagnose without explicitly diffing submitted YAML against the stored object.
kubectl get postgrescluster orders-db -o yaml | diff - submitted.yaml
Rejecting Instead of Pruning
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
additionalProperties: false
properties:
replicas:
type: integer
Setting additionalProperties: false at a given object level changes unknown-field handling from silent pruning to outright rejection at admission time, surfacing an explicit validation error for the same typo instead of a silent, hard-to-diagnose data loss, at the cost of requiring every legitimate field to be explicitly declared before it can be used.
Deliberately Preserving Unstructured Data
The x-kubernetes-preserve-unknown-fields Escape Hatch
For fields that legitimately need to hold arbitrary, schema-less data — an embedded third-party configuration blob, a passthrough field for a downstream system's own schema — the schema can mark a specific subtree exempt from pruning.
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
extraConfig:
type: object
x-kubernetes-preserve-unknown-fields: true
Only the extraConfig subtree above bypasses pruning; every other part of the object remains subject to normal structural schema pruning, allowing a resource to combine strict validation of its well-known fields with an explicitly unstructured escape hatch where genuinely needed.
The Deprecated Cluster-Wide Escape Hatch
spec:
preserveUnknownFields: true
The top-level spec.preserveUnknownFields: true setting on the CRD itself disables structural schema requirements and pruning across the entire resource; this is a legacy, deprecated mechanism retained for backward compatibility with pre-structural-schema CRDs and is not recommended for new CRDs, since it forfeits pruning, defaulting, and kubectl explain support cluster-wide rather than for a specific, deliberately unstructured field.
Interaction with Server-Side Apply
Pruning and Field Ownership
Because server-side apply tracks field ownership per manager based on the declared schema, a field pruned before storage is also absent from the managed-fields ledger, meaning a client attempting to manage an undeclared field through server-side apply sees it neither stored nor tracked, which is a further practical reason to keep the schema synchronized with every field the resource actually needs to support.
kubectl apply --server-side -f postgrescluster.yaml --field-manager=my-controller
Debugging Pruned Fields in Practice
Comparing Submitted and Stored Shape
kubectl get postgrescluster orders-db -o yaml > stored.yaml
diff submitted.yaml stored.yaml
When an Operator or user reports a field "not taking effect," the standard diagnostic step is comparing the submitted manifest against the stored object's YAML to determine whether the field was pruned at admission (invisible in stored.yaml) versus accepted but ignored by the controller's reconcile logic (present in stored.yaml but with no observable effect), since these two failure modes require entirely different fixes.
Relationship to CRD Schema and Validation Management
Pruning management is a direct consequence of the schema authoring practices covered under CRD schema management, and it interacts closely with validation management's layering: a field intended to be validated by a CEL rule or webhook must first survive pruning to reach that layer at all, making correct, complete schema declaration the prerequisite that every downstream validation and reconciliation step depends on.