March 16, 2021·4 min read·engineeringkafkastrimzikubernetesconfiguration

Strimzi 0.22 separates resource conversion from CRD storage migration

Strimzi 0.22 introduces v1beta2 resources without deprecated fields. Converting configuration and changing the storage version are separate parts of preparing for the next operator release.

Changing the API version written in a YAML file does not finish migrating the objects already stored in Kubernetes. Strimzi 0.22.0, released March 16, introduces v1beta2 for all its custom resources. The release removes deprecated fields from that version and provides a migration interval before the next operator release drops the older APIs.

The announcement ties this work to the planned removal of Kubernetes' apiextensions/v1beta1 support in 1.22. That is the API for custom resource definitions. Strimzi's v1beta2 is the version of resources those definitions describe. The two names concern different objects, even though the upgrade needs to account for both.

I value Kafka's ability to retain history independently of its consumers. Operating it declaratively introduces another form of retained state, the configuration stored by the control plane. A migration has to account for that existing representation as well as the files intended to describe the next one.

The definition and the resource have different versions

The Kafka CRD shipped in the release makes the layers visible. Its own apiVersion is apiextensions.k8s.io/v1beta1. Within the definition, the group is kafka.strimzi.io, the resource kind is Kafka, and a list describes versions of that resource. The definition is a Kubernetes object that establishes another API.

The shipped definition includes served and storage flags for its versions. The older v1beta1 entry is marked for storage, while v1alpha1 is served without being the storage version. This shows why accepting a particular request version and choosing the version for persistent representation are different concerns.

That distinction is useful when interpreting a successful API request. A client being able to submit or retrieve a resource does not by itself prove that the stored object has moved to the representation needed for a later upgrade. Compatibility during the migration interval is intended to let that work happen, not to establish that it already has.

Deprecated fields need a structural replacement

The tagged changelog includes an external logging example. Previously, the configuration names a ConfigMap through logging.name. Its replacement uses logging.valueFrom.configMapKeyRef and specifies both the ConfigMap name and the key containing its configuration.

The resulting section has an explicit reference structure:

logging:
  type: external
  valueFrom:
    configMapKeyRef:
      name: my-config-map
      key: log4j.properties

This is more than changing a version string. A configuration that used the old field has to express its meaning through the replacement structure. The new form also names the particular key, making the referenced entry within the ConfigMap explicit.

The same changelog changes Ingress handling. Strimzi no longer automatically supplies nginx when no class is specified for an Ingress listener. It directs users to the listener configuration's class field. That change affects a default an existing configuration may have relied on, independently of whether its YAML can be parsed.

These examples explain why removing deprecated fields requires examining meaning. A configuration can depend on where a value is located or on a value the operator previously supplied. A mechanical change to the document header cannot preserve those assumptions unless it also translates the relevant properties.

The release also changes Cruise Control logging to Log4j 2 syntax. For inline configuration it replaces cruisecontrol.root.logger with rootLogger.level. External configuration needs a log4j2.properties file using the new syntax. This is another case where preserving the old text under a new resource version would not express the configuration expected by the updated component.

Conversion has to reach the cluster

The 0.22 deployment and upgrade guide provides an API conversion tool. Its file conversion mode can write updated YAML without changing the source file. That provides an inspectable result before it is applied. Conversion is complete only after the cluster's resource has been updated with the new configuration.

The guide separately documents direct resource conversion and CRD upgrade. It says to convert all Strimzi resources across the cluster before changing the CRD storage version. The storage upgrade changes spec.versions and updates resources to store them under v1beta2. The tool requires Java 11 and appropriate administrative permissions.

I find that separation valuable because it identifies what a completed migration means. Updated files are evidence about the desired configuration. Updated resource objects and storage version are evidence about control-plane state. Both matter when the next operator will stop accepting older APIs.

Strimzi 0.22 supplies the compatibility interval in which to perform that translation. The release announcement requires completion after upgrading to 0.22 and before the planned 0.23 transition. The relevant outcome is a consistent set of resource fields and stored versions, rather than a collection of manifests whose version headers changed while the existing objects remained untouched.