Skip to content

CRD Validations for etcd

  • The validations for the fields within the etcd resource are done via kubebuilder markers for CRD validation.
  • The validations for clusters with kubernetes versions >= 1.29 are written using a combination of CEL expressions via the x-validation tag which provides a straightforward syntax to write validation rules for the fields, and pattern matching with the use of the validation tag.
  • The validations for clusters with kubernetes versions < 1.29 will not contain validations via CEL expressions since this is GA for kubernetes version 1.29 or higher.
  • Upon any changes to the validation rules to the etcd resource, the yaml files for the same can be generated by running the make generate command.

Validation rules:

Type Validation rules:

The validations for fields of types Duration(metav1.Duration) and cron expressions are done via regex matching. These use the validation:Pattern marker.(The checking for the Quantity(resource.Quantity) fields are done by default, hence, no explicit validation is needed for the fields of this type):

  • Duration fields: '^([0-9]+([.][0-9]+)?h)?([0-9]+([.][0-9]+)?m)?([0-9]+([.][0-9]+)?s)?([0-9]+([.][0-9]+)?d)?$')

  • Cron expression: ^(\*|[1-5]?[0-9]|[1-5]?[0-9]-[1-5]?[0-9]|(?:[1-9]|[1-4][0-9]|5[0-9])\/(?:[1-9]|[1-4][0-9]|5[0-9]|60)|\*\/(?:[1-9]|[1-4][0-9]|5[0-9]|60))\s+(\*|[0-9]|1[0-9]|2[0-3]|[0-9]-(?:[0-9]|1[0-9]|2[0-3])|1[0-9]-(?:1[0-9]|2[0-3])|2[0-3]-2[0-3]|(?:[1-9]|1[0-9]|2[0-3])\/(?:[1-9]|1[0-9]|2[0-4])|\*\/(?:[1-9]|1[0-9]|2[0-4]))\s+(\*|[1-9]|[12][0-9]|3[01]|[1-9]-(?:[1-9]|[12][0-9]|3[01])|[12][0-9]-(?:[12][0-9]|3[01])|3[01]-3[01]|(?:[1-9]|[12][0-9]|30)\/(?:[1-9]|[12][0-9]|3[01])|\*\/(?:[1-9]|[12][0-9]|3[01]))\s+(\*|[1-9]|1[0-2]|[1-9]-(?:[1-9]|1[0-2])|1[0-2]-1[0-2]|(?:[1-9]|1[0-2])\/(?:[1-9]|1[0-2])|\*\/(?:[1-9]|1[0-2]))\s+(\*|[1-7]|[1-6]-[1-7]|[1-6]\/[1-7]|\*\/[1-7])$

    • NOTE: The provided regex does not account for special strings such as @yearly or @monthly. Additionally, it fails to invalidate cases involving the step operator (x/y) and the range operator (x-y), where the cron expression is considered valid even if x > y. Please ensure these values are validated before passing the expression.

Update validations

These validations are triggered when an update operation is done on the etcd resource.

  • Immutable fields: The fields etcd.spec.StorageClass , etcd.spec.StorageCapacity and etcd.spec.VolumeClaimTemplate are immutable. The immutability is enforced by the CEL expression : self == oldSelf.

  • The value set for the field etcd.spec.replicas can either be decreased to 0 or increased. This is enforced by the CEL expression: self==0 ? true : self < oldSelf ? false : true

Field validations

  • The fields which expect only a particular set of values are checked by using the kubebuilder marker: +kubebuilder:validation:Enum=<value1>;<value2>
    • The etcd.spec.etcd.metrics can only be set as either basic or extensive.
    • The etcd.spec.backup.garbageCollectionPolicy can only be set as Exponential or LimitBased
    • The etcd.spec.backup.compression.policy can only be set as either gzip or lzw or zlib.
    • The etcd.spec.sharedConfig.autoCompactionMode can only be set as either periodic or revision.
  • The value of etcd.spec.backup.garbageCollectionPeriod must be greater than etcd.spec.backup.deltaSnapshotPeriod. This is enforced by the CEL expression !(has(self.deltaSnapshotPeriod) && has(self.garbageCollectionPeriod)) || duration(self.deltaSnapshotPeriod).getSeconds() < duration(self.garbageCollectionPeriod).getSeconds(). The first part of the expression ensures that both the fields are present and then compares the values of the garbageCollectionPeriod and deltaSnapshotPeriod fields, if not, skips the check.

  • The value of etcd.spec.StorageCapacity must be more than 3 times that of the etcd.spec.etcd.quota if backups are enabled. If not, the value must be greater than that of the etcd.spec.etcd.quota field. This is enforced by using the CEL expression: has(self.storageCapacity) && has(self.etcd.quota) ? (has(self.backup.store) ? quantity(self.storageCapacity).compareTo(quantity(self.etcd.quota).add(quantity(self.etcd.quota)).add(quantity(self.etcd.quota))) > 0 : quantity(self.storageCapacity).compareTo(quantity(self.etcd.quota)) > 0 ): true The check for whether backups are enabled or not is done by checking if the field etcd.spec.backup.store exists.

EU and German government funding logos

Funded by the European Union – NextGenerationEU.

The views and opinions expressed are solely those of the author(s) and do not necessarily reflect the views of the European Union or the European Commission. Neither the European Union nor the European Commission can be held responsible for them.