ExternalDNS supports swapping out endpoint sources and DNS providers and both sides are pluggable. There currently exist three sources and four provider implementations.
Sources are an abstraction over any kind of source of desired Endpoints, e.g.:
- a list of Service objects from Kubernetes
- a random list for testing purposes
- an aggregated list of multiple nested sources
The Source
interface has a single method called Endpoints
that should return all desired Endpoint objects as a flat list.
type Source interface {
Endpoints() ([]*endpoint.Endpoint, error)
}
All sources live in package source
.
ServiceSource
: collects all Services that have an external IP and returns them as Endpoint objects. The desired DNS name corresponds to an annotation set on the Service or is compiled from the Service attributes via the FQDN Go template string.IngressSource
: collects all Ingresses that have an external IP and returns them as Endpoint objects. The desired DNS name corresponds to the host rules defined in the Ingress object.IstioGatewaySource
: collects all Istio Gateways and returns them as Endpoint objects. The desired DNS name corresponds to the hosts listed within the servers spec of each Gateway object.FakeSource
: returns a random list of Endpoints for the purpose of testing providers without having access to a Kubernetes cluster.ConnectorSource
: returns a list of Endpoint objects which are served by a tcp server configured throughconnector-source-server
flag.CRDSource
: returns a list of Endpoint objects sourced from the spec of CRD objects. For more details refer to CRD source documentation.EmptySource
: returns an empty list of Endpoint objects for the purpose of testing and cleaning out entries.
Providers are an abstraction over any kind of sink for desired Endpoints, e.g.:
- storing them in Google Cloud DNS
- printing them to stdout for testing purposes
- fanning out to multiple nested providers
The Provider
interface has two methods: Records
and ApplyChanges
. Records
should return all currently existing DNS records converted to Endpoint objects as a flat list. Upon receiving a change set (via an object of plan.Changes
), ApplyChanges
should translate these to the provider specific actions in order to persist them in the provider's storage.
type Provider interface {
Records() ([]*endpoint.Endpoint, error)
ApplyChanges(changes *plan.Changes) error
}
The interface tries to be generic and assumes a flat list of records for both functions. However, many providers scope records into zones. Therefore, the provider implementation has to do some extra work to return that flat list. For instance, the AWS provider fetches the list of all hosted zones before it can return or apply the list of records. If the provider has no concept of zones or if it makes sense to cache the list of hosted zones it is happily allowed to do so. Furthermore, the provider should respect the --domain-filter
flag to limit the affected records by a domain suffix. For instance, the AWS provider filters out all hosted zones that doesn't match that domain filter.
All providers live in package provider
.
GoogleProvider
: returns and creates DNS records in Google Cloud DNSAWSProvider
: returns and creates DNS records in AWS Route 53AzureProvider
: returns and creates DNS records in Azure DNSInMemoryProvider
: Keeps a list of records in local memory
You can choose any combination of sources and providers on the command line. Given a cluster on AWS you would most likely want to use the Service and Ingress Source in combination with the AWS provider. Service
+ InMemory
is useful for testing your service collecting functionality, whereas Fake
+ Google
is useful for testing that the Google provider behaves correctly, etc.