Kubernetes 1.15 gives custom resources a more complete API contract
Conversion webhooks, OpenAPI publishing and pruning reach beta in Kubernetes 1.15. Structural schemas connect these changes by describing which data a custom API actually owns.
An API extension needs more than a place to store an object. Clients need to discover its fields, and the server needs a rule for handling data that the API author never defined. As an API evolves, old and new clients also need compatible representations of the same resource. The Kubernetes 1.15 announcement addresses these problems through beta support for custom-resource conversion webhooks, OpenAPI publishing and pruning. Structural schemas supply the shared description that makes much of this behavior possible.
The release team frames this work around consistency with native resources. A user interacting with a custom resource should not need a different set of expectations merely because its type was added through a CustomResourceDefinition. That goal concerns observable behavior of the API, including which fields survive a write and how tools explain them. It is a substantial development for anyone treating the Kubernetes API as a framework for controllers.
I put more weight on that framework than on the collection of built-in workload types. An extension becomes more useful when ordinary clients can understand its schema and the server applies a defined data contract. Kubernetes 1.15 improves those conditions while keeping important distinctions between beta capabilities and work that remains alpha.
A schema must describe the data completely
The release introduces checks for a restriction called a structural schema. The announcement describes this as complete, non-polymorphic typing of custom-resource fields. A schema violation produces a condition identifying the structural problem. Existing non-structural schemas continue to work through the v1beta1 CRD API, but the release team urges serious users to migrate because new capabilities depend on structural descriptions.
This is a change in how much the server can know about an extension. If the schema describes only selected parts of an object, the server cannot confidently distinguish intentional data from an unknown field throughout the rest. A complete description gives operations such as pruning a meaningful basis. The new requirement is therefore connected to behavior, rather than existing solely as a documentation convention.
The 1.15 CRD API definitions expose the configuration involved. Validation can be supplied globally or through version-specific schemas, and those forms are mutually exclusive. The schema is part of the resource definition that the server processes. An author needs to decide how the declared versions obtain their validation instead of layering incompatible global and per-version descriptions together.
The practical consequence is that an extension author must account for the whole intended object. Previously accepted arbitrary data does not become an intentional field simply because it has appeared in persisted objects. Turning the schema into an authoritative definition requires deciding what the API is meant to preserve. That decision precedes relying on the new data-handling behavior.
Pruning changes which fields can persist
Pruning removes unknown fields, meaning fields absent from the OpenAPI validation schema. The announcement identifies both data consistency and security as reasons for this behavior. Only structures specified by the CRD author should persist to etcd. Custom resources gain the same general expectation that native resources already provide.
In the v1beta1 API used here, unknown fields are preserved by default. A CRD activates pruning by setting spec.preserveUnknownFields to false and supplying the required structural schema. This fragment shows that switch within an otherwise complete CRD definition.
spec:
preserveUnknownFields: false
This setting changes the storage contract. A client sending an extra field cannot assume that the field will remain available in a later read. With preservation enabled, an undeclared field could survive despite being outside the schema. With pruning enabled, the schema determines whether the server recognizes it. That makes schema completeness part of compatibility for clients that already send objects to the extension.
The API definition explicitly preserves apiVersion, kind, metadata and known fields inside metadata. Pruning is not an instruction to discard the object's identity because the extension author has omitted Kubernetes' standard metadata machinery from an application schema. It is a rule for unknown data within the resource's defined representation.
I favor that explicit contract because a controller's input should be describable. The benefit depends on the author's schema matching the intended API. Publishing a partial description and then asking the server to discard everything outside it would produce a different interface from one that deliberately permits arbitrary data.
Conversion separates a served version from the stored version
CustomResourceDefinitions already support multiple versions as a beta capability introduced in 1.14. Kubernetes 1.15 promotes conversion webhooks to beta, allowing the server to convert representations as clients use different versions. The announcement says the administrator deploys the conversion webhook inside the cluster. Version handling can therefore include application-specific transformation rather than merely exposing multiple version labels.
The API types distinguish whether a version is served from whether it is the storage version. Exactly one version must have its storage flag set. That distinction is necessary for understanding the new facility. Serving multiple representations does not mean that each representation receives its own independent stored object. The API needs a defined relationship between what clients request and what the server stores.
Two conversion strategies are available. None changes only the apiVersion field and leaves other fields untouched. Webhook calls an external conversion implementation and requires preserveUnknownFields to be false. A version transition that changes the shape of data therefore needs more than selecting the strategy that only relabels the object.
The webhook configuration includes an ordered list of preferred ConversionReview versions. During negotiation, the server tries a version it supports, and conversion fails when no supported version is available. By default the list contains v1beta1. This is a second compatibility relationship alongside the custom resource's own versions. The API server and conversion service must agree on the protocol carrying the conversion request.
Connection configuration is also part of the API. The types allow either a service reference or an HTTPS URL, with a CA bundle for validating the webhook certificate. They recommend a service reference for a webhook running inside the cluster. As a result, conversion introduces operational dependencies involving reachability and certificate trust. Those dependencies implement behavior that a client may need during ordinary API access.
The connection fields also exclude some configurations that an ordinary HTTP client might accept. A URL cannot contain user credentials, fragments or query parameters. Its path can carry information such as a cluster identifier. The API comments warn that localhost is risky unless the webhook runs on every API server host that might call it. These restrictions make the intended connection model more explicit for extension authors.
Those details matter when the extension moves between clusters. A service reference identifies an in-cluster destination through the fields the API expects. A loopback URL depends on the topology of API server hosts. Both are connection choices exposed by the definition, but they imply different deployment requirements for the conversion implementation.
OpenAPI publishing connects the schema to existing tools
Kube-apiserver already publishes native type descriptions at /openapi/v2. The announcement names kubectl client-side validation, kubectl explain and schema-based client generators as consumers. Beta OpenAPI publishing extends that arrangement to CRDs with structural schemas. A custom type can supply information through tooling that already understands Kubernetes' published schema.
This provides another reason to maintain an accurate definition. The same schema that determines recognized data becomes information consumed by users and generated clients. A mismatch between documentation and server behavior is harder to justify when the server can publish the description it uses. The benefit is strongest when the extension author treats that description as the API's actual contract.
Defaulting remains a separate, alpha capability in this release. The announcement describes defaults expressed through the schema's default keyword, applied to unspecified fields on API input and when reading from etcd. Its alpha status matters even though it belongs to the same broader effort. Adoption of beta pruning or conversion should not imply that defaulting has reached an identical support stage.
Admission webhooks receive related improvements, including opt-in reinvocation of mutating webhooks through reinvocationPolicy: IfNeeded. The release team says these webhooks must tolerate another invocation and that validating webhooks subsequently check invariants. Conversion, mutation and validation have distinct jobs even when the same extension depends on all of them. Kubernetes 1.15 makes the custom API more capable, with its schema and deployed webhook implementations defining the behavior clients can actually rely upon.