Helm 4: install fails on an existing CRD previously installed client-side ("conflict with \"helm\"")
What happened?
helm install with server-side apply (the default for install) fails on a CRD from the chart's crds/ directory when that CRD already exists and was written client-side by Helm itself, as soon as the CRD content changes.
Helm never deletes CRDs, so this is the state left behind by any earlier client-side install (Helm 3, or Helm 4 with --server-side=false) followed by an uninstall, a failed release, or a release rename.
Error: INSTALLATION FAILED: failed to install CRD crds/crd.yaml: conflict occurred while applying object /widgets.example.com apiextensions.k8s.io/v1, Kind=CustomResourceDefinition: Apply failed with 1 conflict: conflict with "helm" using apiextensions.k8s.io/v1: .metadata.annotations.example.com/versionThe API server treats helm with operation Update and helm with operation Apply as two different field managers. For the chart's templates Helm already upgrades the client-side field manager before applying, but the CRDs in crds/ are installed through Client.Create, which does not.
What did you expect to happen?
The install succeeds, as it does with Helm 3 or with --server-side=false, and as it does for the same situation on non-CRD resources.
How can we reproduce it (as minimally and precisely as possible)?
Two charts that differ only in one annotation of the CRD:
chart-v1/Chart.yaml name: demo, version: 0.1.0
chart-v1/crds/crd.yaml the CRD below with example.com/version: "0.1.0"
chart-v1/templates/cm.yaml any ConfigMap
chart-v2/... same, version 0.2.0 and example.com/version: "0.2.0"apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: widgets.example.com
annotations:
example.com/version: "0.1.0"
spec:
group: example.com
scope: Namespaced
names: {plural: widgets, singular: widget, kind: Widget}
versions:
- name: v1
served: true
storage: true
schema: {openAPIV3Schema: {type: object, x-kubernetes-preserve-unknown-fields: true}}helm install demo ./chart-v1 --server-side=false # succeeds
helm uninstall demo # the CRD stays
helm install demo ./chart-v2 # fails with the conflict abovehelm install demo ./chart-v2 --server-side=false succeeds, and so does --force-conflicts (which also overrides fields owned by other managers).
Helm version
v4.1.3+gc94d381Kubernetes version
v1.31.5+k3s1 (k3d v5.8.3, single node)
Source: helm/helm