Skip to content

feat(source): add Nomad service #5284

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

kiurchv
Copy link

@kiurchv kiurchv commented Apr 14, 2025

Description

This PR introduces a new source for ExternalDNS: nomad-service.

The purpose of this source is to allow ExternalDNS to discover DNS endpoints from services registered in HashiCorp Nomad, a flexible workload orchestrator. This enables ExternalDNS users to manage DNS records for workloads orchestrated by Nomad using the same toolset they already use for Kubernetes and other platforms.

Nomad provides native service discovery and a metadata-rich API. This source leverages the service metadata—specifically, service tags—to configure DNS endpoints.

Example

Here's an example of a Nomad job that registers a service with DNS configuration:

job "whoami" {
  group "demo" {
    network {
      mode = "host"

      port "http" {
        static = 80
      }
    }

    service {
      name = "whoami-demo"
      port = "http"
      provider = "nomad"
      tags = [
        "external-dns.hostname=whoami.example.org.",
      ]
    }

    task "server" {
      driver = "docker"

      config {
        image = "traefik/whoami"
        ports = ["http"]
      }

      env {
        WHOAMI_PORT_NUMBER = "${NOMAD_PORT_http}"
      }
    }
  }
}

This job will result in ExternalDNS creating a DNS record for whoami.example.org. pointing to the service's IP address.

CLI Flags

The following optional command-line flags were introduced to configure the Nomad client used by the source:

--nomad-address=""             Nomad endpoint address. If empty, defaults to $NOMAD_ADDR or http://127.0.0.1:4646
--nomad-region=""              Nomad region to use. If not provided, the default agent region is used
--nomad-token=NOMAD-TOKEN      Nomad per-request ACL token
--nomad-wait-time=0s           WaitTime limits how long a Watch will block. If not provided, the agent default values will be used

Example Usage

To run ExternalDNS with the nomad-service source and an in-memory provider:

external-dns \
  --source=nomad-service \
  --provider=inmemory \
  --nomad-address=http://127.0.0.1:4646

Note on Nomad Tags vs Kubernetes Annotations

Nomad does not have annotations like Kubernetes, so ExternalDNS-specific configuration is done through service tags.

Unlike Kubernetes annotations, which are a key-value map, Nomad tags are represented as a flat array of strings. To work around this difference, the implementation expects tags to follow a key=value format under the external-dns. prefix.

For example:

tags = [
  "external-dns.hostname=example.nomad.internal.",
  "external-dns.ttl=300",
  "external-dns.controller=dns-controller",
  "external-dns.set-identifier=my-id"
]

Most of ExternalDNS annotations are supported via tags (e.g., hostname, TTL, target, etc.), provider-specific configuration is also supported.


This integration:

  • Provides a consistent developer experience across platforms like Kubernetes and Nomad
  • Enables automated DNS record management for Nomad-deployed services
  • Uses the pluggable ExternalDNS architecture to extend support to non-Kubernetes orchestrators

Checklist

  • Unit tests updated
  • End user documentation updated

Copy link

linux-foundation-easycla bot commented Apr 14, 2025

CLA Signed

The committers listed above are authorized under a signed CLA.

@k8s-ci-robot
Copy link
Contributor

[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 raffo for approval. For more information see the Code Review Process.

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

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

@k8s-ci-robot k8s-ci-robot added the cncf-cla: no Indicates the PR's author has not signed the CNCF CLA. label Apr 14, 2025
@k8s-ci-robot
Copy link
Contributor

Welcome @kiurchv!

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. 😃

@k8s-ci-robot k8s-ci-robot added the needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. label Apr 14, 2025
@k8s-ci-robot
Copy link
Contributor

Hi @kiurchv. 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.

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.

@k8s-ci-robot k8s-ci-robot added size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. 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 Apr 14, 2025
@ivankatliarchuk
Copy link
Contributor

Nomad is not a kubernetes source, it's completely different orchestrator/scheduler. Could you explain a little bit more how the integration suppose to work? And what is wrong with native Nomad + Consul DNS handling that is the reccomeded way of doing things on that platform?

@kiurchv
Copy link
Author

kiurchv commented Apr 14, 2025

@ivankatliarchuk Like a Kubernetes Nomad have similar services concept and similar to Kubernetes services each Nomad service points to a workload instance IP address. And since ExternalDNS architecture allows to implement any Source to be independent of Kubernetes cluster presence and run controller application in any orchestrator/scheduler setup I don't see any issues with running ExternalDNS inside Nomad cluster. There are already present CloudFoundry source which is using only CloudFoundry API and not depends on Kubernetes.

Historically Nomad has an integration with Consul service discovery (which allows to achieve service address resolution via DNS similar to Kubernetes internal DNS naming). Also, since version 1.3 Nomad has native service discovery mechanism, which enables service discovery via Nomad API (but not via DNS). Neither of these service discovery mechanisms address the problem which solves ExternalDNS.

There are similar solutions present such as nomad-external-dns and D53 but they are pretty limited in terms of feature set and provider support.

So my proposal to add a new source implementation to ExternalDNS seems like a shortest and unobtrusive way to bring such functionality to Nomad

@ivankatliarchuk
Copy link
Contributor

My concern isn't with Nomad itself, but whether it effectively serves our project's target audience. I have no opinion, opeartional support could be tricky as we are mainly kubernetes experts, but could be an interesting experiment.

@mloiseleur @Raffo @szuecs wdyt?

@mloiseleur
Copy link
Collaborator

@ivankatliarchuk Why not ? It's interesting to have alternatives.

@kiurchv First, thanks for this proposal.

Is this possible to strictly align current k8s annotations with nomad service tags ?

@kiurchv
Copy link
Author

kiurchv commented Apr 27, 2025

@mloiseleur Thanks for your attention.

Sure this is possible. Actually the current implementation with shortened annotation names was inspired by similar Traefik's Nomad service discovery integration: https://doc.traefik.io/traefik/routing/providers/nomad

So if we're using Traefik as load balancer in Nomad cluster such service configuration could look like this (example from the real Nomad job):

service {
  name = "whoami"
  port = "http"
  provider = "nomad"
  tags = [
    "external-dns.hostname=whoami.internal",
    "external-dns.target=${attr.unique.network.ip-address}",
    "traefik.enable=true",
    "traefik.http.routers.http.rule=Host(`whoami.internal`)",
  ]
}

@ivankatliarchuk
Copy link
Contributor

/ok-to-test

@k8s-ci-robot k8s-ci-robot added ok-to-test Indicates a non-member PR verified by an org member that is safe to test. needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. and removed needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. labels Apr 27, 2025
@ivankatliarchuk
Copy link
Contributor

/label tide/merge-method-squash

@k8s-ci-robot k8s-ci-robot added the tide/merge-method-squash Denotes a PR that should be squashed by tide when it merges. label Apr 27, 2025
@mloiseleur
Copy link
Collaborator

Actually the current implementation with shortened annotation names was inspired by similar Traefik's Nomad service discovery integration

Thanks, it's more clear. Maybe we will do the same for k8s annotations one day :).

Comment on lines 154 to 157
if mergedEndpoints[lastMergedEndpoint].DNSName == endpoints[i].DNSName &&
mergedEndpoints[lastMergedEndpoint].RecordType == endpoints[i].RecordType &&
mergedEndpoints[lastMergedEndpoint].RecordType == endpoint.RecordTypeCNAME {
Copy link
Collaborator

@mloiseleur mloiseleur Apr 29, 2025

Choose a reason for hiding this comment

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

Wdyt of put this into a func ? And use it in the if L144 ?

Copy link
Author

Choose a reason for hiding this comment

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

Good point! Actually this code was shamelessly copied from existing ServiceSource implementation, so I guess it will be better to move this whole sorting thing into own func too

}

func (ns *nomadServiceSource) AddEventHandler(ctx context.Context, handler func()) {
// TODO: Implement event listener logic
Copy link
Collaborator

Choose a reason for hiding this comment

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

Does that mean that it will work only for creation ? That delete / update / add of a nomad service won't be taken into account ?

Copy link
Author

@kiurchv kiurchv Apr 29, 2025

Choose a reason for hiding this comment

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

Any service changes will be taken into account since Endpoints method should return all actual endpoints from all present services and reconciling of next endpoints state etc happens outside of the Source scope.

Speaking of AddEventHandler method — it is used only when --events CLI flag is enabled and allows to subscribe to source changes and update endpoints accordingly in addition to default polling-based approach.
Actually Nomad itself provides such API which allows to subscribe to service changes and I'm planning to implement this method too

@mloiseleur
Copy link
Collaborator

mloiseleur commented May 10, 2025

This PR LGTM.

@kiurchv Do you think you can rebase this PR ?
We need one or two review and we should be good to go.

If this cannot make it for the release, I'm thinking about adding a line about this PR in order to find some interested nomad users to come and review this PR.

/retitle feat(source): add Nomad service

@k8s-ci-robot k8s-ci-robot changed the title Add Nomad Services as a Source feat(source): add Nomad service May 10, 2025
@k8s-ci-robot k8s-ci-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label May 10, 2025
@kiurchv
Copy link
Author

kiurchv commented May 10, 2025

@mloiseleur Done. Also, I've moved duplicated ServiceSource code into own function

@@ -384,3 +385,51 @@ func waitForDynamicCacheSync(ctx context.Context, factory dynamicInformerFactory
}
return nil
}

func mergeAndSortEndpoints(endpoints []*endpoint.Endpoint) []*endpoint.Endpoint {
Copy link
Contributor

Choose a reason for hiding this comment

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

Probably worth rewrite to a method comment

@@ -130,6 +135,10 @@ func NewSourceConfig(cfg *externaldns.Config) *Config {
TraefikDisableNew: cfg.TraefikDisableNew,
ExcludeUnschedulable: cfg.ExcludeUnschedulable,
ExposeInternalIPv6: cfg.ExposeInternalIPV6,
NomadAddress: cfg.NomadAddress,
Copy link
Contributor

Choose a reason for hiding this comment

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

Probably worth to create NomadConfig?


// NewNomadServiceSource creates a new nomadSource.
func NewNomadServiceSource(ctx context.Context, nomadClient *nomad.Client, namespace, fqdnTemplate string, combineFqdnAnnotation bool, ignoreHostnameAnnotation bool) (Source, error) {
tmpl, err := fqdn.ParseTemplate(fqdnTemplate)
Copy link
Contributor

Choose a reason for hiding this comment

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

We may need some examples for FQDN template, as not sure at the moment how it should work. Docs here http://github.com/kubernetes-sigs/external-dns/blob/master/docs/advanced/fqdn-templating.md. This could be added as follow up

external-dns \
--source=nomad-service \
--provider=inmemory \
--nomad-address=http://127.0.0.1:4646
Copy link
Contributor

Choose a reason for hiding this comment

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

Is nomad require no authentication? Any RBAC required to list services in namespace or in all namespaces?

// Flags related to Nomad
app.Flag("nomad-address", "Nomad endpoint address, if empty it defaults to NOMAD_ADDR or http://127.0.0.1:4646").Default(defaultConfig.NomadAddress).StringVar(&cfg.NomadAddress)
app.Flag("nomad-region", "Nomad region to use. If not provided, the default agent region is used").Default(defaultConfig.NomadRegion).StringVar(&cfg.NomadRegion)
// app.Flag("nomad-namespace", "Nomad namespace to use. If not provided the default namespace is used").Default(defaultConfig.NomadNamespace).StringVar(&cfg.NomadNamespace)
Copy link
Contributor

Choose a reason for hiding this comment

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

is this required? If not let's remove commented code

return endpoints, nil
}

func (sc *nomadServiceSource) setResourceLabel(namespace string, serviceName string, endpoints []*endpoint.Endpoint) {
Copy link
Contributor

Choose a reason for hiding this comment

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

receiver names are different, sc, ns etc

}

// Endpoints collects endpoints of all nested Sources and returns them in a single slice.
func (ns *nomadServiceSource) Endpoints(ctx context.Context) ([]*endpoint.Endpoint, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
func (ns *nomadServiceSource) Endpoints(ctx context.Context) ([]*endpoint.Endpoint, error) {
func (ns *nomadServiceSource) Endpoints(_ context.Context) ([]*endpoint.Endpoint, error) {

context not in use at the moment

return nil, err
}

endpoints := []*endpoint.Endpoint{}
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
endpoints := []*endpoint.Endpoint{}
var endpoints []*endpoint.Endpoint

emtpy slice declaration uses a literal. let's replace with nill slice declaration, we are going to enable linter when fixed everywhere

}

func (sc *nomadServiceSource) setResourceLabel(namespace string, serviceName string, endpoints []*endpoint.Endpoint) {
for _, ep := range endpoints {
Copy link
Contributor

Choose a reason for hiding this comment

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

label := fmt.Sprintf("service/%s/%s", namespace, serviceName)
for _, ep := range endpoints {
ep.Labels[endpoint.ResourceLabelKey] = label
}

return nil, fmt.Errorf("failed to apply template on service %s/%s: %w", obj.Namespace, obj.Name, err)
}
for _, name := range strings.Split(buf.String(), ",") {
name = strings.TrimFunc(name, unicode.IsSpace)
Copy link
Contributor

Choose a reason for hiding this comment

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

name = strings.TrimSuffix(strings.TrimSpace(name), ".")

return endpoints, nil
}

func (ns *nomadServiceSource) tagsToAnnotations(tags []string) map[string]string {
Copy link
Contributor

Choose a reason for hiding this comment

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

I wrote a simple test for this function, is the result correct

func TestTagsToAnnotations_Simple(t *testing.T) {
	ns := &nomadServiceSource{}
	tags := []string{
		"external-dns.foo=bar",
		"external-dns.ttl=60",
		"external-dns=controller",
		"invalid-tag",
		"external-dns.foo", // missing '='
	}
	expected := map[string]string{
		"external-dns.alpha.kubernetes.io/foo":          "bar",
		"external-dns.alpha.kubernetes.io/ttl":          "60",
		"external-dns.alpha.kubernetes.io/external-dns": "controller",
	}
	result := ns.tagsToAnnotations(tags)
	assert.Equal(t, expected, result)
}

@k8s-ci-robot k8s-ci-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label May 14, 2025
@k8s-ci-robot
Copy link
Contributor

PR needs rebase.

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.

JesusMtnez added a commit to JesusMtnez/homelab that referenced this pull request May 29, 2025
…o v0.17.0 (#712)

This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [registry.k8s.io/external-dns/external-dns](https://github.com/kubernetes-sigs/external-dns) | minor | `v0.16.1` -> `v0.17.0` |

---

### Release Notes

<details>
<summary>kubernetes-sigs/external-dns (registry.k8s.io/external-dns/external-dns)</summary>

### [`v0.17.0`](https://github.com/kubernetes-sigs/external-dns/releases/tag/v0.17.0)

[Compare Source](kubernetes-sigs/external-dns@v0.16.1...v0.17.0)

#### Global information

:information_source: On Pi Hole, support for v6 has been added. Pi Hole v5 support is deprecated and will be removed in a future version

:information_source: On OVH, the provider has been heavily rewritten. New ACLs are need. See documentation and PR [#&#8203;5143](kubernetes-sigs/external-dns#5143) for details.

:information_source: On IPv6, the [proposal 002](https://github.com/kubernetes-sigs/external-dns/blob/master/docs/proposal/002-internal-ipv6-handling-rollback.md) has been implemented, thanks to [@&#8203;hjoshi123](https://github.com/hjoshi123)

-   ⚠️ In the next release, the default of this new `expose-internal-ipv6` flag will be set to false

⚠️ There is a severe known issue with Active Directory ([#&#8203;5240](kubernetes-sigs/external-dns#5240)) since v0.16.0. PR to fix it ([#&#8203;5385](kubernetes-sigs/external-dns#5385)) is in review

:information_source: The legacy txt-format will be removed in the next minor version ([#&#8203;5172](kubernetes-sigs/external-dns#5172))

-   ⚠️ There is currently no migration script to clean old style txt records. If you need it, if you think you can do it, PRs are welcome.

ℹ️ A new Nomad source may be added to external-dns ([#&#8203;5284](kubernetes-sigs/external-dns#5284))

-   This PR can be merged only after a review and test from real Nomad users

#### 🚀 Features

-   feat: additional template functions by [@&#8203;matkam](https://github.com/matkam) in [#&#8203;3949](kubernetes-sigs/external-dns#3949)
-   feat(banner): standardize user agent and output by [@&#8203;ivankatliarchuk](https://github.com/ivankatliarchuk) in [#&#8203;5154](kubernetes-sigs/external-dns#5154)
-   feat(chart): Update image to v0.16.1 by [@&#8203;stevehipwell](https://github.com/stevehipwell) in [#&#8203;5201](kubernetes-sigs/external-dns#5201)
-   feat(cloudflare): multiple custom hostnames support by [@&#8203;mrozentsvayg](https://github.com/mrozentsvayg) in [#&#8203;5239](kubernetes-sigs/external-dns#5239)
-   feat(helm): allow extraArgs to also be a map enabling overrides of individual values by [@&#8203;frittentheke](https://github.com/frittentheke) in [#&#8203;5293](kubernetes-sigs/external-dns#5293)
-   feat: IDNA awareness in the zone finder by [@&#8203;lexisother](https://github.com/lexisother) in [#&#8203;5147](kubernetes-sigs/external-dns#5147)
-   feat(ovh): major rewriting of the provider by [@&#8203;rbeuque74](https://github.com/rbeuque74) in [#&#8203;5143](kubernetes-sigs/external-dns#5143)
-   feat(pihole): add optional support for v6 by [@&#8203;tJouve](https://github.com/tJouve) in [#&#8203;5226](kubernetes-sigs/external-dns#5226)
-   feat(pihole): add support for IPv6 Dual format by [@&#8203;tJouve](https://github.com/tJouve) in [#&#8203;5253](kubernetes-sigs/external-dns#5253)
-   feat(source): optional exclusion of unschedulable nodes by [@&#8203;Hayajiro](https://github.com/Hayajiro) in [#&#8203;5045](kubernetes-sigs/external-dns#5045)
-   feat(source): optional expose of nodes internal ipv6 by [@&#8203;hjoshi123](https://github.com/hjoshi123) in [#&#8203;5192](kubernetes-sigs/external-dns#5192)

#### 🐛 Bug fixes

-   fix(aws): typo on route53 IAM by [@&#8203;tico24](https://github.com/tico24) in [#&#8203;5197](kubernetes-sigs/external-dns#5197)
-   fix(chart): add missing types for empty values by [@&#8203;t3mi](https://github.com/t3mi) in [#&#8203;5207](kubernetes-sigs/external-dns#5207)
-   fix(cloudflare): custom hostnames edge-cases causing duplicates by [@&#8203;mrozentsvayg](https://github.com/mrozentsvayg) in [#&#8203;5183](kubernetes-sigs/external-dns#5183)
-   fix(cloudflare): regional hostnames by [@&#8203;vflaux](https://github.com/vflaux) in [#&#8203;5175](kubernetes-sigs/external-dns#5175)
-   fix(Gateway API): ensure generation match by [@&#8203;davidwin93](https://github.com/davidwin93) in [#&#8203;5241](kubernetes-sigs/external-dns#5241)
-   fix(gateway-api): ensure to use only latest generation with HTTPRoutes by [@&#8203;kashalls](https://github.com/kashalls) in [#&#8203;5349](kubernetes-sigs/external-dns#5349)
-   fix(helm): added missing schema values by [@&#8203;ivankatliarchuk](https://github.com/ivankatliarchuk) in [#&#8203;5228](kubernetes-sigs/external-dns#5228)
-   fix(helm): update helm schema by [@&#8203;semnell](https://github.com/semnell) in [#&#8203;5297](kubernetes-sigs/external-dns#5297)
-   fix(log testing): re-use logger library testing functionality by [@&#8203;ivankatliarchuk](https://github.com/ivankatliarchuk) in [#&#8203;5368](kubernetes-sigs/external-dns#5368)
-   fix(node): logger test fixed by [@&#8203;ivankatliarchuk](https://github.com/ivankatliarchuk) in [#&#8203;5232](kubernetes-sigs/external-dns#5232)
-   fix(ovh): handling capitalized DNS records + prevent panic by [@&#8203;rbeuque74](https://github.com/rbeuque74) in [#&#8203;5390](kubernetes-sigs/external-dns#5390)
-   fix(webhook): api json object plan.Changes case by [@&#8203;ivankatliarchuk](https://github.com/ivankatliarchuk) in [#&#8203;5355](kubernetes-sigs/external-dns#5355)
-   fix(zonefinder): handle underscores in dns records by [@&#8203;arthlr](https://github.com/arthlr) in [#&#8203;5281](kubernetes-sigs/external-dns#5281)

#### 📝 Documentation

-   docs(contributing): add conventional commits by [@&#8203;mloiseleur](https://github.com/mloiseleur) in [#&#8203;5333](kubernetes-sigs/external-dns#5333)
-   docs(proposal): externaldns api graduation to beta by [@&#8203;ivankatliarchuk](https://github.com/ivankatliarchuk) in [#&#8203;5079](kubernetes-sigs/external-dns#5079)
-   docs(rfc2136): fix env variable in the guideline by [@&#8203;riupie](https://github.com/riupie) in [#&#8203;5352](kubernetes-sigs/external-dns#5352)
-   docs(tutorials): add IONOS Cloud  setup tutorial for ExternalDNS by [@&#8203;smilutinovic-ionos](https://github.com/smilutinovic-ionos) in [#&#8203;5364](kubernetes-sigs/external-dns#5364)
-   docs(typo): grcp → grpc by [@&#8203;octo](https://github.com/octo) in [#&#8203;5231](kubernetes-sigs/external-dns#5231)
-   docs: update link to Anexia webhook provider by [@&#8203;mloiseleur](https://github.com/mloiseleur) in [#&#8203;5244](kubernetes-sigs/external-dns#5244)
-   docs: update rfc2136 by [@&#8203;BasJ93](https://github.com/BasJ93) in [#&#8203;5325](kubernetes-sigs/external-dns#5325)

#### 📦 Others

-   Add Yandex Cloud Webhook by [@&#8203;ismailbaskin](https://github.com/ismailbaskin) in [#&#8203;5190](kubernetes-sigs/external-dns#5190)
-   chore: add se for nlb, alb in thailand region by [@&#8203;xshot9011](https://github.com/xshot9011) in [#&#8203;5200](kubernetes-sigs/external-dns#5200)
-   chore: fix typo on txtOwnerId comment/description by [@&#8203;lanandra](https://github.com/lanandra) in [#&#8203;5351](kubernetes-sigs/external-dns#5351)
-   chore(ci): fix random data race failure on source/node test by [@&#8203;mloiseleur](https://github.com/mloiseleur) in [#&#8203;5268](kubernetes-sigs/external-dns#5268)
-   chore(ci): improve release script by [@&#8203;mloiseleur](https://github.com/mloiseleur) in [#&#8203;5394](kubernetes-sigs/external-dns#5394)
-   chore(ci): update linter to v2.0.2 by [@&#8203;mloiseleur](https://github.com/mloiseleur) in [#&#8203;5246](kubernetes-sigs/external-dns#5246)
-   chore(code-cleanup): move logic away from main.go add tests by [@&#8203;ivankatliarchuk](https://github.com/ivankatliarchuk) in [#&#8203;5222](kubernetes-sigs/external-dns#5222)
-   chore(code): improve some tests + re-order sources flags CLI by [@&#8203;mloiseleur](https://github.com/mloiseleur) in [#&#8203;5288](kubernetes-sigs/external-dns#5288)
-   chore(code-quality): added lint checks by [@&#8203;ivankatliarchuk](https://github.com/ivankatliarchuk) in [#&#8203;5318](kubernetes-sigs/external-dns#5318)
-   chore(code-quality): providers linter warnings fixes by [@&#8203;ivankatliarchuk](https://github.com/ivankatliarchuk) in [#&#8203;5320](kubernetes-sigs/external-dns#5320)
-   chore(code-quality): refactoring and linter fixes by [@&#8203;ivankatliarchuk](https://github.com/ivankatliarchuk) in [#&#8203;5374](kubernetes-sigs/external-dns#5374)
-   chore(code-quality): webhook increase code coverage by [@&#8203;ivankatliarchuk](https://github.com/ivankatliarchuk) in [#&#8203;5337](kubernetes-sigs/external-dns#5337)
-   chore(crd): use conventional paths and update controller-gen to v0.17.2 by [@&#8203;mloiseleur](https://github.com/mloiseleur) in [#&#8203;5287](kubernetes-sigs/external-dns#5287)
-   chore(dependencies): update toools versions by [@&#8203;ivankatliarchuk](https://github.com/ivankatliarchuk) in [#&#8203;5252](kubernetes-sigs/external-dns#5252)
-   chore(deps): build with go 1.24.2 by [@&#8203;mloiseleur](https://github.com/mloiseleur) in [#&#8203;5306](kubernetes-sigs/external-dns#5306)
-   chore(deps): bump renovatebot/github-action from 41.0.14 to 41.0.16 in the dev-dependencies group by [@&#8203;app/dependabot](https://github.com/app/dependabot) in [#&#8203;5188](kubernetes-sigs/external-dns#5188)
-   chore(deps): bump renovatebot/github-action from 41.0.16 to 41.0.17 in the dev-dependencies group by [@&#8203;app/dependabot](https://github.com/app/dependabot) in [#&#8203;5210](kubernetes-sigs/external-dns#5210)
-   chore(deps): bump the dev-dependencies group across 1 directory with 14 updates by [@&#8203;app/dependabot](https://github.com/app/dependabot) in [#&#8203;5346](kubernetes-sigs/external-dns#5346)
-   chore(deps): bump the dev-dependencies group across 1 directory with 14 updates by [@&#8203;app/dependabot](https://github.com/app/dependabot) in [#&#8203;5382](kubernetes-sigs/external-dns#5382)
-   chore(deps): bump the dev-dependencies group across 1 directory with 17 updates by [@&#8203;app/dependabot](https://github.com/app/dependabot) in [#&#8203;5238](kubernetes-sigs/external-dns#5238)
-   chore(deps): bump the dev-dependencies group across 1 directory with 19 updates by [@&#8203;app/dependabot](https://github.com/app/dependabot) in [#&#8203;5262](kubernetes-sigs/external-dns#5262)
-   chore(deps): bump the dev-dependencies group across 1 directory with 20 updates by [@&#8203;app/dependabot](https://github.com/app/dependabot) in [#&#8203;5211](kubernetes-sigs/external-dns#5211)
-   chore(deps): bump the dev-dependencies group across 1 directory with 21 updates by [@&#8203;mloiseleur](https://github.com/mloiseleur) in [#&#8203;5313](kubernetes-sigs/external-dns#5313)
-   chore(deps): bump the dev-dependencies group across 1 directory with 2 updates by [@&#8203;app/dependabot](https://github.com/app/dependabot) in [#&#8203;5247](kubernetes-sigs/external-dns#5247)
-   chore(deps): bump the dev-dependencies group across 1 directory with 2 updates by [@&#8203;app/dependabot](https://github.com/app/dependabot) in [#&#8203;5301](kubernetes-sigs/external-dns#5301)
-   chore(deps): bump the dev-dependencies group across 1 directory with 2 updates by [@&#8203;app/dependabot](https://github.com/app/dependabot) in [#&#8203;5323](kubernetes-sigs/external-dns#5323)
-   chore(deps): code cleanup, pkg/errors is archived by [@&#8203;ivankatliarchuk](https://github.com/ivankatliarchuk) in [#&#8203;5335](kubernetes-sigs/external-dns#5335)
-   chore(deps): switch to goccy yaml by [@&#8203;Raffo](https://github.com/Raffo) in [#&#8203;5292](kubernetes-sigs/external-dns#5292)
-   chore(deps): update linter to v2.1.x by [@&#8203;mloiseleur](https://github.com/mloiseleur) in [#&#8203;5366](kubernetes-sigs/external-dns#5366)
-   chore(fqdn-template): fqdn templating move to specific folder and update documentation by [@&#8203;ivankatliarchuk](https://github.com/ivankatliarchuk) in [#&#8203;5354](kubernetes-sigs/external-dns#5354)
-   chore(github): add a release template by [@&#8203;ivankatliarchuk](https://github.com/ivankatliarchuk) in [#&#8203;5324](kubernetes-sigs/external-dns#5324)
-   chore(helm): add validation for prefix and suffix and capture regression by [@&#8203;ivankatliarchuk](https://github.com/ivankatliarchuk) in [#&#8203;5250](kubernetes-sigs/external-dns#5250)
-   chore(openstack designate)!: remove in-tree provider by [@&#8203;mloiseleur](https://github.com/mloiseleur) in [#&#8203;5126](kubernetes-sigs/external-dns#5126)
-   chore(providers): rename custom TTL constants to defaultTTL by [@&#8203;ivankatliarchuk](https://github.com/ivankatliarchuk) in [#&#8203;5312](kubernetes-sigs/external-dns#5312)
-   chore: Release Helm chart v1.16.1 by [@&#8203;stevehipwell](https://github.com/stevehipwell) in [#&#8203;5270](kubernetes-sigs/external-dns#5270)
-   chore(release): updates kustomize & docs with v0.16.1 by [@&#8203;mloiseleur](https://github.com/mloiseleur) in [#&#8203;5184](kubernetes-sigs/external-dns#5184)
-   chore(source): code cleanup by [@&#8203;ivankatliarchuk](https://github.com/ivankatliarchuk) in [#&#8203;5304](kubernetes-sigs/external-dns#5304)
-   chore(webhook): bump cenkalti/backoff version by [@&#8203;ivankatliarchuk](https://github.com/ivankatliarchuk) in [#&#8203;5342](kubernetes-sigs/external-dns#5342)
-   test: add tests for cloudflare provider by [@&#8203;natitomattis](https://github.com/natitomattis) in [#&#8203;5248](kubernetes-sigs/external-dns#5248)
-   test(log): execute on multiple platforms by [@&#8203;ivankatliarchuk](https://github.com/ivankatliarchuk) in [#&#8203;5370](kubernetes-sigs/external-dns#5370)
-   test(log): fix random race detection by [@&#8203;ivankatliarchuk](https://github.com/ivankatliarchuk) in [#&#8203;5273](kubernetes-sigs/external-dns#5273)
-   test(source): cover unhappy paths by [@&#8203;linoleparquet](https://github.com/linoleparquet) in [#&#8203;5369](kubernetes-sigs/external-dns#5369)
-   test(source): fix data race on node_test by [@&#8203;mloiseleur](https://github.com/mloiseleur) in [#&#8203;5334](kubernetes-sigs/external-dns#5334)
-   test(source/pod): improve code coverage by [@&#8203;ivankatliarchuk](https://github.com/ivankatliarchuk) in [#&#8203;5378](kubernetes-sigs/external-dns#5378)
-   test(tlsconfig): add unit tests by [@&#8203;linoleparquet](https://github.com/linoleparquet) in [#&#8203;5381](kubernetes-sigs/external-dns#5381)
-   test(zone_filter): improve coverage from 66.7% to 100% by [@&#8203;upsaurav12](https://github.com/upsaurav12) in [#&#8203;5388](kubernetes-sigs/external-dns#5388)

#### 📦 Docker Image

    docker pull registry.k8s.io/external-dns/external-dns:v0.17.0

#### New Contributors

-   [@&#8203;ismailbaskin](https://github.com/ismailbaskin) made their first contribution in kubernetes-sigs/external-dns#5190
-   [@&#8203;lexisother](https://github.com/lexisother) made their first contribution in kubernetes-sigs/external-dns#5147
-   [@&#8203;tico24](https://github.com/tico24) made their first contribution in kubernetes-sigs/external-dns#5197
-   [@&#8203;t3mi](https://github.com/t3mi) made their first contribution in kubernetes-sigs/external-dns#5207
-   [@&#8203;octo](https://github.com/octo) made their first contribution in kubernetes-sigs/external-dns#5231
-   [@&#8203;xshot9011](https://github.com/xshot9011) made their first contribution in kubernetes-sigs/external-dns#5200
-   [@&#8203;tJouve](https://github.com/tJouve) made their first contribution in kubernetes-sigs/external-dns#5226
-   [@&#8203;Hayajiro](https://github.com/Hayajiro) made their first contribution in kubernetes-sigs/external-dns#5045
-   [@&#8203;davidwin93](https://github.com/davidwin93) made their first contribution in kubernetes-sigs/external-dns#5241
-   [@&#8203;vflaux](https://github.com/vflaux) made their first contribution in kubernetes-sigs/external-dns#5175
-   [@&#8203;arthlr](https://github.com/arthlr) made their first contribution in kubernetes-sigs/external-dns#5281
-   [@&#8203;semnell](https://github.com/semnell) made their first contribution in kubernetes-sigs/external-dns#5297
-   [@&#8203;BasJ93](https://github.com/BasJ93) made their first contribution in kubernetes-sigs/external-dns#5325
-   [@&#8203;natitomattis](https://github.com/natitomattis) made their first contribution in kubernetes-sigs/external-dns#5248
-   [@&#8203;riupie](https://github.com/riupie) made their first contribution in kubernetes-sigs/external-dns#5352
-   [@&#8203;lanandra](https://github.com/lanandra) made their first contribution in kubernetes-sigs/external-dns#5351
-   [@&#8203;smilutinovic-ionos](https://github.com/smilutinovic-ionos) made their first contribution in kubernetes-sigs/external-dns#5364
-   [@&#8203;linoleparquet](https://github.com/linoleparquet) made their first contribution in kubernetes-sigs/external-dns#5369
-   [@&#8203;kashalls](https://github.com/kashalls) made their first contribution in kubernetes-sigs/external-dns#5349
-   [@&#8203;matkam](https://github.com/matkam) made their first contribution in kubernetes-sigs/external-dns#3949
-   [@&#8203;upsaurav12](https://github.com/upsaurav12) made their first contribution in kubernetes-sigs/external-dns#5388

**Full Changelog**: kubernetes-sigs/external-dns@v0.16.1...v0.17.0

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MC4xMS4xNSIsInVwZGF0ZWRJblZlciI6IjQwLjExLjE1IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJkZXAvbWlub3IiXX0=-->

Co-authored-by: JesusMtnez <[email protected]>
Reviewed-on: https://codeberg.org/JesusMtnez/homelab/pulls/712
Co-authored-by: JesusMtnez-bot <[email protected]>
Co-committed-by: JesusMtnez-bot <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. ok-to-test Indicates a non-member PR verified by an org member that is safe to test. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. tide/merge-method-squash Denotes a PR that should be squashed by tide when it merges.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants