Search code examples
kuberneteskubectl

What happens when updating a CRD schema in k8s without changing the CRD version?


The k8s documentation Versions in CustomResourceDefinitions talks about how to upgrade CRD schema and CRD objects from one version to another.

However, what will happen when I update/change a CRD schema WITHOUT updating its version?

Fr example, I have a CRD schema v1/Foo and two field A,B (written in go):

// api version: v1
type FOOSpec struct {
    A int `json:"a"`
    B int `json:"b"`
}

I use kubebuilder to generate the CRD manifest and apply it in the k8s cluster. After that, The field A is deleted.

// still api version: v1
type FOOSpec struct {
    B int `json:"b"`
}

Again I generate the CRD manifest and apply it in the k8s cluster. Surprisingly k8s simply accept the updated CRD schema and no warning is reported.

Why is that? What if I create a Foo1 object of the first schema and then create a Foo2 object in the second schema. The two object has same version (v1) but the different schema.

I expect k8s to report an error when updating the CRD version without upgrading the version.


Solution

  • You've mostly answered your own question.

    Custom Resource Definitions (CRDs) define Kubernetes resource types in the Kubernetes API.

    In most schema evolutions, it is developers' responsibility to version such changes correctly. Kubernetes can't challenge the developer on the definition of schemas; it must accept the developers' intent (even if problematic).

    The issue as you've observed, it that changing the definition of a GroupVersionKind is problematic and therefore discouraged (in production).

    If you create Resources against CRDs, then revise the CRD (without revising its Version) and create more Resources, you've introduced inconsistency:

    • Removed fields are not accessible in any of the CRD's Resources
    • Added|Changed fields aren't present in pre-change CRD's Resources

    Errors will not arise until an operation (CRUD) is attempted (by the Kubernetes API server) against the Resource.

    Kubernetes Kinds aren't SemVer versioned but follow a limited set of enumerations eg. v1alpha1, v1beta1, v1, v2 ... (see e.g. Version priority). During development I tend to use e.g. v1alpha1, make changes without bumping the version and manage the house-keeping. Once you publish a CRD, it's important to bump versions so that you do not break your users.