Skip to content

CRD source ignores --crd-source-apiversion / --crd-source-kind in v0.21.0 #6414

@IceHamster

Description

@IceHamster

What happened:

external-dns v0.21.0 regressed the crd source and appears to ignore --crd-source-apiversion / --crd-source-kind for custom CRDs implementing the DNSEndpoint contract.

In our cluster, this worked with Helm chart 1.20.0 (app v0.20.0) and stopped working with Helm chart 1.21.1 (app v0.21.0).

The parsed config in both versions still shows:

Sources:[service ingress crd]

and in the broken version also shows the custom CRD settings:

CRDSourceAPIVersion:externaldns.nginx.org/v1
CRDSourceKind:DNSEndpoint

so this does not look like a --source parsing issue. The regression appears to be in the CRD source implementation after flag parsing.

What you expected to happen:

The crd source should continue to honor:

  • --crd-source-apiversion
  • --crd-source-kind

for custom CRDs implementing the DNSEndpoint contract, as documented in:

  • docs/sources/crd.md
  • docs/flags.md

and as observed in v0.20.0.

How to reproduce it (as minimally and precisely as possible):

  1. Run external-dns with a custom DNSEndpoint-style CRD, for example:
--source=service
--source=ingress
--source=crd
--crd-source-apiversion=externaldns.nginx.org/v1
--crd-source-kind=DNSEndpoint
--provider=azure
--domain-filter=dev.domain.com
--registry=txt
--txt-owner-id=<owner-id>
  1. Create custom resources under that apiVersion/kind which implement the DNSEndpoint contract and previously produced DNS records on v0.20.0.
  2. Compare behavior between:
    • Helm chart 1.20.0 / app v0.20.0
    • Helm chart 1.21.1 / app v0.21.0

Observed result:

  • v0.20.0: CRD-derived records are reconciled and written.
  • v0.21.0: config still includes Sources:[service ingress crd], but the CRD-derived records are no longer processed.

Repository-level investigation points to ea4d2d16 / PR #6312 (refactor(source/crd): migrate CRD source to controller-runtime cache) as the regression window. The old dynamic CRD path that used the configured apiVersion/kind was replaced with a typed implementation over the built-in externaldns.k8s.io/v1alpha1 DNSEndpoint.

Anything else we need to know?:

  • This looks unintended rather than intentional:

    • the change was introduced as a refactor, not a documented breaking change
    • PR #6312 describes an internal migration to controller-runtime cache and does not mention removing support for custom CRD apiVersion/kind
    • the PR checklist left end-user documentation updates unchecked
    • the CLI still exposes --crd-source-apiversion and --crd-source-kind
    • docs/sources/crd.md still says the CRD source works by specifying apiVersion and kind
    • the chart CRD still describes DNSEndpoint as a contract that a user-specified CRD may implement
  • I also checked the newer unstructured source. It does not look like a documented replacement for this behavior:

    • it is template-driven (--source=unstructured, --unstructured-resource=..., --fqdn-template, --target-template)
    • it is not a drop-in replacement for the old DNSEndpoint contract
    • no migration away from custom crd apiVersion/kind support is documented
  • A local fix branch restores the old behavior by:

    • keeping the typed/cache-backed path for the built-in externaldns.k8s.io/v1alpha1 DNSEndpoint
    • falling back to a dynamic REST/discovery-backed path when a custom CRD apiVersion/kind is configured

Environment:

  • External-DNS version (use external-dns --version):
    • broken: ExternalDNS/v20260406-v0.21.0
    • working: ExternalDNS/v20251114-v0.20.0
  • DNS provider:
    • Azure
  • Others:
    • working chart: external-dns-helm-chart-1.20.0
    • broken chart: external-dns-helm-chart-1.21.1
    • custom CRD settings in use:
      • --crd-source-apiversion=externaldns.nginx.org/v1
      • --crd-source-kind=DNSEndpoint

Checklist

  • I have searched existing issues and tried to find a fix myself
  • I am using the latest release,
    or have checked the staging image to confirm the bug is still reproducible
  • I have provided the actual process flags (not Helm values)
  • I have provided kubectl get <resource> -o yaml output including status
  • I have provided full external-dns debug logs
  • I have described what DNS records exist and what I expected

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind/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