Visitar URL original
Helm ignores ownership during upgrade · Issue #32218 · helm/helm · GitHub
Skip to content

Helm ignores ownership during upgrade #32218

Open

Description

@mark007

What happened?

When a resource is transferred from one release to another using --take-ownership, and then the original release is upgraded to a version that no longer includes that resource, helm deletes the resource from the cluster — even though it is now owned by a different release.

This was recently fixed for the uninstall case in PR #31584 (which resolved #31333), where verifyOwnershipBeforeDelete now correctly skips resources not owned by the release being uninstalled. However, the upgrade path has no equivalent ownership check.

When helm computes the diff between old and new manifests during upgrade, it deletes orphaned resources based solely on whether helm.sh/resource-policy: keep is present — it does not check meta.helm.sh/release-name or meta.helm.sh/release-namespace.

The deletion happens in pkg/kube/client.go in the update() function (around line 647):

for _, info := range originals.Difference(targets) {
    // ...
    if annotations != nil && annotations[ResourcePolicyAnno] == KeepPolicy {
        continue
    }
    if err := deleteResource(info, metav1.DeletePropagationBackground); err != nil {

This checks helm.sh/resource-policy: keep but does not check meta.helm.sh/release-name. Adding an ownership check here (similar to verifyOwnershipBeforeDelete in the uninstall path) would complete the feature.

What did you expect to happen?

When upgrading release-a to a version that no longer includes a resource, helm should check the live ownership annotations before deleting. If meta.helm.sh/release-name on the resource points to a different release (e.g. release-b), it should skip deletion — the same way helm uninstall now does after PR #31584.

How can we reproduce it (as minimally and precisely as possible)?

# Create two simple charts:
# chart-a-v1: contains ConfigMap "shared-config" + ConfigMap "chart-a-own"
# chart-a-v2: contains only ConfigMap "chart-a-own" (shared-config removed)
# chart-b-v1: contains ConfigMap "shared-config" + ConfigMap "chart-b-own"

# Step 1: Install chart-a v1
helm install release-a ./chart-a-v1 -n test

# Step 2: Install chart-b, adopting shared-config
helm install release-b ./chart-b-v1 -n test --take-ownership

# Verify ownership transferred:
kubectl get configmap shared-config -n test -o jsonpath='{.metadata.annotations}'
# {"meta.helm.sh/release-name":"release-b","meta.helm.sh/release-namespace":"test"}

# Step 3: Upgrade release-a to v2 (removes shared-config from its manifest)
helm upgrade release-a ./chart-a-v2 -n test

# Result: shared-config is DELETED, even though release-b owns it
kubectl get configmap shared-config -n test
# Error from server (NotFound): configmaps "shared-config" not found

For contrast, uninstall works correctly:

# (same setup as above, steps 1-2)
helm uninstall release-a -n test
# level=WARN msg="skipping delete of resource not owned by this release" kind=ConfigMap name=shared-config
# 1 resource(s) were not deleted because they are not owned by this release:
# [ConfigMap] shared-config

# shared-config survives
kubectl get configmap shared-config -n test
# NAME            DATA   AGE
# shared-config   2      30s
``

### Helm version

<details>

```console
$ helm version
version.BuildInfo{Version:"v4.2.0", GitCommit:"06468084e85c244c712834933d25ea232a4c2093", GitTreeState:"clean", GoVersion:"go1.26.3", KubeClientVersion:"v1.36"}

Kubernetes version

Details
$ kubectl version
Client Version: v1.35.2
Server Version: v1.35.0

Activity

  1. cg49996w11 commented on Jun 21, 2026

    @cg49996w11

    @mark007 , I want to work on this issue. Please assign it to me

  2. cg49996w11 commented on Jun 21, 2026

    @cg49996w11

    /assign

  3. venom02 commented on Jul 7, 2026

    @venom02

    yes please, i am blocked too with this take-ownership broken feature

  4. mark007 commented on Sep 15, 2026

    @mark007
    Author

    Thanks for assigning this @cg49996w11 . May I ask if the pull request you created looks to be working, does it just need a code review or is further work required? Many thanks.

  5. added
    bugCategorizes issue or PR as related to a bug.
    on Sep 30, 2026
  6. silence-coding commented on Oct 21, 2026

    @silence-coding

    I've opened #32793 as an alternative fix for this issue.

    It applies the same ownership check to the delete phase of Update (pkg/kube/client.go), so a resource that has been adopted by another release (via --take-ownership) is no longer deleted when the source release is upgraded/rolled back.

    Differences from the stalled draft #32257:

    • Covers all three Update call sites — upgrade, rollback, and install — not just upgrade. They share the same update() delete loop.
    • Checks only meta.helm.sh/release-name (not release-namespace) to avoid edge-case false skips for cluster-scoped or cross-namespace resources.
    • Adds a ClientUpdateOptionOwnership(releaseName) option (single param) and wires it from the three action call sites.

    Verified on a k3s cluster with fixed vs. unmodified builds:

    • One-way transfer (A installs, B adopts via --take-ownership, upgrade A removes): fixed build keeps the resource; unmodified deletes it.
    • Bidirectional swap (A→B and B→A, both via upgrade): fixed build keeps both resources with correct ownership; unmodified loses the resource adopted by the first-upgrading release.
    • Regular upgrade removing a release's own resource: still deleted (no regression).

    Unit + integration test details are in the PR description. Happy to adjust based on maintainer feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugCategorizes issue or PR as related to a bug.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions