Let's say I have the following CRD:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: examples.tomasaschan.com
spec:
group: tomasaschan.com
names:
kind: Example
listKind: Examples
plural: examples
singular: example
scope: Namespaced
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
properties:
spec:
properties:
foo:
type: string
type: object
type: object
A valid example object would look like this:
apiVersion: tomasaschan.com/v1
kind: Example
metadata:
name: example1
spec:
foo: bar
Now, because foo isn't required, if I misspell it this resource will still be accepted by the API server:
apiVersion: tomasaschan.com/v1
kind: Example
metadata:
name: example1
spec:
boo: far
I would like to make it so that this raises a schema validation error.
In JSONSchema, I'd do that by setting additionalProperties: false on the schema.openAPIV3Schema.properties.spec node, but that's not allowed structural CRD schemas (if I try, the API server responds with Forbidden: additionalProperties and properties are mutual exclusive).
This old thread recommends setting spec.preserveUnknownFields: false (on the CRD spec); in more recent Kubernetes versions this is instead accomplished by setting x-kubernetes-preserve-unknown-fields: false on each object node in the schema, but as far as I understand they are otherwise equivalent (modulo the scope they apply to). The effect of that would be the API server dropping the misspelled property, but still happily accepting the resulting config - I want it to return a 400 response with a validation error message that the property boo is unknown.
How do I best accomplish that?
The Kubernetes API server's validation mechanism is intended to be tolerant, ignoring unknown fields rather than rejecting them. The schema validation in Kubernetes is based on OpenAPI v3, which is designed to ignore additional properties by default. See https://kubernetes.io/blog/2019/06/20/crd-structural-schema/
As you already stated corretly
x-kubernetes-preserve-unknown-fieldswill not cause an error. And alsoadditionalProperties: false is not possible.If you really need to achieve this at all cost you can accomplish this by creating a validating admission webhook that checks the resource for unknown properties and rejects the request if any are found. This would involve more complex logic and would need to be maintained separately from the CRD itself. Therefore you need to decide on your own if this works for you.