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):
- 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>
- Create custom resources under that apiVersion/kind which implement the DNSEndpoint contract and previously produced DNS records on
v0.20.0.
- 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:
- 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
What happened:
external-dnsv0.21.0regressed thecrdsource and appears to ignore--crd-source-apiversion/--crd-source-kindfor custom CRDs implementing the DNSEndpoint contract.In our cluster, this worked with Helm chart
1.20.0(appv0.20.0) and stopped working with Helm chart1.21.1(appv0.21.0).The parsed config in both versions still shows:
and in the broken version also shows the custom CRD settings:
so this does not look like a
--sourceparsing issue. The regression appears to be in the CRD source implementation after flag parsing.What you expected to happen:
The
crdsource should continue to honor:--crd-source-apiversion--crd-source-kindfor custom CRDs implementing the DNSEndpoint contract, as documented in:
docs/sources/crd.mddocs/flags.mdand as observed in
v0.20.0.How to reproduce it (as minimally and precisely as possible):
external-dnswith a custom DNSEndpoint-style CRD, for example:v0.20.0.1.20.0/ appv0.20.01.21.1/ appv0.21.0Observed result:
v0.20.0: CRD-derived records are reconciled and written.v0.21.0: config still includesSources:[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-inexternaldns.k8s.io/v1alpha1DNSEndpoint.Anything else we need to know?:
This looks unintended rather than intentional:
#6312describes an internal migration to controller-runtime cache and does not mention removing support for custom CRD apiVersion/kind--crd-source-apiversionand--crd-source-kinddocs/sources/crd.mdstill says the CRD source works by specifying apiVersion and kindDNSEndpointas a contract that a user-specified CRD may implementI also checked the newer
unstructuredsource. It does not look like a documented replacement for this behavior:--source=unstructured,--unstructured-resource=...,--fqdn-template,--target-template)crdapiVersion/kind support is documentedA local fix branch restores the old behavior by:
externaldns.k8s.io/v1alpha1DNSEndpointEnvironment:
external-dns --version):ExternalDNS/v20260406-v0.21.0ExternalDNS/v20251114-v0.20.0external-dns-helm-chart-1.20.0external-dns-helm-chart-1.21.1--crd-source-apiversion=externaldns.nginx.org/v1--crd-source-kind=DNSEndpointChecklist
or have checked the staging image to confirm the bug is still reproducible
kubectl get <resource> -o yamloutput includingstatus