Skip to content

CRD Source

CRD source provides a generic mechanism to manage DNS records in your favourite DNS provider supported by external-dns.


CRD source watches for a user specified CRD to extract Endpoints from its Spec.
So users need to create such a CRD and register it to the kubernetes cluster and then create new object(s) of the CRD specifying the Endpoints.

Registering CRD

Here is typical example of CRD API type which provides Endpoints to CRD source:

type TTL int64
type Targets []string
type ProviderSpecificProperty struct {
    Name  string `json:"name,omitempty"`
    Value string `json:"value,omitempty"`
type ProviderSpecific []ProviderSpecificProperty
type Labels map[string]string

type Endpoint struct {
    // The hostname of the DNS record
    DNSName string `json:"dnsName,omitempty"`
    // The targets the DNS record points to
    Targets Targets `json:"targets,omitempty"`
    // RecordType type of record, e.g. CNAME, A, SRV, TXT etc
    RecordType string `json:"recordType,omitempty"`
    // TTL for the record
    RecordTTL TTL `json:"recordTTL,omitempty"`
    // Labels stores labels defined for the Endpoint
    // +optional
    Labels Labels `json:"labels,omitempty"`
    // ProviderSpecific stores provider specific config
    // +optional
    ProviderSpecific ProviderSpecific `json:"providerSpecific,omitempty"`

type DNSEndpointSpec struct {
    Endpoints []*Endpoint `json:"endpoints,omitempty"`

type DNSEndpointStatus struct {
    // The generation observed by the external-dns controller.
    // +optional
    ObservedGeneration int64 `json:"observedGeneration,omitempty"`

// +genclient

// DNSEndpoint is the CRD wrapper for Endpoint
// +k8s:openapi-gen=true
// +kubebuilder:resource:path=dnsendpoints
// +kubebuilder:subresource:status
type DNSEndpoint struct {
    metav1.TypeMeta   `json:",inline"`
    metav1.ObjectMeta `json:"metadata,omitempty"`

    Spec   DNSEndpointSpec   `json:"spec,omitempty"`
    Status DNSEndpointStatus `json:"status,omitempty"`

Refer to kubebuilder to create and register the CRD.


One can use CRD source by specifying --source flag with crd and specifying the ApiVersion and Kind of the CRD with --crd-source-apiversion and crd-source-kind respectively.
for e.g:

$ build/external-dns --source crd --crd-source-apiversion  --crd-source-kind DNSEndpoint --provider inmemory --once --dry-run

Creating DNS Records

Create the objects of CRD type by filling in the fields of CRD and DNS record would be created accordingly.


Here is an example CRD manifest generated by kubebuilder.
Apply this to register the CRD

$ kubectl apply --validate=false -f docs/contributing/crd-source/crd-manifest.yaml "" created

Then you can create the dns-endpoint yaml similar to dnsendpoint-example

$ kubectl apply -f docs/contributing/crd-source/dnsendpoint-example.yaml "examplednsrecord" created

Run external-dns in dry-mode to see whether external-dns picks up the DNS record from CRD.

$ build/external-dns --source crd --crd-source-apiversion  --crd-source-kind DNSEndpoint --provider inmemory --once --dry-run
INFO[0000] running in dry-run mode. No changes to DNS records will be made.
INFO[0000] Connected to cluster at
INFO[0000] CREATE: 180 IN A
INFO[0000] CREATE: 0 IN TXT "heritage=external-dns,external-dns/owner=default"

RBAC configuration

If you use RBAC, extend the external-dns ClusterRole with:

- apiGroups: [""]
  resources: ["dnsendpoints"]
  verbs: ["get","watch","list"]
- apiGroups: [""]
  resources: ["dnsendpoints/status"]
  verbs: ["*"]

Last update: March 6, 2023
Back to top