[Feature] Pin a constant Kafka cluster ID to survive re-installs and upgrades - #307
Conversation
Test CE Workflos
[Fix] Seaweed Change
# Conflicts: # .github/workflows/release.yml # charts/mlrun-ce/Chart.yaml
…a-bootstrap-constant-clusterip
royischoss
left a comment
There was a problem hiding this comment.
LGTM 3 small comments
| echo " resumed reconciliation on ${res}." | ||
| done | ||
|
|
||
| echo "Kafka cluster ID pinned successfully." |
There was a problem hiding this comment.
maybe worthy to provide a Notes.txt msg if this job failed or succeed
There was a problem hiding this comment.
As we spoke, the note just prints a message based on the user value. I can add a message that the installation uses a constant cluster ID, but I think it will confuse users more than help them. wdyt?
also if the job failed the entire installation shold fail
| app.kubernetes.io/component: clusterid-init | ||
| {{- include "mlrun-ce.common.labels" . | nindent 4 }} | ||
| --- | ||
| apiVersion: rbac.authorization.k8s.io/v1 |
There was a problem hiding this comment.
RBAC wiring is correct. Please scope the Role with resourceNames to {{ .Values.kafka.name }} and {{ .Values.kafka.name }}-pool, drop unused update/list/watch verbs, and note in the PR that the SA retains patch permissions for the life of the release.
means: any pod using this SA can patch any Kafka / KafkaNodePool CR in the namespace — not just the one this chart creates.
The Job script only touches:
kafka/{{ .Values.kafka.name }} → e.g. kafka-stream
kafkanodepool/{{ .Values.kafka.name }}-pool → e.g. kafka-stream-pool
Adding resourceNames would narrow that to those two objects only:
- apiGroups: [kafka.strimzi.io]
resources: [kafkas]
resourceNames: [kafka-stream]
verbs: [get, patch] - apiGroups: [kafka.strimzi.io]
resources: [kafkanodepools]
resourceNames: [kafka-stream-pool]
verbs: [get, patch]
Not a must but hardening the Role
📝 Description
Adds an optional mechanism to pin a constant Kafka cluster ID so that re-installs and upgrades reuse the data on the existing PersistentVolumeClaims instead of failing with
InconsistentClusterIdException.In KRaft mode the Strimzi operator otherwise generates a fresh random cluster ID on every (re)install, which no longer matches the ID persisted in the retained PVC (
meta.properties).Because
clusterIdis a status-only field in the Strimzi CRDs, it cannot be set through a normal Helm/kubectl apply, so the Kafka and KafkaNodePool CRs are now created with reconciliation paused and a post-install hook Job patchesstatus.clusterIdon both resources before resuming reconciliation.This affects only the
kafkacomponent and is gated on the newkafka.clusterIdvalue.🛠️ Changes Made
Added
kafka.clusterIdtocharts/mlrun-ce/values.yaml, defaulting to the fixed value"ByHirbmSVDCwP7YDBt3V2A"(a 22-char base64url-encoded 16-byte UUID); set to""to keep the previous random-ID-per-install behaviour.Added
kafka.clusterIdInitblock tovalues.yamlexposing the hook Job's image (alpine/kubectl:1.33.4) and CPU/memory requests+limits.New template
charts/mlrun-ce/templates/kafka/kafka-clusterid-init.yaml— creates aServiceAccount,Role,RoleBinding, and post-install/post-upgradeJob({{ .Values.kafka.name }}-clusterid-init) that waits for the CRs, patchesstatus.clusterIdonkafka/<name>andkafkanodepool/<name>-poolvia the/statussubresource (idempotent), then removes the pause annotation to resume reconciliation. Guarded by{{- if and .Values.kafka.enabled .Values.kafka.clusterId }}.templates/kafka/kafka-cluster.yamlandtemplates/kafka/kafka-nodepool.yaml— conditionally addstrimzi.io/pause-reconciliation: "true"(only whenkafka.clusterIdis set) so the operator does not format storage with a random ID before the init Job pins the constant ID.The RBAC grants
get/list/watch/patch/updateonkafkas/kafkanodepoolsandget/patch/updateon their/statussubresources, scoped to.Release.Namespace.Hook ordering: CRs at
hook-weight: "5", init Job athook-weight: "10"withhook-delete-policy: before-hook-creation,hook-succeededand a 600s timeout.✅ Checklist
charts/mlrun-ce/Chart.yaml.🧪 Testing
Suggested (not yet confirmed from the diff):
make helm-lint;helm templatewithkafka.enabled=trueto confirm the init Job, RBAC, and pause annotations render only whenkafka.clusterIdis non-empty; andhelm template ... | kubectl apply --dry-run=client -f -for schema validation.A real-cluster run is required to verify the full flow: fresh install pins the ID, a re-install reuses the retained PVC without
InconsistentClusterIdException, and the init Job resumes reconciliation successfully.🔗 References
🚨 Breaking Changes?
Yes (explain below)
No
No new or renamed value keys are removed, and no Secret/ConfigMap names or NodePorts change — but the default behaviour changes:
kafka.clusterIdnow ships with a fixed non-empty default instead of the operator generating a random ID per install.For an existing Kafka deployment whose PVCs already hold data under a previously-generated random cluster ID, upgrading to this chart will cause the init Job to pin
status.clusterIdto the new fixed value and resume reconciliation, which can triggerInconsistentClusterIdExceptionagainst the retainedmeta.properties.Mitigation for such installs: set
kafka.clusterIdto the cluster's existing ID, or setkafka.clusterId: ""to preserve the prior random-ID behaviour.🔍️ Additional Notes
The
clusterIddefault is hardcoded to a single shared value across all installs; consider whether each deployment should generate/pin its own unique ID to avoid multiple clusters sharing the same identifier.The init Job overwrites any pre-existing
status.clusterId(it only logs a WARNING), so upgrades on clusters with existing data need care.