You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Deleting a tenant with a Kafka app hangs the namespace in Terminating (KafkaTopic strimzi.io/topic-operator finalizer) #3793
Deleting a tenant that has a Kafka app leaves the tenant namespace stuck in Terminating indefinitely. The KafkaTopic CR keeps the finalizer strimzi.io/topic-operator, but the Strimzi topic-operator is torn down together with the Kafka app, so nothing ever removes the finalizer and the namespace never finalizes.
Environment
Cozystack v1.6.1-rc.1
A Kafka app (Strimzi-based) with at least one topic
Steps to reproduce
Create a tenant.
Deploy a Kafka app with a topic (e.g. topic orders).
Delete the tenant (this deletes the Kafka app and the namespace).
Actual result
The tenant namespace hangs in Terminating:
NamespaceContentRemaining: Some resources are remaining: kafkatopics.kafka.strimzi.io has 1 resource instances
NamespaceFinalizersRemaining: Some content in the namespace has finalizers remaining: strimzi.io/topic-operator in 1 resource instances
The KafkaTopic (e.g. kafka-kafka-orders) still carries finalizers: [strimzi.io/topic-operator]. The Strimzi topic-operator has already been deleted together with the Kafka app, so no controller is left to drain that finalizer. The namespace stays in Terminating forever.
Reproduced on every tenant that had a Kafka app (multiple tenants stuck the same way).
Expected result
Deleting the tenant / Kafka app should clean up KafkaTopic resources (or drain their finalizers) so the namespace terminates cleanly, without manual finalizer surgery.
Workaround
Remove the finalizer manually, then the namespace finalizes within seconds:
Order the teardown so the Strimzi topic-operator outlives its KafkaTopic resources (drain the strimzi.io/topic-operator finalizer before the operator itself is removed), or have the Kafka app / tenant deletion explicitly delete KafkaTopic CRs and wait for their finalizers to clear before removing the operator.
Good write-up. This is the same class of "operator torn down before its finalizer-owning CRs" bug that has already been fixed for several other apps in the repo, and the mechanism is well understood.
Root cause
The Kafka chart's topics.yaml creates KafkaTopic CRs with no finalizers field [1] — Strimzi's entity-operator adds the strimzi.io/topic-operator finalizer at runtime when it takes ownership. When the Kafka app (and the entity-operator pod) is torn down first, nothing remains to drain that finalizer, so the KafkaTopic objects block namespace GC indefinitely. This was already observed as a side-effect in PR #2934, which noted that a CrashLoopBackOff entity-operator leaves KafkaTopics stuck with the same finalizer.
No pre-delete hook exists for Kafka today
The packages/apps/kafka/templates directory contains only kafka.yaml, topics.yaml, and monitoring/config templates — there is no delete.yaml or any pre-delete hook [2]. The tenant-level cleanup-job.yaml deletes HelmReleases in the namespace with a 90s bounded wait, but that only removes the Kafka HelmRelease — it has no authority over KafkaTopic CRs or their Strimzi finalizers.
Existing patterns to follow
The repo already has two merged fixes for the identical problem class:
PR #3078 — the packages/apps/kubernetes chart's delete.yaml deletes the TenantControlPlane with --wait=true --timeout=120s to let Kamaji drain its own finalizer, then as a backstop patches metadata.finalizers: null on the datastore-config secret if it still exists.
PR #3598 — the tenant pre-delete hook with bounded waits, activeDeadlineSeconds: 270, backoffLimit: 0, and restartPolicy: Never, all sized to fit inside helm-controller's 300s uninstall budget.
Suggested fix direction
Add a Helm pre-delete hook Job to the kafka chart (mirroring the kubernetes app's delete.yaml) that:
Deletes all KafkaTopic CRs in the namespace with --wait=true --timeout=<N>s — while the entity-operator is still alive to process the deletion and drain its finalizer.
As a backstop after the timeout, patches metadata.finalizers: null on any surviving KafkaTopic CRs — safe because the Kafka CR and its operator are being torn down in the same release.
Carries activeDeadlineSeconds set below the HelmRelease uninstall budget, backoffLimit: 0, and restartPolicy: Never, following the same arithmetic used in the tenant and kubernetes hooks.
Your manual workaround (patching finalizers: null) is correct in the interim.
Reproduced on Cozystack with Strimzi 0.45. Helm uninstall removes the topic operator together with the KafkaTopics, so a topic still carrying the strimzi.io/topic-operator finalizer blocks deletion, and the next install with the same release name times out on the leftover topic.
Opened #3938 with a pre-delete hook that deletes only release-labelled KafkaTopics while the operator is still running, without forcing finalizer removal. Render and unit tests pass, and the kafka e2e suite gains an absence assert for the release topics after deletion.
and not one Kafka pod left in the namespace — the entity operator that owns that finalizer is already gone. So the ordering is the same one #3938 fixes, reached from the app side: the release tears down the topic operator, the topics keep a finalizer only it can clear, and the HelmRelease never finalizes behind them.
Two things this adds.
The e2e suite already catches it. hack/e2e-chainsaw/kafka/chainsaw-test.yaml fails on this in ordinary runs, so the defect is not waiting on someone to reproduce it by hand — it is one of the failures authors of unrelated PRs are currently working around. #3938 is open since 9 Sep and the hook is not on main, so every run that reaches that step spends five minutes proving the same thing.
And the app-deletion path may want its own assertion. #3938 adds an absence assert for the release topics after deletion, which covers this if the suite deletes the app; worth confirming that is the path the new assert exercises, since the tenant path and the app path tear things down in a different order.
Fixed by #3938, which deletes the release's KafkaTopics in a pre-delete hook while the topic operator is still running, and #4280 for the hook credentials. The release-1.6 backport is #4421.
Activity
dosubot commentedon Aug 13, 2026
Good write-up. This is the same class of "operator torn down before its finalizer-owning CRs" bug that has already been fixed for several other apps in the repo, and the mechanism is well understood.
Root cause
The Kafka chart's
topics.yamlcreatesKafkaTopicCRs with nofinalizersfield [1] — Strimzi's entity-operator adds thestrimzi.io/topic-operatorfinalizer at runtime when it takes ownership. When the Kafka app (and the entity-operator pod) is torn down first, nothing remains to drain that finalizer, so theKafkaTopicobjects block namespace GC indefinitely. This was already observed as a side-effect in PR #2934, which noted that a CrashLoopBackOff entity-operator leavesKafkaTopics stuck with the same finalizer.No pre-delete hook exists for Kafka today
The
packages/apps/kafka/templatesdirectory contains onlykafka.yaml,topics.yaml, and monitoring/config templates — there is nodelete.yamlor any pre-delete hook [2]. The tenant-level cleanup-job.yaml deletes HelmReleases in the namespace with a 90s bounded wait, but that only removes the Kafka HelmRelease — it has no authority overKafkaTopicCRs or their Strimzi finalizers.Existing patterns to follow
The repo already has two merged fixes for the identical problem class:
packages/apps/kuberneteschart'sdelete.yamldeletes theTenantControlPlanewith--wait=true --timeout=120sto let Kamaji drain its own finalizer, then as a backstop patchesmetadata.finalizers: nullon the datastore-config secret if it still exists.activeDeadlineSeconds: 270,backoffLimit: 0, andrestartPolicy: Never, all sized to fit inside helm-controller's 300s uninstall budget.Suggested fix direction
Add a Helm
pre-deletehook Job to thekafkachart (mirroring the kubernetes app'sdelete.yaml) that:KafkaTopicCRs in the namespace with--wait=true --timeout=<N>s— while the entity-operator is still alive to process the deletion and drain its finalizer.metadata.finalizers: nullon any survivingKafkaTopicCRs — safe because theKafkaCR and its operator are being torn down in the same release.activeDeadlineSecondsset below the HelmRelease uninstall budget,backoffLimit: 0, andrestartPolicy: Never, following the same arithmetic used in the tenant and kubernetes hooks.Your manual workaround (patching
finalizers: null) is correct in the interim.To reply, just mention @dosu.
Docs are dead. Just use Dosu.
yankawai commentedon Aug 21, 2026
Reproduced on Cozystack with Strimzi 0.45. Helm uninstall removes the topic operator together with the KafkaTopics, so a topic still carrying the
strimzi.io/topic-operatorfinalizer blocks deletion, and the next install with the same release name times out on the leftover topic.Opened #3938 with a pre-delete hook that deletes only release-labelled KafkaTopics while the operator is still running, without forcing finalizer removal. Render and unit tests pass, and the kafka e2e suite gains an absence assert for the release topics after deletion.
IvanHunters commentedon Sep 15, 2026
Still reproduces on
mainatb222cb658, and there is a second entry point worth recording: deleting the app hits it, not only deleting the tenant.From the
cozyreportof anE2E (in-tree)run,kafkasuite, stepverify-pvc-reclaim-on-delete:Five minutes, the operation's whole budget, on deleting the Kafka CR itself. No tenant is being removed here.
What the snapshot holds at that moment:
and not one Kafka pod left in the namespace — the entity operator that owns that finalizer is already gone. So the ordering is the same one #3938 fixes, reached from the app side: the release tears down the topic operator, the topics keep a finalizer only it can clear, and the HelmRelease never finalizes behind them.
Two things this adds.
The e2e suite already catches it.
hack/e2e-chainsaw/kafka/chainsaw-test.yamlfails on this in ordinary runs, so the defect is not waiting on someone to reproduce it by hand — it is one of the failures authors of unrelated PRs are currently working around. #3938 is open since 9 Sep and the hook is not onmain, so every run that reaches that step spends five minutes proving the same thing.And the app-deletion path may want its own assertion. #3938 adds an absence assert for the release topics after deletion, which covers this if the suite deletes the app; worth confirming that is the path the new assert exercises, since the tenant path and the app path tear things down in a different order.
fix(kafka): delete release topics before the topic operator is removed (
fix(kafka): keep the pre-delete hook's credentials as long as its Job (…
lexfrei commentedon Sep 23, 2026
Fixed by #3938, which deletes the release's KafkaTopics in a pre-delete hook while the topic operator is still running, and #4280 for the hook credentials. The release-1.6 backport is #4421.
[Backport release-1.6] fix(kafka): delete release topics before the t…