Skip to content

feat(chart): add crds.install flag to gate DNSEndpoint CRD installation - #6595

Open
ausias-armesto wants to merge 1 commit into
kubernetes-sigs:masterfrom
ausias-armesto:feat/crds-install-flag
Open

feat(chart): add crds.install flag to gate DNSEndpoint CRD installation#6595
ausias-armesto wants to merge 1 commit into
kubernetes-sigs:masterfrom
ausias-armesto:feat/crds-install-flag

Conversation

@ausias-armesto

Copy link
Copy Markdown

What does it do?

Adds a .crds.install value (default true) to the external-dns chart, gating installation of the DNSEndpoint CustomResourceDefinition. The CRD is moved from crds/ into templates/dnsendpoint-crd.yaml, wrapped in {{- if .Values.crds.install -}}.

Motivation

When running multiple external-dns releases of this chart in the same cluster (e.g. one release per DNS provider — a common pattern when different Ingress/Service subsets are delegated to different providers), every release installs its own copy of the DNSEndpoint CRD via the chart's bundled crds/ directory. Since CRDs are cluster-scoped, this means the identical CRD object is emitted by more than one Helm release.

GitOps tools that aggregate multiple releases under one logical application (e.g. ArgoCD via Helmfile) then see the same resource (CustomResourceDefinition/dnsendpoints.externaldns.k8s.io) appear more than once within a single application's manifest set, which is treated as a comparison error rather than a warning, blocking sync/diff for the whole application.

Helm's crds/ directory has no templating support by design, so there's no way to conditionally skip it today. Moving the CRD into templates/ with a value-gated toggle lets users installing multiple releases set crds.install: false on all but one release, so the CRD is applied exactly once, while leaving default single-release behavior unchanged.

