Configure external DNS servers (AWS Route53, Google CloudDNS and others) for Kubernetes Ingresses and Services
Go Makefile
Clone or download
njuettner Merge pull request #624 from nenadilic84/patch-1
Update DO CNAME type API request to prevent error 422
Latest commit b9f7dd8 Jul 19, 2018
Failed to load latest commit information.
controller use ticker (#553) May 15, 2018
docs added list nodes Jul 13, 2018
endpoint Add support for NodePort services (#559) Jun 14, 2018
img Add Logo for ExternalDNS (#313) Aug 16, 2017
internal Adds TLS flags for pdns provider Jun 19, 2018
pkg fix tests Jul 12, 2018
plan chore Jun 20, 2018
provider Merge pull request #624 from nenadilic84/patch-1 Jul 19, 2018
registry Only store endpoints with their labels in the cache (#612) Jun 28, 2018
source formatting (gofmt -s -w ./source/ingress_test.go) Jun 21, 2018
.gitignore Using dep in travis to ensure all dependencies are installed (#471) Feb 21, 2018
.travis.yml Remove sed deadline from travis.yml (#621) Jul 2, 2018
.zappr.yaml chore: add zappr file in order to push to pierone (#279) Jul 18, 2017 Update Jul 6, 2018 Follow CLA doc to kubernetes/community (#432) Jan 5, 2018
Dockerfile Always build against latest stable version of golang Mar 16, 2018
Gopkg.lock exoscale: fix boilerplate header Jul 12, 2018
Gopkg.toml Merge branch 'master' into external-dns-exoscale Jul 12, 2018
LICENSE Initial commit Feb 9, 2017
Makefile Fix docker build and delete vendor files which were not deleted (#473) Feb 22, 2018
OWNERS Fix docker build and delete vendor files which were not deleted (#473) Feb 22, 2018 Merge branch 'master' into external-dns-exoscale Jul 12, 2018 Update (#426) Dec 21, 2017
delivery.yaml Only store endpoints with their labels in the cache (#612) Jun 28, 2018
main.go Merge branch 'master' into external-dns-exoscale Jul 12, 2018



Build Status Coverage Status GitHub release go-doc Go Report Card

ExternalDNS synchronizes exposed Kubernetes Services and Ingresses with DNS providers.

What It Does

Inspired by Kubernetes DNS, Kubernetes' cluster-internal DNS server, ExternalDNS makes Kubernetes resources discoverable via public DNS servers. Like KubeDNS, it retrieves a list of resources (Services, Ingresses, etc.) from the Kubernetes API to determine a desired list of DNS records. Unlike KubeDNS, however, it's not a DNS server itself, but merely configures other DNS providers accordingly—e.g. AWS Route 53 or Google CloudDNS.

In a broader sense, ExternalDNS allows you to control DNS records dynamically via Kubernetes resources in a DNS provider-agnostic way.

The FAQ contains additional information and addresses several questions about key concepts of ExternalDNS.

To see ExternalDNS in action, have a look at this video.

The Latest Release: v0.5

ExternalDNS' current release is v0.5. This version allows you to keep selected zones (via --domain-filter) synchronized with Ingresses and Services of type=LoadBalancer in various cloud providers:

From this release, ExternalDNS can become aware of the records it is managing (enabled via --registry=txt), therefore ExternalDNS can safely manage non-empty hosted zones. We strongly encourage you to use v0.5 (or greater) with --registry=txt enabled and --txt-owner-id set to a unique value that doesn't change for the lifetime of your cluster. You might also want to run ExternalDNS in a dry run mode (--dry-run flag) to see the changes to be submitted to your DNS Provider API.

Note that all flags can be replaced with environment variables; for instance, --dry-run could be replaced with EXTERNAL_DNS_DRY_RUN=1, or --registry txt could be replaced with EXTERNAL_DNS_REGISTRY=txt.

Deploying to a Cluster

The following tutorials are provided:

Running Locally

Technical Requirements

Make sure you have the following prerequisites:

  • A local Go 1.7+ development environment.
  • Access to a Google/AWS account with the DNS API enabled.
  • Access to a Kubernetes cluster that supports exposing Services, e.g. GKE.

Setup Steps

First, get ExternalDNS:

To install all dependencies, make sure to install dep first.

$ git clone && cd external-dns
$ dep ensure -vendor-only
$ make

This will create external-dns in the build directory directly from master.

Next, run an application and expose it via a Kubernetes Service:

$ kubectl run nginx --image=nginx --replicas=1 --port=80
$ kubectl expose deployment nginx --port=80 --target-port=80 --type=LoadBalancer

Annotate the Service with your desired external DNS name. Make sure to change to your domain.

$ kubectl annotate service nginx ""

Optionally, you can customize the TTL value of the resulting DNS record by using the annotation:

$ kubectl annotate service nginx ""

For more details on configuring TTL, see here.

Locally run a single sync loop of ExternalDNS.

$ external-dns --registry txt --txt-owner-id my-cluster-id --provider google --google-project example-project --source service --once --dry-run

This should output the DNS records it will modify to match the managed zone with the DNS records you desire. Note TXT records having my-cluster-id value embedded. Those are used to ensure that ExternalDNS is aware of the records it manages.

Once you're satisfied with the result, you can run ExternalDNS like you would run it in your cluster: as a control loop, and not in dry-run mode:

$ external-dns --registry txt --txt-owner-id my-cluster-id --provider google --google-project example-project --source service

Check that ExternalDNS has created the desired DNS record for your Service and that it points to its load balancer's IP. Then try to resolve it:

$ dig +short

Now you can experiment and watch how ExternalDNS makes sure that your DNS records are configured as desired. Here are a couple of things you can try out:

  • Change the desired hostname by modifying the Service's annotation.
  • Recreate the Service and see that the DNS record will be updated to point to the new load balancer IP.
  • Add another Service to create more DNS records.
  • Remove Services to clean up your managed zone.

The tutorials section contains examples, including Ingress resources, and shows you how to set up ExternalDNS in different environments such as other cloud providers and alternative Ingress controllers.


If using a txt registry and attempting to use a CNAME the --txt-prefix must be set to avoid conflicts. Changing --txt-prefix will result in lost ownership over previously created records.


ExternalDNS was built with extensibility in mind. Adding and experimenting with new DNS providers and sources of desired DNS records should be as easy as possible. It should also be possible to modify how ExternalDNS behaves—e.g. whether it should add records but never delete them.

Here's a rough outline on what is to come (subject to change):


  • Support for Google CloudDNS
  • Support for Kubernetes Services


  • Support for AWS Route 53
  • Support for Kubernetes Ingresses


  • Support for AWS Route 53 via ALIAS
  • Support for multiple zones
  • Ownership System


  • Support for AzureDNS
  • Support for CloudFlare
  • Support for DigitalOcean
  • Multiple DNS names per Service

v0.5 - current version

  • Support for creating DNS records to multiple targets (for Google and AWS)
  • Support for OpenStack Designate
  • Support for PowerDNS


  • Ability to replace Kops' DNS Controller (This could also directly become v1.0)


Yet to be defined

  • Support for CoreDNS
  • Support for record weights
  • Support for different behavioral policies
  • Support for Services with type=NodePort
  • Support for CRDs
  • Support for more advanced DNS record configurations

Have a look at the milestones to get an idea of where we currently stand.


We encourage you to get involved with ExternalDNS, as users, contributors or as new maintainers that can take over some parts like different providers and help with code reviews.

Providers which currently need maintainers:

  • Azure
  • Cloudflare
  • Digital Ocean
  • Google Cloud Platform

Any provider should have at least one maintainer. It would be nice if you run it in production, but it is not required. You should check changes and make sure your provider is working correctly.

It would be also great to have an automated end-to-end test for different cloud providers, so help from Kubernetes maintainers and their idea on how this can be done would be valuable.

Read the contributing guidelines and have a look at the contributing docs to learn about building the project, the project structure, and the purpose of each package.

If you are interested please reach out to us on the Kubernetes slack in the #external-dns channel.

For an overview on how to write new Sources and Providers check out Sources and Providers.


ExternalDNS is an effort to unify the following similar projects in order to bring the Kubernetes community an easy and predictable way of managing DNS records across cloud providers based on their Kubernetes resources:

Kubernetes Incubator

This is a Kubernetes Incubator project. The project was established 2017-Feb-9 (initial announcement here). The incubator team for the project is:

  • Sponsor: sig-network
  • Champion: Tim Hockin (@thockin)
  • SIG: sig-network

For more information about sig-network, such as meeting times and agenda, check out the community site.

Code of conduct

Participation in the Kubernetes community is governed by the Kubernetes Code of Conduct.