This follows the same pattern used by several other charts that support multi-release-per-cluster installs (e.g. cert-manager's crds.enabled), trading Helm's CRD-protection-on-uninstall guarantee (native crds/ are never deleted/upgraded by Helm) for the ability to toggle installation — a tradeoff that only affects users who explicitly opt in by setting the value.

More

  • Yes, this PR title follows Conventional Commits
  • Yes, I added unit tests
  • Yes, I updated end user documentation (README regenerated via helm-docs, values.schema.json regenerated via helm schema)
  • Added a CHANGELOG.md entry under ## [UNRELEASED] per docs/contributing/chart.md

Copilot AI review requested due to automatic review settings July 31, 2026 13:58
@kubernetes-prow

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign stevehipwell for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@kubernetes-prow

Copy link
Copy Markdown

Welcome @ausias-armesto!

It looks like this is your first PR to kubernetes-sigs/external-dns 🎉. Please refer to our pull request process documentation to help your PR have a smooth ride to approval.

You will be prompted by a bot to use commands during the review process. Do not be afraid to follow the prompts! It is okay to experiment. Here is the bot commands documentation.

You can also check if kubernetes-sigs/external-dns has its own contribution guidelines.

You may want to refer to our testing guide if you run into trouble with your tests not passing.

If you are having difficulty getting your pull request seen, please follow the recommended escalation practices. Also, for tips and tricks in the contribution process you may want to read the Kubernetes contributor cheat sheet. We want to make sure your contribution gets all the attention it needs!

Thank you, and welcome to Kubernetes. 😃

@kubernetes-prow

Copy link
Copy Markdown

Hi @ausias-armesto. Thanks for your PR.

I'm waiting for a kubernetes-sigs member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work.

Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@kubernetes-prow kubernetes-prow Bot added needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. size/M Denotes a PR that changes 30-99 lines, ignoring generated files. labels Jul 31, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the charts/external-dns Helm chart to support multi-release-per-cluster deployments by introducing a value gate for installing the cluster-scoped DNSEndpoint CRD.

Changes:

  • Adds .crds.install (default true) to control whether the DNSEndpoint CustomResourceDefinition is rendered/installed.
  • Moves the DNSEndpoint CRD manifest into templates/ and wraps it with {{- if .Values.crds.install -}}.
  • Adds Helm unittest coverage and updates generated chart documentation/schema and the chart changelog.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
charts/external-dns/values.yaml Introduces the new .crds.install value with default true.
charts/external-dns/values.schema.json Adds schema for the new crds.install value.
charts/external-dns/tests/crds_test.yaml Adds unit tests ensuring the CRD is present by default and omitted when disabled.
charts/external-dns/templates/dnsendpoint-crd.yaml Renders the CRD conditionally based on .Values.crds.install and adds labels.
charts/external-dns/README.md Documents the new crds.install value in the values table.
charts/external-dns/CHANGELOG.md Adds an UNRELEASED entry for the new .crds.install value.
Suppressed comments (2)

charts/external-dns/templates/dnsendpoint-crd.yaml:7

  • Moving the CRD into templates/ means Helm will treat it like a normal manifest and (by default) delete it on helm uninstall. Since deleting a CRD also deletes all its CRs, this is a high-risk operational change compared to the prior crds/ behavior. Consider adding helm.sh/resource-policy: keep so uninstalling the release does not remove the CRD (users can still delete it manually if desired).

This issue also appears on line 7 of the same file.
charts/external-dns/templates/dnsendpoint-crd.yaml:10

  • The CRD is cluster-scoped and shared across releases. Using external-dns.labels here injects release-specific and version-specific labels (e.g. app.kubernetes.io/instance and helm.sh/chart), which can cause label "flapping" if multiple releases ever render this CRD and also forces a CRD patch on every chart version bump. Consider removing these labels (or using only stable, non-release-specific labels).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread charts/external-dns/CHANGELOG.md Outdated
Copilot AI review requested due to automatic review settings July 31, 2026 14:06
@linux-foundation-easycla

linux-foundation-easycla Bot commented Jul 31, 2026

Copy link
Copy Markdown

CLA Signed
The committers listed above are authorized under a signed CLA.

  • ✅ login: ausias-armesto / name: Ausiàs Armesto (5cf2b81)

@kubernetes-prow kubernetes-prow Bot added cncf-cla: no Indicates the PR's author has not signed the CNCF CLA. and removed cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. labels Jul 31, 2026
Clusters running multiple external-dns releases from this chart (e.g.
one release per DNS provider) get the DNSEndpoint CRD applied by every
release, since it's unconditionally bundled under crds/. This makes
ArgoCD (and similar GitOps tools) see the same CRD resource emitted
more than once within a single Application, which errors instead of
just being a warning.

Move the CRD out of the crds/ directory into templates/, gated by a
new .crds.install value (default true, preserving current behavior).
Set it to false on all but one release to install the CRD exactly
once.

Note: because the CRD is now rendered from templates/, Helm may
attempt to update it on upgrade and will delete it on uninstall unless
it is marked with helm.sh/resource-policy: keep.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated no new comments.

Suppressed comments (1)

charts/external-dns/CHANGELOG.md:23

  • This changelog entry says the CRD is "now rendered from templates/", but in this PR the CRD is already in templates/dnsendpoint-crd.yaml and the change is to gate rendering behind .Values.crds.install. Consider rewording to avoid implying the CRD was moved into templates/ by this change (and to avoid overstating a behavioral change that may have existed previously).
- Add value `.crds.install` to control whether the `DNSEndpoint` `CustomResourceDefinition` is installed. Defaults to `true`; set to `false` on all but one release when running multiple `external-dns` releases (e.g. one per provider) in the same cluster to avoid the CRD being installed more than once. Note: because the CRD is now rendered from `templates/`, Helm may attempt to update it on upgrade and will delete it on uninstall unless it is marked with `helm.sh/resource-policy: keep`.

@ausias-armesto
ausias-armesto force-pushed the feat/crds-install-flag branch from 8f182da to 5cf2b81 Compare July 31, 2026 14:11
@kubernetes-prow kubernetes-prow Bot added cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. and removed cncf-cla: no Indicates the PR's author has not signed the CNCF CLA. labels Jul 31, 2026
@ivankatliarchuk

ivankatliarchuk commented Aug 2, 2026

Copy link
Copy Markdown
Member

Previous attempts

When it was added #4322

Supported with --skip-crd flag. At its core, Helm is a templating engine. Helm's CRD handling is deliberately minimal, and it's a known, longstanding limitation (not a bug) rooted in a design decision:

  • CRDs in crds/ are install-only, never templated. Helm has a special, non-templated crds/ directory (this chart uses exactly that convention. Helm explicitly never updates or deletes anything under crds/ on helm upgrade or helm uninstall, by design.
  • The reason is ownership/blast-radius avoidance. A CRD is a cluster-scoped object; changing or deleting it can affect resources managed by other releases/tools sharing that CRD, or wipe out CRs (and their controllers' data) that Helm has no visibility into. Helm's maintainers decided it's safer to force operators to manage CRD lifecycle explicitly (kubectl apply -f crds/) than to let a chart upgrade silently mutate or drop a cluster-wide schema.
  • Templates can't reference a CRD they just installed, reliably. Because crds/ objects install before templates render, and Helm doesn't guarantee CRD establishment (the API server accepting the new type) before the rest of the chart applies, charts that need to create instances of their own CRD in the same install often race or fail on a fresh cluster.
  • No upgrade path, no patching, no values-driven templating for anything in crds/ — you can't inject {{ .Values.x }} into a CRD manifest the "normal" chart way (some charts fake it by putting CRDs in templates/ instead, but then Helm will try to diff/patch them on upgrade, which risks the same blast-radius problem in the other direction, plus helm uninstall will delete the CRD and cascade-delete every CR of that type cluster-wide).

Helm treats CRDs as "install-time, hands-off-after-that" objects, favoring predictability and avoiding destructive cascades over convenience - which is why most projects (including this chart) ship CRDs in the special crds/ folder and document that upgrades/removals are a manual, out-of-band step for the operator.

If someone from maintainer team thinks we should switch to CRD templating, no objection to unhold.

/hold

@kubernetes-prow kubernetes-prow Bot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Aug 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

chart cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. size/M Denotes a PR that changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants